Skip to content

Commit

Permalink
Fix ltc decode segwit (#8)
Browse files Browse the repository at this point in the history
* create locking scripts for bech32 properly
  • Loading branch information
vladmelnyk authored Dec 29, 2020
1 parent 45250de commit b2fa776
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 36 deletions.
4 changes: 2 additions & 2 deletions src/main/java/sd/fomin/gerbera/transaction/RegularOutput.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ class RegularOutput extends Output {
@Override
protected byte[] getLockingScript() {
return isBech32
? ScriptPubKeyProducer.getInstance(mainNet, coin, decodedAddress[0]).produceScript(decodedAddress)
: ScriptPubKeyProducer.getInstance(mainNet, coin, decodedAddress[0])
? ScriptPubKeyProducer.getInstance(mainNet, coin, decodedAddress[0], true).produceScript(decodedAddress)
: ScriptPubKeyProducer.getInstance(mainNet, coin, decodedAddress[0], false)
.produceScript(Arrays.copyOfRange(decodedAddress, 1, decodedAddress.length));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package sd.fomin.gerbera.transaction;

import sd.fomin.gerbera.constant.ErrorMessages;
import sd.fomin.gerbera.constant.OpCodes;
import sd.fomin.gerbera.types.Coin;
import sd.fomin.gerbera.types.OpSize;
Expand All @@ -14,7 +15,7 @@ public interface ScriptPubKeyProducer {

byte[] produceScript(byte[] hash);

static ScriptPubKeyProducer getInstance(boolean mainNet, Coin coin, byte prefix) {
static ScriptPubKeyProducer getInstance(boolean mainNet, Coin coin, byte prefix, boolean isBech32) {
List<Byte> prefixesP2PKHMainnet;
List<Byte> prefixesP2PKHTestnet;
List<Byte> prefixesP2SHMainnet;
Expand All @@ -28,15 +29,25 @@ static ScriptPubKeyProducer getInstance(boolean mainNet, Coin coin, byte prefix)
prefixesP2SHTestnet = singletonList((byte) 0xC4);
break;
case LTC:
prefixesP2PKHMainnet = singletonList((byte) 0x30);
prefixesP2PKHMainnet = asList((byte) 0x30, (byte) 0x00);
prefixesP2PKHTestnet = singletonList((byte) 0x6F);
prefixesP2SHMainnet = asList((byte) 0x05, (byte) 0x32);
prefixesP2SHTestnet = singletonList((byte) 0xC4);
break;
default:
throw new IllegalStateException("Unexpected value: " + coin);
}
if ((mainNet ? prefixesP2PKHMainnet : prefixesP2PKHTestnet).contains(prefix)) {
if (isBech32) {
//P2WSH & P2WKH
return hash -> {
ByteBuffer lockingScript = new ByteBuffer();
lockingScript.append(OpCodes.FALSE);
lockingScript.append(OpSize.ofInt(hash.length).getSize());
lockingScript.append(hash);

return lockingScript.bytes();
};
} else if ((mainNet ? prefixesP2PKHMainnet : prefixesP2PKHTestnet).contains(prefix)) {
//P2PKH
return hash -> {
ByteBuffer lockingScript = new ByteBuffer();
Expand All @@ -58,18 +69,9 @@ static ScriptPubKeyProducer getInstance(boolean mainNet, Coin coin, byte prefix)
};
//TODO Provide appropriate condition to verify P2WSH
} else {
//P2WSH & P2WKH
return hash -> {
ByteBuffer lockingScript = new ByteBuffer();
lockingScript.append(OpCodes.FALSE);
lockingScript.append(OpSize.ofInt(hash.length).getSize());
lockingScript.append(hash);

return lockingScript.bytes();
};
throw new IllegalArgumentException(String.format(ErrorMessages.SPK_UNSUPPORTED_PRODUCER, mainNet, prefix));
}

// throw new IllegalArgumentException(String.format(ErrorMessages.SPK_UNSUPPORTED_PRODUCER, mainNet, prefix));
}

}
Expand Down
15 changes: 3 additions & 12 deletions src/test/java/sd/fomin/gerbera/RawTransactionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,7 @@ public void testFullMainnet() {

@Test
public void testFullMainnetLTC() {
String expectedRaw = "0100000001033f2e5cc2ad25e4106d0289928ee5bd796380522baeb81de" +
"36f47ff3edf2237010000006a4730440220080a8e8dbf870a060daad725" +
"e79a79700e6bcf7f282d98f837cc94ebdd58111f02200948d3f7ea30ac0c2" +
"454f10a2c39cbdc9fdb2f9a13f426e0b82cc6a526782223012102ca686617da" +
"4a3fd7a3a8863311541a2e162e5d8da90aac6d73667dd1befec119ffffffff0" +
"550c30000000000001976a9146a9a23662de8a1db8c11c8730c9b03de1ef17bf" +
"688ac1405000000000000160014a5205449ab6df718521cf72b0b311dd7f38de" +
"cd6780500000000000017a914d8b83ad7bf8795b9ff61464fcf06f156c28e3e1f87" +
"50c300000000000017a914d8b83ad7bf8795b9ff61464fcf06f156c28e3e1f8712c" +
"3f802000000001600144747e8746cddb33b0f7f95a90f89f89fb387cbb600000000";
String expectedRaw = "0100000001033f2e5cc2ad25e4106d0289928ee5bd796380522baeb81de36f47ff3edf2237010000006b483045022100832f9cba48483a812c1eeccb5e7d80d60bdb1425a19a3d24e18f9a10ba6c1213022078f8d4897eed8ff440eac8aadf4ca8743517fbbc8d5d7d900abc5c39e02337ef012102ca686617da4a3fd7a3a8863311541a2e162e5d8da90aac6d73667dd1befec119ffffffff0550c30000000000001976a9146a9a23662de8a1db8c11c8730c9b03de1ef17bf688acd20400000000000017a914c74582228bcb0840b771ddd6fa0413fde1432dde871405000000000000160014a5205449ab6df718521cf72b0b311dd7f38decd640060000000000001600143014bcd20e0b4d58869d1f950f4016430489ed7bc880f902000000001976a9144747e8746cddb33b0f7f95a90f89f89fb387cbb688ac00000000";

TransactionBuilder builder = TransactionBuilder.create(true, LTC)
.from(
Expand All @@ -106,9 +97,9 @@ public void testFullMainnetLTC() {
"TB6ioeJEF2qdXKpzPrPLkQuZRXiJzB1JWu2QmquNTj4gPU76gnxa"
)
.to("LUwcYGAm7nhZB3TrEpk3GknMokxa7DWkah", 50000)
.to("MS4oy8QgbCwxUHvCkouyPdzspxtkiG1Rjs", 1234)
.to("ltc1q55s9gjdtdhm3s5su7u4skvga6lecmmxkgg44tk", 1300)
.to("3MSvaVbVFFLML86rt5eqgA9SvW23upaXdY", 1400)
.to("MTf4tP1TCNBn8dNkyxeBVoPrFCcVzxJvvh", 50000)
.to("ltc1qxq2te5swpdx43p5ar72s7sqkgvzgnmtmtfecms", 1600)
.withFee(40002)
.changeTo("17Vu7st1U1KwymUKU4jJheHHGRVNqrcfLD");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,71 +10,71 @@ public class ScriptPubKeyProducerTest {

@Test
public void testP2PKHMainNet() {
byte[] script = ScriptPubKeyProducer.getInstance(true, Coin.BTC, (byte) 0x00)
byte[] script = ScriptPubKeyProducer.getInstance(true, Coin.BTC, (byte) 0x00, false)
.produceScript(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04});
String expectedScript = "76" + "A9" + "05" + "0001020304" + "88" + "AC";
assertThat(script).isEqualTo(HexUtils.asBytes(expectedScript));
}

@Test
public void testP2PKHTestNet() {
byte[] script = ScriptPubKeyProducer.getInstance(false, Coin.BTC, (byte) 0x6F)
byte[] script = ScriptPubKeyProducer.getInstance(false, Coin.BTC, (byte) 0x6F, false)
.produceScript(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04});
String expectedScript = "76" + "A9" + "05" + "0001020304" + "88" + "AC";
assertThat(script).isEqualTo(HexUtils.asBytes(expectedScript));
}

@Test
public void testP2SHMainNet() {
byte[] script = ScriptPubKeyProducer.getInstance(true, Coin.BTC, (byte) 0x05)
byte[] script = ScriptPubKeyProducer.getInstance(true, Coin.BTC, (byte) 0x05, false)
.produceScript(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04});
String expectedScript = "A9" + "05" + "0001020304" + "87";
assertThat(script).isEqualTo(HexUtils.asBytes(expectedScript));
}

@Test
public void testP2SHTestNet() {
byte[] script = ScriptPubKeyProducer.getInstance(false, Coin.BTC, (byte) 0xC4)
byte[] script = ScriptPubKeyProducer.getInstance(false, Coin.BTC, (byte) 0xC4, false)
.produceScript(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04});
String expectedScript = "A9" + "05" + "0001020304" + "87";
assertThat(script).isEqualTo(HexUtils.asBytes(expectedScript));
}

@Test
public void testP2PKHMainNetLtc() {
byte[] script = ScriptPubKeyProducer.getInstance(true, Coin.LTC, (byte) 0x30)
byte[] script = ScriptPubKeyProducer.getInstance(true, Coin.LTC, (byte) 0x30, false)
.produceScript(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04});
String expectedScript = "76" + "A9" + "05" + "0001020304" + "88" + "AC";
assertThat(script).isEqualTo(HexUtils.asBytes(expectedScript));
}

@Test
public void testP2PKHTestNetLtc() {
byte[] script = ScriptPubKeyProducer.getInstance(false, Coin.LTC, (byte) 0x6F)
byte[] script = ScriptPubKeyProducer.getInstance(false, Coin.LTC, (byte) 0x6F, false)
.produceScript(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04});
String expectedScript = "76" + "A9" + "05" + "0001020304" + "88" + "AC";
assertThat(script).isEqualTo(HexUtils.asBytes(expectedScript));
}

@Test
public void testP2SHMainNetLtc() {
byte[] script = ScriptPubKeyProducer.getInstance(true, Coin.LTC, (byte) 0x05)
byte[] script = ScriptPubKeyProducer.getInstance(true, Coin.LTC, (byte) 0x05, false)
.produceScript(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04});
String expectedScript = "A9" + "05" + "0001020304" + "87";
assertThat(script).isEqualTo(HexUtils.asBytes(expectedScript));
}

@Test
public void testP2SHMainNetLtcNewFormat() {
byte[] script = ScriptPubKeyProducer.getInstance(true, Coin.LTC, (byte) 0x32)
byte[] script = ScriptPubKeyProducer.getInstance(true, Coin.LTC, (byte) 0x32, false)
.produceScript(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04});
String expectedScript = "A9" + "05" + "0001020304" + "87";
assertThat(script).isEqualTo(HexUtils.asBytes(expectedScript));
}

@Test
public void testP2SHTestNetLtc() {
byte[] script = ScriptPubKeyProducer.getInstance(false, Coin.LTC, (byte) 0xC4)
byte[] script = ScriptPubKeyProducer.getInstance(false, Coin.LTC, (byte) 0xC4, false)
.produceScript(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04});
String expectedScript = "A9" + "05" + "0001020304" + "87";
assertThat(script).isEqualTo(HexUtils.asBytes(expectedScript));
Expand Down

0 comments on commit b2fa776

Please sign in to comment.