diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/Base58ReferenceTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/Base58ReferenceTestsCommon.kt index 285b1e8b..4ac57f96 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/Base58ReferenceTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/Base58ReferenceTestsCommon.kt @@ -36,7 +36,7 @@ class Base58ReferenceTestsCommon { val expected = it[1].jsonPrimitive.content assertEquals(Base58.encode(Hex.decode(hex)), expected) val decoded = Base58.decode(expected) - assertEquals(Hex.encode(decoded), hex) + assertEquals(Hex.encode(decoded).lowercase(), hex.lowercase()) } } diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/KeyEncodingTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/KeyEncodingTestsCommon.kt index c7eb6fcd..b9b9b69a 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/KeyEncodingTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/KeyEncodingTestsCommon.kt @@ -79,7 +79,7 @@ class KeyEncodingTestsCommon { } val prefix = when (chain) { "main" -> "bc" - "test", "signet" -> "tb" + "test", "signet", "testnet4" -> "tb" "regtest" -> "bcrt" else -> throw IllegalArgumentException("invalid chain $chain") } diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/ScriptTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/ScriptTestsCommon.kt index c60cbe15..c8a6d187 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/ScriptTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/ScriptTestsCommon.kt @@ -52,7 +52,7 @@ class ScriptTestsCommon { runTest(it.jsonArray) count += 1 } - assertEquals(1207, count) + assertEquals(1212, count) } @@ -176,8 +176,27 @@ class ScriptTestsCommon { comments: String?, expectedText: String ) { - val witness = ScriptWitness(witnessText.map { ByteVector(it) }) - val scriptPubKey = parseFromText(scriptPubKeyText) + val witnessStack = mutableListOf() + val priv = PrivateKey(ByteVector32.One) + var leaf: ScriptTree.Leaf? = null + + witnessText.map { + when { + it.startsWith("#SCRIPT#") -> witnessStack.add(parseFromText(it.removePrefix("#SCRIPT#")).byteVector()) + it.startsWith("#CONTROLBLOCK#") -> { + leaf = ScriptTree.Leaf(witnessStack.last(), Script.TAPROOT_LEAF_TAPSCRIPT) + val controlBlock = Script.ControlBlock.build(priv.xOnlyPublicKey(), leaf, leaf) + witnessStack.add(controlBlock) + } + else -> witnessStack.add(ByteVector(it)) + } + } + val witness = ScriptWitness(witnessStack) + val scriptPubKey = if (scriptPubKeyText == "0x51 0x20 #TAPROOTOUTPUT#") { + Script.write(Script.pay2tr(priv.xOnlyPublicKey(), leaf)) + } else { + parseFromText(scriptPubKeyText) + } val scriptSig = parseFromText(scriptSigText) val tx = spendingTx(scriptSig, creditTx(scriptPubKey, amount)).updateWitness(0, witness) val ctx = Script.Context(tx, 0, amount, listOf()) diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/TransactionTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/TransactionTestsCommon.kt index b83074b2..fbaf3780 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/TransactionTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/TransactionTestsCommon.kt @@ -107,7 +107,7 @@ class TransactionTestsCommon { fun `reference valid tx tests`() { val tests = TestHelpers.readResourceAsJson("data/tx_valid.json") val count = process(tests.jsonArray, true) - assertEquals(119, count) + assertEquals(120, count) } @Test diff --git a/src/commonTest/resources/data/base58_encode_decode.json b/src/commonTest/resources/data/base58_encode_decode.json index 1a4bd7f4..7255fd45 100644 --- a/src/commonTest/resources/data/base58_encode_decode.json +++ b/src/commonTest/resources/data/base58_encode_decode.json @@ -11,6 +11,13 @@ ["ecac89cad93923c02321", "EJDM8drfXA6uyA"], ["10c8511e", "Rt5zm"], ["00000000000000000000", "1111111111"], +["00000000000000000000000000000000000000000000000000000000000000000000000000000000", "1111111111111111111111111111111111111111"], +["00000000000000000000000000000000000000000000000000000000000000000000000000000001", "1111111111111111111111111111111111111112"], +["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ec39d04c37e71e5d591881f6", "111111111111111111111111111111111111111111111111111111111111111111111111111111111111115TYzLYH1udmLdzCLM"], ["000111d38e5fc9071ffcd20b4a763cc9ae4f252bb4e48fd66a835e252ada93ff480d6dd43dc62a641155a5", "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"], -["000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "1cWB5HCBdLjAuqGGReWE3R3CguuwSjw6RHn39s2yuDRTS5NsBgNiFpWgAnEx6VQi8csexkgYw3mdYrMHr8x9i7aEwP8kZ7vccXWqKDvGv3u1GxFKPuAkn8JCPPGDMf3vMMnbzm6Nh9zh1gcNsMvH3ZNLmP5fSG6DGbbi2tuwMWPthr4boWwCxf7ewSgNQeacyozhKDDQQ1qL5fQFUW52QKUZDZ5fw3KXNQJMcNTcaB723LchjeKun7MuGW5qyCBZYzA1KjofN1gYBV3NqyhQJ3Ns746GNuf9N2pQPmHz4xpnSrrfCvy6TVVz5d4PdrjeshsWQwpZsZGzvbdAdN8MKV5QsBDY"] +["000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "1cWB5HCBdLjAuqGGReWE3R3CguuwSjw6RHn39s2yuDRTS5NsBgNiFpWgAnEx6VQi8csexkgYw3mdYrMHr8x9i7aEwP8kZ7vccXWqKDvGv3u1GxFKPuAkn8JCPPGDMf3vMMnbzm6Nh9zh1gcNsMvH3ZNLmP5fSG6DGbbi2tuwMWPthr4boWwCxf7ewSgNQeacyozhKDDQQ1qL5fQFUW52QKUZDZ5fw3KXNQJMcNTcaB723LchjeKun7MuGW5qyCBZYzA1KjofN1gYBV3NqyhQJ3Ns746GNuf9N2pQPmHz4xpnSrrfCvy6TVVz5d4PdrjeshsWQwpZsZGzvbdAdN8MKV5QsBDY"], +["271F359E", "zzzzy"], +["271F359F", "zzzzz"], +["271F35A0", "211111"], +["271F35A1", "211112"] ] diff --git a/src/commonTest/resources/data/key_io_valid.json b/src/commonTest/resources/data/key_io_valid.json index c051f8b7..bff7ecff 100644 --- a/src/commonTest/resources/data/key_io_valid.json +++ b/src/commonTest/resources/data/key_io_valid.json @@ -19,7 +19,7 @@ "mzK2FFDEhxqHcmrJw1ysqFkVyhUULo45hZ", "76a914ce28b26c57472737f5c3561a1761185bd8589a4388ac", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false } ], @@ -27,7 +27,7 @@ "2NC2hEhe28ULKAJkW5MjZ3jtTMJdvXmByvK", "a914ce0bba75891ff9ec60148d4bd4a09ee2dc5c933187", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false } ], @@ -85,7 +85,7 @@ "92ZdE5HoLafywnTBbzPxbvRmp75pSfzvdU3XaZGh1cToipgdHVh", "80c32d81e91bdea04cd7a3819b32275fc3298af4c7ec87eb0099527d041ced5c", { - "chain": "test", + "chain": "testnet4", "isCompressed": false, "isPrivkey": true } @@ -94,7 +94,7 @@ "cV83kKisF3RQSvXbUCm9ox3kaz5JjEUBWcx8tNydfGJcyeUxuH47", "e0fcd4ce4e3d0e3de091f21415bb7cd011fac288c42020a879f28c2a4387df9b", { - "chain": "test", + "chain": "testnet4", "isCompressed": true, "isPrivkey": true } @@ -175,7 +175,7 @@ "tb1qcrh3yqn4nlleplcez2yndq2ry8h9ncg3qh7n54", "0014c0ef1202759fff90ff19128936814321ee59e111", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false, "tryCaseFlip": true } @@ -184,7 +184,7 @@ "tb1quyl9ujpgwr2chdzdnnalen48sup245vdfnh2jxhsuq3yx80rrwlq5hqfe4", "0020e13e5e482870d58bb44d9cfbfccea78702aad18d4ceea91af0e022431de31bbe", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false, "tryCaseFlip": true } @@ -193,7 +193,7 @@ "tb1p35n52jy6xkm4wd905tdy8qtagrn73kqdz73xe4zxpvq9t3fp50aqk3s6gz", "51208d2745489a35b75734afa2da43817d40e7e8d80d17a26cd4460b0055c521a3fa", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false, "tryCaseFlip": true } @@ -202,7 +202,7 @@ "tb1rgv5m6uvdk3kc7qsuz0c79v88ycr5w4wa", "53104329bd718db46d8f021c13f1e2b0e726", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false, "tryCaseFlip": true } @@ -299,7 +299,7 @@ "n4YNbYuFdPwFrxSP8sjHFbAhUbLMUiY9jE", "76a914fc8f9851f3c1e4719cd0b8e4816dd4e88c72e52888ac", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false } ], @@ -307,7 +307,7 @@ "2NAeQVZayzVFAtgeC3iYJsjpjWDmsDph71A", "a914bedc797342c03fd7a346c4c7857ca03d467013b687", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false } ], @@ -365,7 +365,7 @@ "921M1RNxghFcsVGqAJksQVbSgx36Yz4u6vebfz1wDujNvgNt93B", "3777b341c45e2a9b9bf6bfb71dc7d129f64f1b9406ed4f93ade8f56065f1b732", { - "chain": "test", + "chain": "testnet4", "isCompressed": false, "isPrivkey": true } @@ -374,7 +374,7 @@ "cNEnbfF2fcxmmCLWqMAaq6fxJvVkwMbyU3kCbpQznz4Z1j6TZDGb", "1397b0d4a03e1ab2c54dd9af99ce1ecbfb90c80a58886da95e1181a55703d96b", { - "chain": "test", + "chain": "testnet4", "isCompressed": true, "isPrivkey": true } @@ -455,7 +455,7 @@ "tb1ql4k5ayv7p7w0t0ge7tpntgpkgw53g2payxkszr", "0014fd6d4e919e0f9cf5bd19f2c335a03643a914283d", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false, "tryCaseFlip": true } @@ -464,7 +464,7 @@ "tb1q9jx3x2qqdpempxrcfgyrkjd5fzeacaqj4ua7cs7fe2sfd2wdaueq5wn26y", "00202c8d1328006873b098784a083b49b448b3dc7412af3bec43c9caa096a9cdef32", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false, "tryCaseFlip": true } @@ -473,7 +473,7 @@ "tb1pdswckwd9ym5yf5eyzg8j4jjwnzla8y0tf9cp7aasfkek0u29sz9qfr00yf", "51206c1d8b39a526e844d324120f2aca4e98bfd391eb49701f77b04db367f145808a", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false, "tryCaseFlip": true } @@ -482,7 +482,7 @@ "tb1r0ecpfxg2udhtc556gqrpwwhk4sw3f0kc", "53107e7014990ae36ebc529a4006173af6ac", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false, "tryCaseFlip": true } @@ -579,7 +579,7 @@ "mwgS2HRbjyfYxFnR1nF9VKLvmdgMfFBmGq", "76a914b14ce7070b53cb0e4b5b5f6e253e876990aeca2e88ac", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false } ], @@ -587,7 +587,7 @@ "2MwBVrJQ76BdaGD76CTmou8cZzQYLpe4NqU", "a9142b2c149cde619eae3d7fe995243b76a3417541aa87", { - "chain": "test", + "chain": "testnet4", "isPrivkey": false } ], diff --git a/src/commonTest/resources/data/script_tests.json b/src/commonTest/resources/data/script_tests.json index ad052403..6282f666 100644 --- a/src/commonTest/resources/data/script_tests.json +++ b/src/commonTest/resources/data/script_tests.json @@ -105,6 +105,7 @@ ["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL", "P2SH,STRICTENC", "OK"], ["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL", "P2SH,STRICTENC", "OK"], ["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL", "P2SH,STRICTENC", "OK"], +["1 2 3 4 5 6", "2ROT DEPTH 6 EQUAL", "P2SH,STRICTENC", "OK"], ["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"], ["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "OK"], ["13 14", "2DUP ROT EQUALVERIFY EQUAL", "P2SH,STRICTENC", "OK"], @@ -2610,6 +2611,63 @@ [["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"], [["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], +["Tapscript tests"], +[ + [ + "1ffe1234567890", + "00", + "#SCRIPT# HASH256 DUP SHA1 DROP DUP DROP TOALTSTACK HASH256 DUP DROP TOALTSTACK FROMALTSTACK", + "#CONTROLBLOCK#", + 0.00000001 + ], + "", + "0x51 0x20 #TAPROOTOUTPUT#", + "P2SH,WITNESS,TAPROOT", + "OK", + "TAPSCRIPT Tests testing tapscript with many different op codes including ALTSTACK interactions" +], +[ + [ + "abcdef", + "#SCRIPT# 1 IF SHA256 ENDIF SIZE SWAP DROP 32 EQUAL", + "#CONTROLBLOCK#", + 0.00000001 + ], + "", + "0x51 0x20 #TAPROOTOUTPUT#", + "P2SH,WITNESS,TAPROOT", + "OK", + "TAPSCRIPT Test IF conditional when true" +], +[ + [ + "abcdef", + "#SCRIPT# 0 IF SHA256 ENDIF SIZE SWAP DROP 32 EQUAL", + "#CONTROLBLOCK#", + 0.00000001 + ], + "", + "0x51 0x20 #TAPROOTOUTPUT#", + "P2SH,WITNESS,TAPROOT", + "EVAL_FALSE", + "TAPSCRIPT Test IF conditional when false" +], +[ + [ + "aa", + "bb", + "cc", + "#SCRIPT# EQUAL IF DROP DROP ENDIF", + "#CONTROLBLOCK#", + 0.00000001 + ], + "", + "0x51 0x20 #TAPROOTOUTPUT#", + "P2SH,WITNESS,TAPROOT", + "OK", + "TAPSCRIPT Test that DROP operations do not execute inside of a false IF conditional" +], + ["NULLFAIL should cover all signatures and signatures only"], ["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"], ["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"], diff --git a/src/commonTest/resources/data/tx_invalid.json b/src/commonTest/resources/data/tx_invalid.json index a47bc8f3..486469dd 100644 --- a/src/commonTest/resources/data/tx_invalid.json +++ b/src/commonTest/resources/data/tx_invalid.json @@ -246,7 +246,7 @@ [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]], "0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -["Failure due to insufficient tx.nVersion (<2)"], +["Failure due to insufficient tx.version (<2)"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY"]], diff --git a/src/commonTest/resources/data/tx_valid.json b/src/commonTest/resources/data/tx_valid.json index b874f6f2..d7c367b8 100644 --- a/src/commonTest/resources/data/tx_valid.json +++ b/src/commonTest/resources/data/tx_valid.json @@ -7,7 +7,7 @@ ["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], ["It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"], -["See http://r6.ca/blog/20111119T211504Z.html"], +["See https://r6.ca/blog/20111119T211504Z.html"], ["It is also the first OP_CHECKMULTISIG transaction in standard form"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "DERSIG,LOW_S,STRICTENC"], @@ -319,6 +319,10 @@ [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]], "0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2010000000100000000000000000000000000", "NONE"], +["Valid CHECKSEQUENCEVERIFY even with negative tx version number"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]], +"ffffffff01000100000000000000000000000000000000000000000000000000000000000000000000030251b2010000000100000000000000000000000000", "NONE"], + ["Valid P2WPKH (Private key of segwit tests is L5AQtV2HDm4xGsseLokK2VAT2EtYKcTm3c7HwqnJBFt9LdaQULsM)"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]], "0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "NONE"],