diff --git a/src/commonMain/kotlin/fr/acinq/bitcoin/Bech32.kt b/src/commonMain/kotlin/fr/acinq/bitcoin/Bech32.kt index 1b4c94cd..19ca785a 100644 --- a/src/commonMain/kotlin/fr/acinq/bitcoin/Bech32.kt +++ b/src/commonMain/kotlin/fr/acinq/bitcoin/Bech32.kt @@ -47,7 +47,7 @@ public object Bech32 { } @JvmStatic - public fun hrp(chainHash: ByteVector32): String = when (chainHash) { + public fun hrp(chainHash: BlockHash): String = when (chainHash) { Block.TestnetGenesisBlock.hash -> "tb" Block.SignetGenesisBlock.hash -> "tb" Block.RegtestGenesisBlock.hash -> "bcrt" diff --git a/src/commonMain/kotlin/fr/acinq/bitcoin/Bitcoin.kt b/src/commonMain/kotlin/fr/acinq/bitcoin/Bitcoin.kt index ea1f97dc..b92bd80f 100644 --- a/src/commonMain/kotlin/fr/acinq/bitcoin/Bitcoin.kt +++ b/src/commonMain/kotlin/fr/acinq/bitcoin/Bitcoin.kt @@ -87,10 +87,10 @@ public sealed class AddressFromPublicKeyScriptResult { public object Bitcoin { @JvmStatic - public fun computeP2PkhAddress(pub: PublicKey, chainHash: ByteVector32): String = pub.p2pkhAddress(chainHash) + public fun computeP2PkhAddress(pub: PublicKey, chainHash: BlockHash): String = pub.p2pkhAddress(chainHash) @JvmStatic - public fun computeBIP44Address(pub: PublicKey, chainHash: ByteVector32): String = computeP2PkhAddress(pub, chainHash) + public fun computeBIP44Address(pub: PublicKey, chainHash: BlockHash): String = computeP2PkhAddress(pub, chainHash) /** * @param pub public key @@ -98,10 +98,10 @@ public object Bitcoin { * @return the p2swh-of-p2pkh address for this key. It is a Base58 address that is compatible with most bitcoin wallets */ @JvmStatic - public fun computeP2ShOfP2WpkhAddress(pub: PublicKey, chainHash: ByteVector32): String = pub.p2shOfP2wpkhAddress(chainHash) + public fun computeP2ShOfP2WpkhAddress(pub: PublicKey, chainHash: BlockHash): String = pub.p2shOfP2wpkhAddress(chainHash) @JvmStatic - public fun computeBIP49Address(pub: PublicKey, chainHash: ByteVector32): String = computeP2ShOfP2WpkhAddress(pub, chainHash) + public fun computeBIP49Address(pub: PublicKey, chainHash: BlockHash): String = computeP2ShOfP2WpkhAddress(pub, chainHash) /** * @param pub public key @@ -110,10 +110,10 @@ public object Bitcoin { * understood only by native segwit wallets */ @JvmStatic - public fun computeP2WpkhAddress(pub: PublicKey, chainHash: ByteVector32): String = pub.p2wpkhAddress(chainHash) + public fun computeP2WpkhAddress(pub: PublicKey, chainHash: BlockHash): String = pub.p2wpkhAddress(chainHash) @JvmStatic - public fun computeBIP84Address(pub: PublicKey, chainHash: ByteVector32): String = computeP2WpkhAddress(pub, chainHash) + public fun computeBIP84Address(pub: PublicKey, chainHash: BlockHash): String = computeP2WpkhAddress(pub, chainHash) /** * Compute an address from a public key script @@ -121,7 +121,7 @@ public object Bitcoin { * @param pubkeyScript public key script */ @JvmStatic - public fun addressFromPublicKeyScript(chainHash: ByteVector32, pubkeyScript: List): AddressFromPublicKeyScriptResult { + public fun addressFromPublicKeyScript(chainHash: BlockHash, pubkeyScript: List): AddressFromPublicKeyScriptResult { try { return when { Script.isPay2pkh(pubkeyScript) -> { @@ -179,7 +179,7 @@ public object Bitcoin { } @JvmStatic - public fun addressFromPublicKeyScript(chainHash: ByteVector32, pubkeyScript: ByteArray): AddressFromPublicKeyScriptResult { + public fun addressFromPublicKeyScript(chainHash: BlockHash, pubkeyScript: ByteArray): AddressFromPublicKeyScriptResult { return runCatching { Script.parse(pubkeyScript) }.fold( onSuccess = { addressFromPublicKeyScript(chainHash, it) @@ -191,7 +191,7 @@ public object Bitcoin { } @JvmStatic - public fun addressToPublicKeyScript(chainHash: ByteVector32, address: String): AddressToPublicKeyScriptResult { + public fun addressToPublicKeyScript(chainHash: BlockHash, address: String): AddressToPublicKeyScriptResult { val witnessVersions = mapOf( 0.toByte() to OP_0, 1.toByte() to OP_1, diff --git a/src/commonMain/kotlin/fr/acinq/bitcoin/Block.kt b/src/commonMain/kotlin/fr/acinq/bitcoin/Block.kt index da5daf78..78629086 100644 --- a/src/commonMain/kotlin/fr/acinq/bitcoin/Block.kt +++ b/src/commonMain/kotlin/fr/acinq/bitcoin/Block.kt @@ -24,11 +24,27 @@ import kotlin.experimental.and import kotlin.jvm.JvmField import kotlin.jvm.JvmStatic +/** This is the double hash of a serialized block header. */ +public data class BlockHash(@JvmField val value: ByteVector32) { + public constructor(hash: ByteArray) : this(hash.byteVector32()) + public constructor(hash: String) : this(ByteVector32(hash)) + public constructor(blockId: BlockId) : this(blockId.value.reversed()) + + override fun toString(): String = value.toString() +} + +/** This contains the same data as [BlockHash], but encoded with the opposite endianness. */ +public data class BlockId(@JvmField val value: ByteVector32) { + public constructor(blockId: ByteArray) : this(blockId.byteVector32()) + public constructor(blockId: String) : this(ByteVector32(blockId)) + public constructor(hash: BlockHash) : this(hash.value.reversed()) + + override fun toString(): String = value.toString() +} + /** - * * @param version Block version information, based upon the software version creating this block - * @param hashPreviousBlock The hash value of the previous block this particular block references. Please note that - * this hash is not reversed (as opposed to Block.hash) + * @param hashPreviousBlock The hash value of the previous block this particular block references. * @param hashMerkleRoot The reference to a Merkle tree collection which is a hash of all transactions related to this block * @param time A timestamp recording when this block was created (Will overflow in 2106[2]) * @param bits The calculated difficulty target being used for this block @@ -36,21 +52,21 @@ import kotlin.jvm.JvmStatic */ public data class BlockHeader( @JvmField val version: Long, - @JvmField val hashPreviousBlock: ByteVector32, + @JvmField val hashPreviousBlock: BlockHash, @JvmField val hashMerkleRoot: ByteVector32, @JvmField val time: Long, @JvmField val bits: Long, @JvmField val nonce: Long ) : BtcSerializable { @JvmField - public val hash: ByteVector32 = ByteVector32(Crypto.hash256(write(this))) + public val hash: BlockHash = BlockHash(Crypto.hash256(write(this))) @JvmField - public val blockId: ByteVector32 = hash.reversed() + public val blockId: BlockId = BlockId(hash) public fun setVersion(input: Long): BlockHeader = this.copy(version = input) - public fun setHashPreviousBlock(input: ByteVector32): BlockHeader = this.copy(hashPreviousBlock = input) + public fun setHashPreviousBlock(input: BlockHash): BlockHeader = this.copy(hashPreviousBlock = input) public fun setHashMerkleRoot(input: ByteVector32): BlockHeader = this.copy(hashMerkleRoot = input) @@ -64,14 +80,14 @@ public data class BlockHeader( public companion object : BtcSerializer() { override fun read(input: Input, protocolVersion: Long): BlockHeader { val version = uint32(input) - val hashPreviousBlock = hash(input) + val hashPreviousBlock = BlockHash(hash(input)) val hashMerkleRoot = hash(input) val time = uint32(input) val bits = uint32(input) val nonce = uint32(input) return BlockHeader( version.toLong(), - hashPreviousBlock.byteVector32(), + hashPreviousBlock, hashMerkleRoot.byteVector32(), time.toLong(), bits.toLong(), @@ -91,7 +107,7 @@ public data class BlockHeader( override fun write(message: BlockHeader, output: Output, protocolVersion: Long) { writeUInt32(message.version.toUInt(), output) - writeBytes(message.hashPreviousBlock, output) + writeBytes(message.hashPreviousBlock.value, output) writeBytes(message.hashMerkleRoot, output) writeUInt32(message.time.toUInt(), output) writeUInt32(message.bits.toUInt(), output) @@ -138,7 +154,7 @@ public data class BlockHeader( @JvmStatic public fun checkProofOfWork(header: BlockHeader): Boolean { val (target, _, _) = UInt256.decodeCompact(header.bits) - val hash = UInt256(header.blockId.toByteArray()) + val hash = UInt256(header.blockId.value.toByteArray()) return hash <= target } @@ -187,10 +203,10 @@ public object MerkleTree { public data class Block(@JvmField val header: BlockHeader, @JvmField val tx: List) { @JvmField - val hash: ByteVector32 = header.hash + val hash: BlockHash = header.hash @JvmField - val blockId: ByteVector32 = hash.reversed() + val blockId: BlockId = header.blockId public companion object : BtcSerializer() { override fun write(message: Block, out: Output, protocolVersion: Long) { @@ -222,7 +238,7 @@ public data class Block(@JvmField val header: BlockHeader, @JvmField val tx: Lis @JvmStatic override fun validate(message: Block) { BlockHeader.validate(message.header) - require(message.header.hashMerkleRoot == MerkleTree.computeRoot(message.tx.map { it.hash })) { "invalid block: merkle root mismatch" } + require(message.header.hashMerkleRoot == MerkleTree.computeRoot(message.tx.map { it.hash.value })) { "invalid block: merkle root mismatch" } require(message.tx.map { it.hash }.toSet().size == message.tx.size) { "invalid block: duplicate transactions" } message.tx.map { Transaction.validate(it) } } @@ -333,7 +349,7 @@ public data class Block(@JvmField val header: BlockHeader, @JvmField val tx: Lis Block( BlockHeader( version = 1, - hashPreviousBlock = ByteVector32.Zeroes, + hashPreviousBlock = BlockHash(ByteVector32.Zeroes), hashMerkleRoot = ByteVector32("3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a"), time = 1231006505, bits = 0x1d00ffff, diff --git a/src/commonMain/kotlin/fr/acinq/bitcoin/Descriptor.kt b/src/commonMain/kotlin/fr/acinq/bitcoin/Descriptor.kt index 8e48aa39..5cf1c352 100644 --- a/src/commonMain/kotlin/fr/acinq/bitcoin/Descriptor.kt +++ b/src/commonMain/kotlin/fr/acinq/bitcoin/Descriptor.kt @@ -66,14 +66,14 @@ public object Descriptor { return ret.toString() } - private fun getBIP84KeyPath(chainHash: ByteVector32): Pair = when (chainHash) { + private fun getBIP84KeyPath(chainHash: BlockHash): Pair = when (chainHash) { Block.RegtestGenesisBlock.hash, Block.TestnetGenesisBlock.hash -> "84'/1'/0'/0" to DeterministicWallet.tpub Block.LivenetGenesisBlock.hash -> "84'/0'/0'/0" to DeterministicWallet.xpub else -> error("invalid chain hash $chainHash") } @JvmStatic - public fun BIP84Descriptors(chainHash: ByteVector32, master: DeterministicWallet.ExtendedPrivateKey): Pair { + public fun BIP84Descriptors(chainHash: BlockHash, master: DeterministicWallet.ExtendedPrivateKey): Pair { val (keyPath, _) = getBIP84KeyPath(chainHash) val accountPub = publicKey(derivePrivateKey(master, KeyPath(keyPath))) val fingerprint = DeterministicWallet.fingerprint(master) and 0xFFFFFFFFL @@ -81,7 +81,7 @@ public object Descriptor { } @JvmStatic - public fun BIP84Descriptors(chainHash: ByteVector32, fingerprint: Long, accountPub: DeterministicWallet.ExtendedPublicKey): Pair { + public fun BIP84Descriptors(chainHash: BlockHash, fingerprint: Long, accountPub: DeterministicWallet.ExtendedPublicKey): Pair { val (keyPath, prefix) = getBIP84KeyPath(chainHash) val accountDesc = "wpkh([${fingerprint.toString(16)}/$keyPath]${DeterministicWallet.encode(accountPub, prefix)}/0/*)" val changeDesc = "wpkh([${fingerprint.toString(16)}/$keyPath]${DeterministicWallet.encode(accountPub, prefix)}/1/*)" diff --git a/src/commonMain/kotlin/fr/acinq/bitcoin/LexicographicalOrdering.kt b/src/commonMain/kotlin/fr/acinq/bitcoin/LexicographicalOrdering.kt index 049c6bb4..7467ca21 100644 --- a/src/commonMain/kotlin/fr/acinq/bitcoin/LexicographicalOrdering.kt +++ b/src/commonMain/kotlin/fr/acinq/bitcoin/LexicographicalOrdering.kt @@ -44,7 +44,7 @@ public object LexicographicalOrdering { @JvmStatic public fun isLessThan(a: OutPoint, b: OutPoint): Boolean { - return if (a.txid == b.txid) a.index < b.index else isLessThan(a.txid, b.txid) + return if (a.txid == b.txid) a.index < b.index else isLessThan(a.txid.value, b.txid.value) } @JvmStatic diff --git a/src/commonMain/kotlin/fr/acinq/bitcoin/PublicKey.kt b/src/commonMain/kotlin/fr/acinq/bitcoin/PublicKey.kt index c4abd961..c2f641ff 100644 --- a/src/commonMain/kotlin/fr/acinq/bitcoin/PublicKey.kt +++ b/src/commonMain/kotlin/fr/acinq/bitcoin/PublicKey.kt @@ -76,7 +76,7 @@ public data class PublicKey(@JvmField val value: ByteVector) { * @param chainHash chain hash (i.e. hash of the genesis block of the chain we're on) * @return the "legacy" p2pkh address for this key */ - public fun p2pkhAddress(chainHash: ByteVector32): String = when (chainHash) { + public fun p2pkhAddress(chainHash: BlockHash): String = when (chainHash) { Block.TestnetGenesisBlock.hash, Block.RegtestGenesisBlock.hash, Block.SignetGenesisBlock.hash -> Base58Check.encode(Base58.Prefix.PubkeyAddressTestnet, hash160()) Block.LivenetGenesisBlock.hash -> Base58Check.encode(Base58.Prefix.PubkeyAddress, hash160()) else -> error("invalid chain hash $chainHash") @@ -87,7 +87,7 @@ public data class PublicKey(@JvmField val value: ByteVector) { * @return the p2swh-of-p2pkh address for this key. * It is a Base58 address that is compatible with most bitcoin wallets. */ - public fun p2shOfP2wpkhAddress(chainHash: ByteVector32): String { + public fun p2shOfP2wpkhAddress(chainHash: BlockHash): String { val script = Script.pay2wpkh(this) val hash = Crypto.hash160(Script.write(script)) return when (chainHash) { @@ -102,7 +102,7 @@ public data class PublicKey(@JvmField val value: ByteVector) { * @return the BIP84 address for this key (i.e. the p2wpkh address for this key). * It is a Bech32 address that will be understood only by native segwit wallets. */ - public fun p2wpkhAddress(chainHash: ByteVector32): String { + public fun p2wpkhAddress(chainHash: BlockHash): String { return Bech32.encodeWitnessAddress(Bech32.hrp(chainHash), 0, hash160()) } diff --git a/src/commonMain/kotlin/fr/acinq/bitcoin/Transaction.kt b/src/commonMain/kotlin/fr/acinq/bitcoin/Transaction.kt index 7ffe04f6..c0dd5dcd 100644 --- a/src/commonMain/kotlin/fr/acinq/bitcoin/Transaction.kt +++ b/src/commonMain/kotlin/fr/acinq/bitcoin/Transaction.kt @@ -25,32 +25,54 @@ import kotlin.jvm.JvmField import kotlin.jvm.JvmStatic /** - * an out point is a reference to a specific output in a specific transaction that we want to claim - * - * @param hash reversed sha256(sha256(tx)) where tx is the transaction we want to refer to - * @param index index of the output in tx that we want to refer to + * This is the double hash of a transaction serialized without witness data. + * Note that this is confusingly called `txid` in some context (e.g. in lightning messages). */ -public data class OutPoint(@JvmField val hash: ByteVector32, @JvmField val index: Long) : BtcSerializable { - public constructor(hash: ByteArray, index: Long) : this(hash.byteVector32(), index) +public data class TxHash(@JvmField val value: ByteVector32) { + public constructor(hash: ByteArray) : this(hash.byteVector32()) + public constructor(hash: String) : this(ByteVector32(hash)) + public constructor(txid: TxId) : this(txid.value.reversed()) + + override fun toString(): String = value.toString() +} + +/** + * This contains the same data as [TxHash], but encoded with the opposite endianness. + * Some explorers and bitcoin RPCs use this encoding for their inputs. + */ +public data class TxId(@JvmField val value: ByteVector32) { + public constructor(txid: ByteArray) : this(txid.byteVector32()) + public constructor(txid: String) : this(ByteVector32(txid)) + public constructor(hash: TxHash) : this(hash.value.reversed()) + + override fun toString(): String = value.toString() +} +/** + * An OutPoint is a reference to a specific output in a specific transaction. + * + * @param hash sha256(sha256(tx)) where tx is the transaction we want to refer to. + * @param index index of the output in tx that we want to refer to. + */ +public data class OutPoint(@JvmField val hash: TxHash, @JvmField val index: Long) : BtcSerializable { public constructor(tx: Transaction, index: Long) : this(tx.hash, index) + public constructor(txid: TxId, index: Long) : this(TxHash(txid), index) init { // The genesis block contains inputs with index = -1, so we cannot require it to be >= 0 require(index >= -1) } - /** - * @return the id of the transaction this output belongs to - */ @JvmField - public val txid: ByteVector32 = hash.reversed() + public val txid: TxId = TxId(hash) public val isCoinbase: Boolean get() = isCoinbase(this) + override fun toString(): String = "$txid:$index" + public companion object : BtcSerializer() { @JvmStatic - override fun read(input: Input, protocolVersion: Long): OutPoint = OutPoint(hash(input), uint32(input).toLong()) + override fun read(input: Input, protocolVersion: Long): OutPoint = OutPoint(TxHash(hash(input)), uint32(input).toLong()) @JvmStatic override fun read(input: ByteArray): OutPoint { @@ -59,7 +81,7 @@ public data class OutPoint(@JvmField val hash: ByteVector32, @JvmField val index @JvmStatic override fun write(message: OutPoint, out: Output, protocolVersion: Long) { - out.write(message.hash.toByteArray()) + out.write(message.hash.value.toByteArray()) writeUInt32(message.index.toUInt(), out) } @@ -69,7 +91,7 @@ public data class OutPoint(@JvmField val hash: ByteVector32, @JvmField val index } @JvmStatic - public fun isCoinbase(input: OutPoint): Boolean = input.index == 0xffffffffL && input.hash == ByteVector32.Zeroes + public fun isCoinbase(input: OutPoint): Boolean = input.index == 0xffffffffL && input.hash.value == ByteVector32.Zeroes @JvmStatic public fun isNull(input: OutPoint): Boolean = isCoinbase(input) @@ -201,7 +223,7 @@ public data class TxIn( @JvmStatic public fun coinbase(script: ByteArray): TxIn { require(script.size in 2..100) { "coinbase script length must be between 2 and 100" } - return TxIn(OutPoint(ByteArray(32), 0xffffffffL), script, sequence = 0xffffffffL) + return TxIn(OutPoint(TxHash(ByteArray(32)), 0xffffffffL), script, sequence = 0xffffffffL) } @JvmStatic @@ -282,10 +304,10 @@ public data class Transaction( public val hasWitness: Boolean get() = txIn.any { it.hasWitness } @JvmField - public val hash: ByteVector32 = Crypto.hash256(Transaction.write(this, SERIALIZE_TRANSACTION_NO_WITNESS)).byteVector32() + public val hash: TxHash = TxHash(Crypto.hash256(Transaction.write(this, SERIALIZE_TRANSACTION_NO_WITNESS))) @JvmField - public val txid: ByteVector32 = hash.reversed() + public val txid: TxId = TxId(hash) /** * @param i index of the tx input to update diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/BitcoinTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/BitcoinTestsCommon.kt index 6f92ada5..c466d5f5 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/BitcoinTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/BitcoinTestsCommon.kt @@ -33,16 +33,16 @@ class BitcoinTestsCommon { fun `compute address from pubkey script`() { val pub = PrivateKey.fromHex("0101010101010101010101010101010101010101010101010101010101010101").publicKey() - fun address(script: List, chainHash: ByteVector32) = addressFromPublicKeyScript(chainHash, script) + fun address(script: List, chainHash: BlockHash) = addressFromPublicKeyScript(chainHash, script) listOf(Block.LivenetGenesisBlock.hash, Block.TestnetGenesisBlock.hash, Block.RegtestGenesisBlock.hash, Block.SignetGenesisBlock.hash).forEach { assertEquals(address(Script.pay2pkh(pub), it).result, computeP2PkhAddress(pub, it)) assertEquals(address(Script.pay2wpkh(pub), it).result, computeP2WpkhAddress(pub, it)) assertEquals(address(Script.pay2sh(Script.pay2wpkh(pub)), it).result, computeP2ShOfP2WpkhAddress(pub, it)) // all these chain hashes are invalid - assertTrue(address(Script.pay2pkh(pub), it.reversed()).isFailure()) - assertTrue(address(Script.pay2wpkh(pub), it.reversed()).isFailure()) - assertTrue(address(Script.pay2sh(Script.pay2wpkh(pub)), it.reversed()).isFailure()) + assertTrue(address(Script.pay2pkh(pub), BlockHash(it.value.reversed())).isFailure()) + assertTrue(address(Script.pay2wpkh(pub), BlockHash(it.value.reversed())).isFailure()) + assertTrue(address(Script.pay2sh(Script.pay2wpkh(pub)), BlockHash(it.value.reversed())).isFailure()) } listOf( @@ -117,9 +117,9 @@ class BitcoinTestsCommon { @Test fun `check genesis block hashes`() { - assertEquals(Block.RegtestGenesisBlock.blockId, ByteVector32.fromValidHex("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")) - assertEquals(Block.SignetGenesisBlock.blockId, ByteVector32.fromValidHex("0x00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6")) - assertEquals(Block.TestnetGenesisBlock.blockId, ByteVector32.fromValidHex("0x000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")) - assertEquals(Block.LivenetGenesisBlock.blockId, ByteVector32.fromValidHex("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")) + assertEquals(Block.RegtestGenesisBlock.blockId, BlockId("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")) + assertEquals(Block.SignetGenesisBlock.blockId, BlockId("00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6")) + assertEquals(Block.TestnetGenesisBlock.blockId, BlockId("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")) + assertEquals(Block.LivenetGenesisBlock.blockId, BlockId("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")) } } \ No newline at end of file diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/BlockTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/BlockTestsCommon.kt index 3fafb43f..5445c876 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/BlockTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/BlockTestsCommon.kt @@ -40,7 +40,7 @@ class BlockTestsCommon { val block = Block.read(blockData) assertTrue(Block.checkProofOfWork(block)) - assertEquals(MerkleTree.computeRoot(block.tx.map { it.hash }), block.header.hashMerkleRoot) + assertEquals(MerkleTree.computeRoot(block.tx.map { it.hash.value }), block.header.hashMerkleRoot) // check that we can deserialize and re-serialize scripts for (tx in block.tx) { @@ -64,6 +64,18 @@ class BlockTestsCommon { assertEquals(check.byteVector(), blockData.byteVector()) } + @Test + fun `serialize and deserialize block headers`() { + // The following are mainnet block headers for blocks 784900 and 784901. + val serialized784900 = ByteVector("0020a1309ea246510ac18e4bf1e40d7534e0e34ccc9af28c24a402000000000000000000bb5c749cd2700dbfb944acaefdc5af88e85b12b2300a80edf0d8d51cf00149c709333564b2e0051776140ae0") + val header784900 = BlockHeader.read(serialized784900.bytes) + val serialized784901 = ByteVector("00602f2ae7c9e1422e2782ea47a06a1e646a7ed61abefd11fe1102000000000000000000b6695a665e4f1b444770bb8e6224cce3ee4c74e031cbaf432981718b7a0c53e42e343564b2e00517275e5cf9") + val header784901 = BlockHeader.read(serialized784901.bytes) + assertEquals(header784901.hashPreviousBlock, header784900.hash) + assertEquals(serialized784900, BlockHeader.write(header784900).byteVector()) + assertEquals(serialized784901, BlockHeader.write(header784901).byteVector()) + } + @Test fun `compute proof of work`() { assertEquals( @@ -100,7 +112,7 @@ class BlockTestsCommon { fun `calculate next work required`() { val header = BlockHeader( version = 2, - hashPreviousBlock = ByteVector32.Zeroes, + hashPreviousBlock = BlockHash(ByteVector32.Zeroes), hashMerkleRoot = ByteVector32.Zeroes, time = 0L, bits = 0L, @@ -121,7 +133,7 @@ class BlockTestsCommon { "0000c0208d1459d7a99eb66ea054532c29771d39bba60c897314030000000000000000009fed1aefd92f59e35f1410570f90c0d5f43ab7ea58c7af6ecccef50c7c7b7ae3ed06d862afa70917308a412ecc0b00000cdfc60a77fdd548edf67c6a7a023a7d7b2a6b107a8b425b2328c2a4ed7621c65b22f578025d43c278f33514b5d3cdddafa89b5505b74fba4fdbe725a378d37d835b8c0003f14e6676c732324500c6c32ffecaf66677c1059733d4536aca0cae89913273ca64be4efcb44c86bc37b86ce17b1292b513de9c2f07b613c798966124ded1c92d32904a5928b940f4f11e9e75bff77f804e401947036ebd896acba889de0023490f45392a271d2bfbb8c0a912092c5d314d34c785a4c59dca160b5611b9151eaa500aa813b35d33f1d4d1bed3059349362f4dbffb1ad82f911e1d23ed9cf285084722c59f2947b87499f829fdf7edf4338292af047635b46b82e8e1e262b5f837b524359e2bc3572831e23862832b698da33b82ebcc28ce048e8b9d9061de2fadecd76ac3f6304f8c86f559564ef9aca03a8efe057b3da7fa3530e342f8422cdaa56349887e92ae22f040d90e135505c8bb12b91dd9f0c2413179a5ef770972389e6dea9a8cfb9d971d35bccf9959c7de570bd417ff1090d900ab0f8c037d7f00" ) val (header, matched) = Block.verifyTxOutProof(raw) - assertEquals(header.hash, ByteVector32("000000000000000000030cbb70966693d2516ca868fb490582dcf3dec90250f1").reversed()) + assertEquals(header.blockId, BlockId("000000000000000000030cbb70966693d2516ca868fb490582dcf3dec90250f1")) assertTrue(BlockHeader.checkProofOfWork(header)) assertEquals(matched, listOf(ByteVector32("89ae0cca6a53d4339705c17766f6cafe2fc3c600453232c776664ef103008c5b").reversed() to 2112)) } @@ -132,7 +144,7 @@ class BlockTestsCommon { "0000c0208d1459d7a99eb66ea054532c29771d39bba60c897314030000000000000000009fed1aefd92f59e35f1410570f90c0d5f43ab7ea58c7af6ecccef50c7c7b7ae3ed06d862afa70917308a412ecc0b000019dfc60a77fdd548edf67c6a7a023a7d7b2a6b107a8b425b2328c2a4ed7621c65b22f578025d43c278f33514b5d3cdddafa89b5505b74fba4fdbe725a378d37d835b8c0003f14e6676c732324500c6c32ffecaf66677c1059733d4536aca0cae89913273ca64be4efcb44c86bc37b86ce17b1292b513de9c2f07b613c798966124ded1c92d32904a5928b940f4f11e9e75bff77f804e401947036ebd896acba889de0023490f45392a271d2bfbb8c0a912092c5d314d34c785a4c59dca160b5611b9151eaa500aa813b35d33f1d4d1bed3059349362f4dbffb1ad82f911e1d23ed9cf285084722c59f2947b87499f829fdf7edf4338292af047635b46b82e8e1e262b5f837b524359e2bc3572831e23862832b698da33b82ebcc28ce048e8b9d9061de2fadecd76ac3f6304f8c86f559564ef9aca03a8efe057b3da7fa3530e342f8422cdaa56349887e92ae22f040d90e135505c8bb12b91dd9f0c2413179a5efa380fd0f292b2a3a8f80d06d0213573fbe6a0f7b3df11ceea069c1249d322697beb23d697b1e35cce2834426514ba111c8d728fe89231937c26dbc577fa242bf8127544db139078c43087b0ccee2806d76ffc08ae66480608c808812cc7c092ba1b2a54d89babd64d0ee6f644911643442d70d060e2e633dc4e6c668df6d80e325292348e9859218a8eb860ca006089d76fef266a33d2dfbb88abad72d022a93976e45cacaba7d7405dc48be530c84f961f503906aec983246c6629b07311661c8bc0ed3dbe4e4967b7ba3afaf9385fb7bedb7259c97dcec7f87689e7756cef4df4b51bfb7767c2dce8f3dd892442cf0e882f0e98572c6a1a705b25a9d73a8dde11543f5516ce7842aa15afd501ec97d2dc96f6b86f61e94d1a738c5917c5558715060d28d6c5ca778e614e3b28297c9846b5924920e3e65fb35016a3dfe525b5fb9a5011a6aee9ebbed682d19a381c388c71e52d65d9996120184b2367ca0774053b9d90fa400f6593a4049d3fa4ea8071ca0ebe868a3975e25811040cf65f4fe77d21f625d5723ed260ea9c6b4ad1be2ba6f9e9df43a6ef400cff571ab3c126591f066459a966e74e9f783d652be9d46af3bfde5995be2856c65509fb99d70077d7f80da6a5b00" ) val (header, matched) = Block.verifyTxOutProof(raw) - assertEquals(header.hash, ByteVector32("000000000000000000030cbb70966693d2516ca868fb490582dcf3dec90250f1").reversed()) + assertEquals(header.blockId, BlockId("000000000000000000030cbb70966693d2516ca868fb490582dcf3dec90250f1")) assertTrue(BlockHeader.checkProofOfWork(header)) assertEquals( matched, @@ -150,7 +162,7 @@ class BlockTestsCommon { "0000002051ac76bab033df05336c51eed091525aec9c12ea1e6c0700000000000000000033e8830654ba263225a013bc7af63a29e8b9da7f093beacabe0ee48974f62851ad7f6e5faa920e17201c2dc54104000012e008dd2119f24b941e97a9a17a6ba684f99999a8bf63f54d771d2df93098b3da3df20b78c761f58555a57cd8b073685680fe05a230bade66f031854a2ad7c561c341db5a05744eea6cb589bde17ba60c8bdafda1baf76eaeef19bbc695cda277afbd2e1e56efe478c4e6a091cdc9df49aeae76495cc7533ae1d208e371f8afec6f4991af6eff74e21a9563bfedcf3c7736c6921cda270c385e9def1e2465f0717370d6d27057b9491405071ae90395e5c5fdefc7759296287c19f9faecde9119bc0ac7eb0412de0ce63d8055c9b0b3e1128e80b29bba2ae2a1f3a6be8a72488d33bda3374730a5278c953630d316772287d9be24eaa2822bf3349894412409dfe8212ef1d3fc2a45f6b7dc6d1bddecb1e72b72d92dc0af682be1d1c2ba8878dafbeece4ef5d137a2285c8cd7975e006541592976722b82383f7c94ee2e8a8e558009546b900033594f3915d3b0b4280a91fff19dda6ef260bddf4f64ef8b8e224d9d26736c87209d8573abcaa66fa596420fb939a0910ca3d4c52f8373427236a4b5ddc77e1046806dd7c40aae3bf29e4f974717736c77e5459656658c205c700ced60a546470f5d8f344bd2645edc5a1da5229936cbbe655d12e364f344fe7934359e1c2f564e463fb142493d15c2e1a85d948d510bb63201ce4d495e67355a4d0bc04f8d5fe289ee49c6c031f6787c7d63eb3a4144ea1a13aeb717559fbeb418e07945c4b2c19c8d6f8930d79e9e264d3a989917766ea25bdcfb709948ff54aadb68adc634240b7cd287bb3bc4ddc216a956aa8518a248151940210cd8dacb067f755605ef0f" ) val (header, matched) = Block.verifyTxOutProof(raw) - assertEquals(header.hash, ByteVector32("0000000000000000000060e32d547b6ae2ded52aadbc6310808e4ae42b08cc6a").reversed()) + assertEquals(header.blockId, BlockId("0000000000000000000060e32d547b6ae2ded52aadbc6310808e4ae42b08cc6a")) assertTrue(BlockHeader.checkProofOfWork(header)) assertEquals( matched, diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/LexicographicalOrderingTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/LexicographicalOrderingTestsCommon.kt index f62a69dd..520e8229 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/LexicographicalOrderingTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/LexicographicalOrderingTestsCommon.kt @@ -30,27 +30,27 @@ class LexicographicalOrderingTestsCommon { val tx = Transaction.read( "0100000011aad553bb1650007e9982a8ac79d227cd8c831e1573b11f25573a37664e5f3e64000000006a47304402205438cedd30ee828b0938a863e08d810526123746c1f4abee5b7bc2312373450c02207f26914f4275f8f0040ab3375bacc8c5d610c095db8ed0785de5dc57456591a601210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffc26f3eb7932f7acddc5ddd26602b77e7516079b03090a16e2c2f5485d1fde028000000006b483045022100f81d98c1de9bb61063a5e6671d191b400fda3a07d886e663799760393405439d0220234303c9af4bad3d665f00277fe70cdd26cd56679f114a40d9107249d29c979401210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff456a9e597129f5df2e11b842833fc19a94c563f57449281d3cd01249a830a1f0000000006a47304402202310b00924794ef68a8f09564fd0bb128838c66bc45d1a3f95c5cab52680f166022039fc99138c29f6c434012b14aca651b1c02d97324d6bd9dd0ffced0782c7e3bd01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff571fb3e02278217852dd5d299947e2b7354a639adc32ec1fa7b82cfb5dec530e000000006b483045022100d276251f1f4479d8521269ec8b1b45c6f0e779fcf1658ec627689fa8a55a9ca50220212a1e307e6182479818c543e1b47d62e4fc3ce6cc7fc78183c7071d245839df01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff5d8de50362ff33d3526ac3602e9ee25c1a349def086a7fc1d9941aaeb9e91d38010000006b4830450221008768eeb1240451c127b88d89047dd387d13357ce5496726fc7813edc6acd55ac022015187451c3fb66629af38fdb061dfb39899244b15c45e4a7ccc31064a059730d01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff60ad3408b89ea19caf3abd5e74e7a084344987c64b1563af52242e9d2a8320f3000000006b4830450221009be4261ec050ebf33fa3d47248c7086e4c247cafbb100ea7cee4aa81cd1383f5022008a70d6402b153560096c849d7da6fe61c771a60e41ff457aac30673ceceafee01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffe9b483a8ac4129780c88d1babe41e89dc10a26dedbf14f80a28474e9a11104de010000006b4830450221009bc40eee321b39b5dc26883f79cd1f5a226fc6eed9e79e21d828f4c23190c57e022078182fd6086e265589105023d9efa4cba83f38c674a499481bd54eee196b033f01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffe28db9462d3004e21e765e03a45ecb147f136a20ba8bca78ba60ebfc8e2f8b3b000000006a47304402200fb572b7c6916515452e370c2b6f97fcae54abe0793d804a5a53e419983fae1602205191984b6928bf4a1e25b00e5b5569a0ce1ecb82db2dea75fe4378673b53b9e801210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff7a1ef65ff1b7b7740c662ab6c9735ace4a16279c23a1db5709ed652918ffff54010000006a47304402206bc218a925f7280d615c8ea4f0131a9f26e7fc64cff6eeeb44edb88aba14f1910220779d5d67231bc2d2d93c3c5ab74dcd193dd3d04023e58709ad7ffbf95161be6201210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff850cecf958468ca7ffa6a490afe13b8c271b1326b0ddc1fdfdf9f3c7e365fdba000000006a473044022047df98cc26bd2bfdc5b2b97c27aead78a214810ff023e721339292d5ce50823d02205fe99dc5f667908974dae40cc7a9475af7fa6671ba44f64a00fcd01fa12ab523012102ca46fa75454650afba1784bc7b079d687e808634411e4beff1f70e44596308a1ffffffff8640e312040e476cf6727c60ca3f4a3ad51623500aacdda96e7728dbdd99e8a5000000006a47304402205566aa84d3d84226d5ab93e6f253b57b3ef37eb09bb73441dae35de86271352a02206ee0b7f800f73695a2073a2967c9ad99e19f6ddf18ce877adf822e408ba9291e01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff91c1889c5c24b93b56e643121f7a05a34c10c5495c450504c7b5afcb37e11d7a000000006b483045022100df61d45bbaa4571cdd6c5c822cba458cdc55285cdf7ba9cd5bb9fc18096deb9102201caf8c771204df7fd7c920c4489da7bc3a60e1d23c1a97e237c63afe53250b4a01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff2470947216eb81ea0eeeb4fe19362ec05767db01c3aa3006bb499e8b6d6eaa26010000006a473044022031501a0b2846b8822a32b9947b058d89d32fc758e009fc2130c2e5effc925af70220574ef3c9e350cef726c75114f0701fd8b188c6ec5f84adce0ed5c393828a5ae001210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff0abcd77d65cc14363f8262898335f184d6da5ad060ff9e40bf201741022c2b40010000006b483045022100a6ac110802b699f9a2bff0eea252d32e3d572b19214d49d8bb7405efa2af28f1022033b7563eb595f6d7ed7ec01734e17b505214fe0851352ed9c3c8120d53268e9a01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffa43bebbebf07452a893a95bfea1d5db338d23579be172fe803dce02eeb7c037d010000006b483045022100ebc77ed0f11d15fe630fe533dc350c2ddc1c81cfeb81d5a27d0587163f58a28c02200983b2a32a1014bab633bfc9258083ac282b79566b6b3fa45c1e6758610444f401210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffb102113fa46ce949616d9cda00f6b10231336b3928eaaac6bfe42d1bf3561d6c010000006a473044022010f8731929a55c1c49610722e965635529ed895b2292d781b183d465799906b20220098359adcbc669cd4b294cc129b110fe035d2f76517248f4b7129f3bf793d07f01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffb861fab2cde188499758346be46b5fbec635addfc4e7b0c8a07c0a908f2b11b4000000006a47304402207328142bb02ef5d6496a210300f4aea71f67683b842fa3df32cae6c88b49a9bb022020f56ddff5042260cfda2c9f39b7dec858cc2f4a76a987cd2dc25945b04e15fe01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff027064d817000000001976a9144a5fba237213a062f6f57978f796390bdcf8d01588ac00902f50090000001976a9145be32612930b8323add2212a4ec03c1562084f8488ac00000000" ) - assertEquals(tx.txid, ByteVector32("0a6a357e2f7796444e02638749d9611c008b253fb55f5dc88b739b230ed0c4c3")) + assertEquals(tx.txid, TxId("0a6a357e2f7796444e02638749d9611c008b253fb55f5dc88b739b230ed0c4c3")) val tx1 = LexicographicalOrdering.sort(tx) val expected = listOf( - ByteVector32("0e53ec5dfb2cb8a71fec32dc9a634a35b7e24799295ddd5278217822e0b31f57"), - ByteVector32("26aa6e6d8b9e49bb0630aac301db6757c02e3619feb4ee0eea81eb1672947024"), - ByteVector32("28e0fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2"), - ByteVector32("381de9b9ae1a94d9c17f6a08ef9d341a5ce29e2e60c36a52d333ff6203e58d5d"), - ByteVector32("3b8b2f8efceb60ba78ca8bba206a137f14cb5ea4035e761ee204302d46b98de2"), - ByteVector32("402b2c02411720bf409eff60d05adad684f135838962823f3614cc657dd7bc0a"), - ByteVector32("54ffff182965ed0957dba1239c27164ace5a73c9b62a660c74b7b7f15ff61e7a"), - ByteVector32("643e5f4e66373a57251fb173151e838ccd27d279aca882997e005016bb53d5aa"), - ByteVector32("6c1d56f31b2de4bfc6aaea28396b333102b1f600da9c6d6149e96ca43f1102b1"), - ByteVector32("7a1de137cbafb5c70405455c49c5104ca3057a1f1243e6563bb9245c9c88c191"), - ByteVector32("7d037ceb2ee0dc03e82f17be7935d238b35d1deabf953a892a4507bfbeeb3ba4"), - ByteVector32("a5e899dddb28776ea9ddac0a502316d53a4a3fca607c72f66c470e0412e34086"), - ByteVector32("b4112b8f900a7ca0c8b0e7c4dfad35c6be5f6be46b3458974988e1cdb2fa61b8"), - ByteVector32("bafd65e3c7f3f9fdfdc1ddb026131b278c3be1af90a4a6ffa78c4658f9ec0c85"), - ByteVector32("de0411a1e97484a2804ff1dbde260ac19de841bebad1880c782941aca883b4e9"), - ByteVector32("f0a130a84912d03c1d284974f563c5949ac13f8342b8112edff52971599e6a45"), - ByteVector32("f320832a9d2e2452af63154bc687493484a0e7745ebd3aaf9ca19eb80834ad60") + TxId("0e53ec5dfb2cb8a71fec32dc9a634a35b7e24799295ddd5278217822e0b31f57"), + TxId("26aa6e6d8b9e49bb0630aac301db6757c02e3619feb4ee0eea81eb1672947024"), + TxId("28e0fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2"), + TxId("381de9b9ae1a94d9c17f6a08ef9d341a5ce29e2e60c36a52d333ff6203e58d5d"), + TxId("3b8b2f8efceb60ba78ca8bba206a137f14cb5ea4035e761ee204302d46b98de2"), + TxId("402b2c02411720bf409eff60d05adad684f135838962823f3614cc657dd7bc0a"), + TxId("54ffff182965ed0957dba1239c27164ace5a73c9b62a660c74b7b7f15ff61e7a"), + TxId("643e5f4e66373a57251fb173151e838ccd27d279aca882997e005016bb53d5aa"), + TxId("6c1d56f31b2de4bfc6aaea28396b333102b1f600da9c6d6149e96ca43f1102b1"), + TxId("7a1de137cbafb5c70405455c49c5104ca3057a1f1243e6563bb9245c9c88c191"), + TxId("7d037ceb2ee0dc03e82f17be7935d238b35d1deabf953a892a4507bfbeeb3ba4"), + TxId("a5e899dddb28776ea9ddac0a502316d53a4a3fca607c72f66c470e0412e34086"), + TxId("b4112b8f900a7ca0c8b0e7c4dfad35c6be5f6be46b3458974988e1cdb2fa61b8"), + TxId("bafd65e3c7f3f9fdfdc1ddb026131b278c3be1af90a4a6ffa78c4658f9ec0c85"), + TxId("de0411a1e97484a2804ff1dbde260ac19de841bebad1880c782941aca883b4e9"), + TxId("f0a130a84912d03c1d284974f563c5949ac13f8342b8112edff52971599e6a45"), + TxId("f320832a9d2e2452af63154bc687493484a0e7745ebd3aaf9ca19eb80834ad60") ) assertEquals(tx1.txIn.map { it.outPoint.txid }, expected) } @@ -59,19 +59,19 @@ class LexicographicalOrderingTestsCommon { fun `reference test no2`() { val tx = Transaction.read("010000000255605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df1501ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8bbe9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac00000000") - assertEquals(tx.txid, ByteVector32("28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f")) + assertEquals(tx.txid, TxId("28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f")) val tx1 = LexicographicalOrdering.sort(tx) assertEquals( tx1.txIn.map { it.outPoint }, listOf( - OutPoint(ByteVector32("35288d269cee1941eaebb2ea85e32b42cdb2b04284a56d8b14dcc3f5c65d6055").reversed(), 0), - OutPoint(ByteVector32("35288d269cee1941eaebb2ea85e32b42cdb2b04284a56d8b14dcc3f5c65d6055").reversed(), 1) + OutPoint(TxId("35288d269cee1941eaebb2ea85e32b42cdb2b04284a56d8b14dcc3f5c65d6055"), 0), + OutPoint(TxId("35288d269cee1941eaebb2ea85e32b42cdb2b04284a56d8b14dcc3f5c65d6055"), 1) ) ) assertEquals( tx1.txOut, listOf( - TxOut(100000000L.toSatoshi(), ByteVector("41046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac")), - TxOut(2400000000L.toSatoshi(), ByteVector("41044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac")) + TxOut(100_000_000.sat(), ByteVector("41046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac")), + TxOut(2_400_000_000.sat(), ByteVector("41044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac")) ) ) } diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/PowTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/PowTestsCommon.kt index f08fda81..a2988ea2 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/PowTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/PowTestsCommon.kt @@ -22,7 +22,7 @@ import kotlin.test.assertEquals class PowTestsCommon { @Test fun `calculate next work required`() { - val header = BlockHeader(version = 2, hashPreviousBlock = ByteVector32.Zeroes, hashMerkleRoot = ByteVector32.Zeroes, time = 0L, bits = 0L, nonce = 0L) + val header = BlockHeader(version = 2, hashPreviousBlock = BlockHash(ByteVector32.Zeroes), hashMerkleRoot = ByteVector32.Zeroes, time = 0L, bits = 0L, nonce = 0L) assertEquals(0x1d00d86aL, BlockHeader.calculateNextWorkRequired(header.copy(time = 1262152739, bits = 0x1d00ffff), 1261130161)) assertEquals(0x1d00ffffL, BlockHeader.calculateNextWorkRequired(header.copy(time = 1233061996, bits = 0x1d00ffff), 1231006505)) assertEquals(0x1c0168fdL, BlockHeader.calculateNextWorkRequired(header.copy(time = 1279297671, bits = 0x1c05a3f4), 1279008237)) diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/ScriptTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/ScriptTestsCommon.kt index de77ed7b..7f428814 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/ScriptTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/ScriptTestsCommon.kt @@ -77,7 +77,7 @@ class ScriptTestsCommon { fun `parse if - else - endif`() { val tx = Transaction( version = 1, - txIn = listOf(TxIn(OutPoint(ByteVector32.Zeroes, 0xffffffff), Script.write(listOf(OP_NOP)), 0xffffffff)), + txIn = listOf(TxIn(OutPoint(TxHash(ByteVector32.Zeroes), 0xffffffff), Script.write(listOf(OP_NOP)), 0xffffffff)), txOut = listOf(TxOut(0x12a05f200L.sat(), ByteVector.empty)), lockTime = 0 ) diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/SegwitTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/SegwitTestsCommon.kt index 5fb917e1..6febd46b 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/SegwitTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/SegwitTestsCommon.kt @@ -152,7 +152,7 @@ class SegwitTestsCommon { } Transaction.correctlySpends(tx2, listOf(tx1), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) - assertEquals(tx2.txid, ByteVector32("f25b3fecc9652466926237d96e4bc7ee2c984051fe48e61417aba218af5570c3")) + assertEquals(tx2.txid, TxId("f25b3fecc9652466926237d96e4bc7ee2c984051fe48e61417aba218af5570c3")) // this tx was published on testnet as f25b3fecc9652466926237d96e4bc7ee2c984051fe48e61417aba218af5570c3 // and now we create a testnet tx that spends the P2WPK output @@ -185,7 +185,7 @@ class SegwitTestsCommon { } Transaction.correctlySpends(tx3, listOf(tx2), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) - assertEquals(tx3.txid, ByteVector32("739e7cba97af259d2c089690adea00aa78b1c8d7995aa9377be58fe5332378aa")) + assertEquals(tx3.txid, TxId("739e7cba97af259d2c089690adea00aa78b1c8d7995aa9377be58fe5332378aa")) // this tx was published on testnet as 739e7cba97af259d2c089690adea00aa78b1c8d7995aa9377be58fe5332378aa } @@ -240,7 +240,7 @@ class SegwitTestsCommon { tmp.updateSigScript(0, listOf(OP_PUSHDATA(sig), OP_PUSHDATA(pub1))) } Transaction.correctlySpends(tx2, listOf(tx1), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) - assertEquals(tx2.txid, ByteVector32("2f8360a06a31ca642d717b1857aa86b3306fc554fa9c437d88b4bc61b7f2b3e9")) + assertEquals(tx2.txid, TxId("2f8360a06a31ca642d717b1857aa86b3306fc554fa9c437d88b4bc61b7f2b3e9")) // this tx was published on testnet as 2f8360a06a31ca642d717b1857aa86b3306fc554fa9c437d88b4bc61b7f2b3e9 // and now we create a segwit tx that spends the P2WSH output @@ -275,7 +275,7 @@ class SegwitTestsCommon { } Transaction.correctlySpends(tx3, listOf(tx2), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) - assertEquals(tx3.txid, ByteVector32("4817f79def9d9f559ddaa636f0c196e79f31bc959feead77b4151733114c652a")) + assertEquals(tx3.txid, TxId("4817f79def9d9f559ddaa636f0c196e79f31bc959feead77b4151733114c652a")) // this tx was published on testnet as 4817f79def9d9f559ddaa636f0c196e79f31bc959feead77b4151733114c652a } @@ -323,7 +323,7 @@ class SegwitTestsCommon { } Transaction.correctlySpends(tx1, listOf(tx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) - assertEquals(tx1.txid, ByteVector32("4807cb10f50df84acd7766245133f902d22d91b7e8bfe77c4bbcb0cf9b017a86")) + assertEquals(tx1.txid, TxId("4807cb10f50df84acd7766245133f902d22d91b7e8bfe77c4bbcb0cf9b017a86")) // this tx was published on testnet as 4807cb10f50df84acd7766245133f902d22d91b7e8bfe77c4bbcb0cf9b017a86 } } diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/TaprootTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/TaprootTestsCommon.kt index 41042d69..6d133aaf 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/TaprootTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/TaprootTestsCommon.kt @@ -250,7 +250,9 @@ class TaprootTestsCommon { val sweepPublicKeyScript = addressToPublicKeyScript(blockchain, "tb1qxy9hhxkw7gt76qrm4yzw4j06gkk4evryh8ayp7").result!! // see https://mempool.space/signet/tx/c284010f06b5182e9f4722ce3474980339b1fc76e5ff29ece812f5d2162595c1 - val fundingTx = Transaction.read("020000000001017034061243a7770f791aa2afdb118be900f4f8fc755a36d8632213acc139bab20100000000feffffff0200e1f50500000000225120f1d062d20433c023ba934aec75fa78cf8e2f840181b88c301430524aad93d0fbc192ac1700000000160014b66f2e807b9f4adecb99ad811dde501ca3f0fd5f02473044022046a2fd077e12b1d7ba74f6e7ac469deb3e3755c100216abad667980fc39463dc022018b63cfaf72fde0b5ca10c617aeaa0015013bd06ef08f82eea500c6467d963cc0121030b50ec81d958ae79d34d3579faf72456213d7d581a908e2b64d21b96777882043ab10100") + val fundingTx = Transaction.read( + "020000000001017034061243a7770f791aa2afdb118be900f4f8fc755a36d8632213acc139bab20100000000feffffff0200e1f50500000000225120f1d062d20433c023ba934aec75fa78cf8e2f840181b88c301430524aad93d0fbc192ac1700000000160014b66f2e807b9f4adecb99ad811dde501ca3f0fd5f02473044022046a2fd077e12b1d7ba74f6e7ac469deb3e3755c100216abad667980fc39463dc022018b63cfaf72fde0b5ca10c617aeaa0015013bd06ef08f82eea500c6467d963cc0121030b50ec81d958ae79d34d3579faf72456213d7d581a908e2b64d21b96777882043ab10100" + ) // output #1 is the one we want to spend assertEquals(fundingTx.txOut[0].publicKeyScript, script) @@ -271,11 +273,16 @@ class TaprootTestsCommon { } // see: https://mempool.space/signet/tx/de3e4dcf07e68c7b237269eee75b926b9d147869f6317031b0550dcbf509ff5b - assertEquals(tx.toString(), "02000000000101c1952516d2f512e8ec29ffe576fcb13903987434ce22479f2e18b5060f0184c20000000000ffffffff0178cdf50500000000160014310b7b9acef217ed007ba904eac9fa45ad5cb064014004174022193d585759ce094bbe47ff23eef0238aaa89a89a0d04c80fa321c9b9056623282c49cfa7388409af5ef9a1ab7e3733b72637edcfb15019018d4d7f5a00000000") + assertEquals( + tx.toString(), + "02000000000101c1952516d2f512e8ec29ffe576fcb13903987434ce22479f2e18b5060f0184c20000000000ffffffff0178cdf50500000000160014310b7b9acef217ed007ba904eac9fa45ad5cb064014004174022193d585759ce094bbe47ff23eef0238aaa89a89a0d04c80fa321c9b9056623282c49cfa7388409af5ef9a1ab7e3733b72637edcfb15019018d4d7f5a00000000" + ) Transaction.correctlySpends(tx, fundingTx, ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) // see https://mempool.space/signet/tx/193962bdc619a1c6f28e3989603a229055b544ee9e12c5ca8cc0a694babd8506 - val fundingTx1 = Transaction.read("020000000001032c94e663cbee0edbdb4375bb2e79be60f8ecfa4e936a14e9a054b1c8923928570000000000feffffff308788df38f369e33bcd70765c171a9796d910b02525a550bfe4d2a2cf8a710c0100000000feffffff94dc10cd523655b0323e90428d720b378b91de312e56908325df6878c530d30d0000000000feffffff0200e1f50500000000225120f1d062d20433c023ba934aec75fa78cf8e2f840181b88c301430524aad93d0fb8b4f174e020000001600140e361914cb87862fb6ea24193331d6591b59859002463043021f5dcc64a2fef28bdd2b88b5d10851079cc98663a1284d0569bdde5afc558fb202205c2bcdcf1dae62b2c32e8cf6ac6cb2534b70b1889be893da170564a8c4d40f2001210270b71142cd209ddd686ef013adaeb12b641fde95d589a5a607ee0b6c95cc086202473044022034121d55d61376aee90f6b975522b6bad85491448d527b83f6dacbdddcd9548202201a0a9405542ae06239fabdc01069fe2518ee7340ed400d4db2d92604f9d454d601210319b3ad1b37d95ab41034cd810799149501e62ab6d009a6a4eca6034f78ca725b024730440220487663d7740eaa5370673f4807497970feb2d69c83cae281d89fef8aa616259a02200a21dc493e455c2980bc245224eb67aba576f732f77af0fd555a5f44fa205e4d0121023a34e31279a234431b349fd229790038c95c837a8139862df9cbb1226d63c4003eb10100") + val fundingTx1 = Transaction.read( + "020000000001032c94e663cbee0edbdb4375bb2e79be60f8ecfa4e936a14e9a054b1c8923928570000000000feffffff308788df38f369e33bcd70765c171a9796d910b02525a550bfe4d2a2cf8a710c0100000000feffffff94dc10cd523655b0323e90428d720b378b91de312e56908325df6878c530d30d0000000000feffffff0200e1f50500000000225120f1d062d20433c023ba934aec75fa78cf8e2f840181b88c301430524aad93d0fb8b4f174e020000001600140e361914cb87862fb6ea24193331d6591b59859002463043021f5dcc64a2fef28bdd2b88b5d10851079cc98663a1284d0569bdde5afc558fb202205c2bcdcf1dae62b2c32e8cf6ac6cb2534b70b1889be893da170564a8c4d40f2001210270b71142cd209ddd686ef013adaeb12b641fde95d589a5a607ee0b6c95cc086202473044022034121d55d61376aee90f6b975522b6bad85491448d527b83f6dacbdddcd9548202201a0a9405542ae06239fabdc01069fe2518ee7340ed400d4db2d92604f9d454d601210319b3ad1b37d95ab41034cd810799149501e62ab6d009a6a4eca6034f78ca725b024730440220487663d7740eaa5370673f4807497970feb2d69c83cae281d89fef8aa616259a02200a21dc493e455c2980bc245224eb67aba576f732f77af0fd555a5f44fa205e4d0121023a34e31279a234431b349fd229790038c95c837a8139862df9cbb1226d63c4003eb10100" + ) assertEquals(fundingTx1.txOut[0].publicKeyScript, script) // spending with script #1 @@ -297,11 +304,16 @@ class TaprootTestsCommon { } // see: https://mempool.space/signet/tx/5586515f9ed7fce8b7e8be97a8681c298a94166ff95e15edd94226edec50d9ea - assertEquals(tx1.toString(), "020000000001010685bdba94a6c08ccac5129eee44b55590223a6089398ef2c6a119c6bd6239190000000000ffffffff0178cdf50500000000160014310b7b9acef217ed007ba904eac9fa45ad5cb0640340c6aaa48614bfa03b8cb3c56c84df6214ca223d11b63a7d2dbd67ad4dbb13ccc5ee26890e68b655dfa371fefe8e0117eee854fc3538cbe453ebe6c9ae9d12111022201b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078fac61c01b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f4b756b9676af737379eb8b2767da3e68df7b59757b9f67cb0d21bb5a63ccc1a8a7b49fc07e0495843b92705136c98e1e64d19bf40303f0c2e32d9c58413b770200000000") + assertEquals( + tx1.toString(), + "020000000001010685bdba94a6c08ccac5129eee44b55590223a6089398ef2c6a119c6bd6239190000000000ffffffff0178cdf50500000000160014310b7b9acef217ed007ba904eac9fa45ad5cb0640340c6aaa48614bfa03b8cb3c56c84df6214ca223d11b63a7d2dbd67ad4dbb13ccc5ee26890e68b655dfa371fefe8e0117eee854fc3538cbe453ebe6c9ae9d12111022201b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078fac61c01b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f4b756b9676af737379eb8b2767da3e68df7b59757b9f67cb0d21bb5a63ccc1a8a7b49fc07e0495843b92705136c98e1e64d19bf40303f0c2e32d9c58413b770200000000" + ) Transaction.correctlySpends(tx1, fundingTx1, ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) // see https://mempool.space/signet/tx/b4dfa342b434709e1b4fd46a2caf7661a195267445ba4402bb2364b174edc5a6 - val fundingTx2 = Transaction.read("02000000000101c1952516d2f512e8ec29ffe576fcb13903987434ce22479f2e18b5060f0184c20100000000feffffff0200e1f50500000000225120f1d062d20433c023ba934aec75fa78cf8e2f840181b88c301430524aad93d0fb28b1b61100000000160014665ea2d5f8f03b7edc82472baed5ba28dcd22a9f024730440220014381ea4fc0e96733231b84bf9d24ee6d197147c2d2842c896530103c9c23310220384d174f4578767f2117c558671e592ea497f0680cedbacc73dc3f4c316f6b73012102d2212f3a1ef1a797be1fbe8ac784eb81158957339cab89e32faa6f73cc9bf6713fb10100") + val fundingTx2 = Transaction.read( + "02000000000101c1952516d2f512e8ec29ffe576fcb13903987434ce22479f2e18b5060f0184c20100000000feffffff0200e1f50500000000225120f1d062d20433c023ba934aec75fa78cf8e2f840181b88c301430524aad93d0fb28b1b61100000000160014665ea2d5f8f03b7edc82472baed5ba28dcd22a9f024730440220014381ea4fc0e96733231b84bf9d24ee6d197147c2d2842c896530103c9c23310220384d174f4578767f2117c558671e592ea497f0680cedbacc73dc3f4c316f6b73012102d2212f3a1ef1a797be1fbe8ac784eb81158957339cab89e32faa6f73cc9bf6713fb10100" + ) assertEquals(fundingTx2.txOut[0].publicKeyScript, script) // spending with script #2 @@ -324,11 +336,16 @@ class TaprootTestsCommon { } // see: https://mempool.space/signet/tx/5586515f9ed7fce8b7e8be97a8681c298a94166ff95e15edd94226edec50d9ea - assertEquals(tx2.toString(), "02000000000101a6c5ed74b16423bb0244ba45742695a16176af2c6ad44f1b9e7034b442a3dfb40000000000ffffffff0178cdf50500000000160014310b7b9acef217ed007ba904eac9fa45ad5cb06403409ded7b5094a959650a725f4c1d87f5ba17904a14085ad5ec65c4b2ebb817c8e9193a31091ad3c9ac393bc394dd2a85f2456908cc2209760540e5094b32ccec392220c050c3f0b8d45b9e093a91cb96d097b24100e66585d0d8561e01c1231837493fac61c01b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078fb3377ed08656d10020a2669defa10b1493771fbd61be8e3dbe2d8232a6b9805ca7b49fc07e0495843b92705136c98e1e64d19bf40303f0c2e32d9c58413b770200000000") + assertEquals( + tx2.toString(), + "02000000000101a6c5ed74b16423bb0244ba45742695a16176af2c6ad44f1b9e7034b442a3dfb40000000000ffffffff0178cdf50500000000160014310b7b9acef217ed007ba904eac9fa45ad5cb06403409ded7b5094a959650a725f4c1d87f5ba17904a14085ad5ec65c4b2ebb817c8e9193a31091ad3c9ac393bc394dd2a85f2456908cc2209760540e5094b32ccec392220c050c3f0b8d45b9e093a91cb96d097b24100e66585d0d8561e01c1231837493fac61c01b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078fb3377ed08656d10020a2669defa10b1493771fbd61be8e3dbe2d8232a6b9805ca7b49fc07e0495843b92705136c98e1e64d19bf40303f0c2e32d9c58413b770200000000" + ) Transaction.correctlySpends(tx2, fundingTx2, ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) // see https://mempool.space/signet/tx/97196e1dc3ee089955d2a738143a66a34166d0c7f0a85d8ad4ba2c972dc0555c - val fundingTx3 = Transaction.read("020000000001025bff09f5cb0d55b0317031f66978149d6b925be7ee6972237b8ce607cf4d3ede0000000000feffffffead950eced2642d9ed155ef96f16948a291c68a897bee8b7e8fcd79e5f5186550000000000feffffff0214b9f50500000000160014faf51bb67e3e35a93aa549cf2c8d24763d8162ce00e1f50500000000225120f1d062d20433c023ba934aec75fa78cf8e2f840181b88c301430524aad93d0fb0247304402201989eb9d1f4d976a9f0bf512e7f1fa784c45eee369a6c13511162a463c89935002201a1d41e53c56600137a851d0c26daaffd6aa30197fbf9221daf6cbca458fb40f012102238ee9a8b833398e3421c809e7ac75089e4e738841577273fe87d3cd14a22cf202473044022035e887ced3bb03f54cce39e4cdecf93b787765c51de2545a16c97fec67d3085b02200bd15d5497d1a9be37ad29142673ef2cdc0cee69f6a9cf5643c376a4b4f81489012102238ee9a8b833398e3421c809e7ac75089e4e738841577273fe87d3cd14a22cf290b10100") + val fundingTx3 = Transaction.read( + "020000000001025bff09f5cb0d55b0317031f66978149d6b925be7ee6972237b8ce607cf4d3ede0000000000feffffffead950eced2642d9ed155ef96f16948a291c68a897bee8b7e8fcd79e5f5186550000000000feffffff0214b9f50500000000160014faf51bb67e3e35a93aa549cf2c8d24763d8162ce00e1f50500000000225120f1d062d20433c023ba934aec75fa78cf8e2f840181b88c301430524aad93d0fb0247304402201989eb9d1f4d976a9f0bf512e7f1fa784c45eee369a6c13511162a463c89935002201a1d41e53c56600137a851d0c26daaffd6aa30197fbf9221daf6cbca458fb40f012102238ee9a8b833398e3421c809e7ac75089e4e738841577273fe87d3cd14a22cf202473044022035e887ced3bb03f54cce39e4cdecf93b787765c51de2545a16c97fec67d3085b02200bd15d5497d1a9be37ad29142673ef2cdc0cee69f6a9cf5643c376a4b4f81489012102238ee9a8b833398e3421c809e7ac75089e4e738841577273fe87d3cd14a22cf290b10100" + ) assertEquals(fundingTx3.txOut[1].publicKeyScript, script) // spending with script #3 @@ -349,7 +366,10 @@ class TaprootTestsCommon { } // see: https://mempool.space/signet/tx/2eb421e044de0535aa3d14a5a4c325ba8b5181440bbd911b5b43718b686b09a8 - assertEquals(tx3.toString(), "020000000001015c55c02d972cbad48a5da8f0c7d06641a3663a1438a7d2559908eec31d6e19970100000000ffffffff018ca5f50500000000160014310b7b9acef217ed007ba904eac9fa45ad5cb0640340c10da2636457db468385345303e984ee949d0815745f5dcba67cde603ef02738b6f26f6c44beef0a93d9fcbb82571d215ca2cf04a1894ce01d2eaf7b6068260a2220a4fbd2c1822592c0ae8afa0e63a0d4c56a571179e93fd61615627f419fd0be9aac41c01b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f35b9c8be6dc0c33d6ce3cc9d3ba04c509b3f5b0139254f67d3184a5a238901f400000000") + assertEquals( + tx3.toString(), + "020000000001015c55c02d972cbad48a5da8f0c7d06641a3663a1438a7d2559908eec31d6e19970100000000ffffffff018ca5f50500000000160014310b7b9acef217ed007ba904eac9fa45ad5cb0640340c10da2636457db468385345303e984ee949d0815745f5dcba67cde603ef02738b6f26f6c44beef0a93d9fcbb82571d215ca2cf04a1894ce01d2eaf7b6068260a2220a4fbd2c1822592c0ae8afa0e63a0d4c56a571179e93fd61615627f419fd0be9aac41c01b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f35b9c8be6dc0c33d6ce3cc9d3ba04c509b3f5b0139254f67d3184a5a238901f400000000" + ) Transaction.correctlySpends(tx3, fundingTx3, ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) } @@ -362,7 +382,9 @@ class TaprootTestsCommon { file.close() val tx = Transaction.read(buffer) assertEquals(1001, tx.txIn[0].witness.stack.size) - val parentTx = Transaction.read("020000000001011c0bf7a36ae6f663be6424d8fb84672fec0c2efb9753630675d1fe9836785fff0000000000fdffffff02906500000000000022512056e1005938333d0095cd0b7225e47216417619867bc12ae91c5b61cbc95a315ef5e6010000000000160014dbd208b293eaae96ded0424695f68718b97cd8290247304402206c1d49b0c0afc55e48b3ff56ab09c71be9f52a38ca69e88b89fbee437cdf68df02201984d8e67629b5a8dd477d09fb3abae18e98d33c41f2b57696f98c1d90af807201210331a2f9b23d7dbb4eb51050b1d35a88b608e48cc6e48c23051b362a498887fc8600000000") + val parentTx = Transaction.read( + "020000000001011c0bf7a36ae6f663be6424d8fb84672fec0c2efb9753630675d1fe9836785fff0000000000fdffffff02906500000000000022512056e1005938333d0095cd0b7225e47216417619867bc12ae91c5b61cbc95a315ef5e6010000000000160014dbd208b293eaae96ded0424695f68718b97cd8290247304402206c1d49b0c0afc55e48b3ff56ab09c71be9f52a38ca69e88b89fbee437cdf68df02201984d8e67629b5a8dd477d09fb3abae18e98d33c41f2b57696f98c1d90af807201210331a2f9b23d7dbb4eb51050b1d35a88b608e48cc6e48c23051b362a498887fc8600000000" + ) Transaction.correctlySpends(tx, parentTx, ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) // check that we can also serialize this tx and get the same result @@ -374,7 +396,9 @@ class TaprootTestsCommon { fun `parse and validate huge transaction enabled by OP_SUCCESSx`() { // construct large taproot tx: 73be398c4bdc43709db7398106609eea2a7841aaf3a4fa2000dc18184faa2a7e // this is the tx that broke btcd/lnd: https://github.com/btcsuite/btcd/issues/1906 - val parentTx = Transaction.read("0200000000010219d3bdb21c713911fe18cf2dbe8dde9e85c2bdde76139a30c725a7f0115a983b0100000000fdffffffb9da566f902363594ce178f8b32e92a45fec5860e1121aae58b15178fbd3fb670000000000fdffffff019f313800000000002251209bb9efbddf9d70afd3ac2cef011747236bdf90832a78b08f57d1139f07aa9185024730440220146d18445bd3fb00f5140e4ef886cff7b432c55911730483a202abfe8ca43880022074e143eec20286df9ab06194a638dbbdaa7ef3001c252f9b83c8270a608ce04a01210349e84631e7d206600f72fc30d43fa9004171c5d314ea9f88e92687394b2560f3024730440220140c1888004c649a7ca4135bc9e4fe10fd4bf30264126a248ad9c5c762a387e702204de3da8bf5304abe05fba690a91eed2cab59444592be520640280ee7f1b5467401210290d5dab3b51ae9293d07ace66bdfa6bbaa5f398d1a5464b2ede4d41104aae97e00000000") + val parentTx = Transaction.read( + "0200000000010219d3bdb21c713911fe18cf2dbe8dde9e85c2bdde76139a30c725a7f0115a983b0100000000fdffffffb9da566f902363594ce178f8b32e92a45fec5860e1121aae58b15178fbd3fb670000000000fdffffff019f313800000000002251209bb9efbddf9d70afd3ac2cef011747236bdf90832a78b08f57d1139f07aa9185024730440220146d18445bd3fb00f5140e4ef886cff7b432c55911730483a202abfe8ca43880022074e143eec20286df9ab06194a638dbbdaa7ef3001c252f9b83c8270a608ce04a01210349e84631e7d206600f72fc30d43fa9004171c5d314ea9f88e92687394b2560f3024730440220140c1888004c649a7ca4135bc9e4fe10fd4bf30264126a248ad9c5c762a387e702204de3da8bf5304abe05fba690a91eed2cab59444592be520640280ee7f1b5467401210290d5dab3b51ae9293d07ace66bdfa6bbaa5f398d1a5464b2ede4d41104aae97e00000000" + ) val count = 500001 val tx = Transaction( version = 2L, @@ -387,8 +411,8 @@ class TaprootTestsCommon { val stack = Array(count) { ByteVector("") }.toList() val witness = ScriptWitness(stack + opSuccess + sig) // must not exceed available Java heap space val tx2 = tx.updateWitness(0, witness) //, op, sig) - assertEquals(count+2, tx2.txIn[0].witness.stack.size) - assertEquals(ByteVector32("73be398c4bdc43709db7398106609eea2a7841aaf3a4fa2000dc18184faa2a7e"), tx.txid) + assertEquals(count + 2, tx2.txIn[0].witness.stack.size) + assertEquals(TxId("73be398c4bdc43709db7398106609eea2a7841aaf3a4fa2000dc18184faa2a7e"), tx.txid) assertFails { // invalid and not relayed by nodes with default policy settings because of OP_SUCCESSx in the script @@ -409,7 +433,9 @@ class TaprootTestsCommon { file.readBytes(buffer) file.close() val tx = Transaction.read(buffer) - val parentTx = Transaction.read("0100000000010273721ae5e7d59775f7104670fc8f74e9dee6fe57de47a2ebc14c95cafe4241050000000000fdffffff73721ae5e7d59775f7104670fc8f74e9dee6fe57de47a2ebc14c95cafe4241050100000000fdffffff025459f00200000000225120ca991d5bfbc6840c7568146e305f9eb67d8650948b1f929e941659b2649195941ea50c000000000022512051bf94b8b1d63574a47847d5fdccf2c90953189fa0220cf8f2d6284cf60e5f820140a844d30c2231d6e9c370b094200004475f21545efbd548a6f374ea956e2eea51d62d7048350130bc2fca3a5517ffe34d9e02d150ac58aba2920c88acb3cfc7fe014089d904d0be731c542ef9fe623b19502483348b1b6e0c9058e31c5ebd755070a27aa7dea288b839e2853da70607ea35851394f887e71c1ed58f15bf661969aa5900000000") + val parentTx = Transaction.read( + "0100000000010273721ae5e7d59775f7104670fc8f74e9dee6fe57de47a2ebc14c95cafe4241050000000000fdffffff73721ae5e7d59775f7104670fc8f74e9dee6fe57de47a2ebc14c95cafe4241050100000000fdffffff025459f00200000000225120ca991d5bfbc6840c7568146e305f9eb67d8650948b1f929e941659b2649195941ea50c000000000022512051bf94b8b1d63574a47847d5fdccf2c90953189fa0220cf8f2d6284cf60e5f820140a844d30c2231d6e9c370b094200004475f21545efbd548a6f374ea956e2eea51d62d7048350130bc2fca3a5517ffe34d9e02d150ac58aba2920c88acb3cfc7fe014089d904d0be731c542ef9fe623b19502483348b1b6e0c9058e31c5ebd755070a27aa7dea288b839e2853da70607ea35851394f887e71c1ed58f15bf661969aa5900000000" + ) Transaction.correctlySpends(tx, parentTx, ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) // check that we can also serialize this tx and get the same result diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/TransactionTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/TransactionTestsCommon.kt index e6e77aa7..4ecaabb3 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/TransactionTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/TransactionTestsCommon.kt @@ -46,7 +46,7 @@ class TransactionTestsCommon { val tx = Transaction.read(hex, Protocol.PROTOCOL_VERSION or Transaction.SERIALIZE_TRANSACTION_NO_WITNESS) assertEquals(tx.version, 2) assertTrue(tx.txIn.isEmpty()) - assertEquals(tx.txid, ByteVector32("062d74b3c6183147c30a02addf3c8cd0df10a049ced5677247edd8f114ddb6fb")) + assertEquals(tx.txid, TxId("062d74b3c6183147c30a02addf3c8cd0df10a049ced5677247edd8f114ddb6fb")) assertEquals(tx.txOut.size, 2) assertEquals(tx.txOut[0].publicKeyScript, ByteVector(Script.write(listOf(OP_DUP, OP_HASH160, OP_PUSHDATA(ByteVector("d0c59903c5bac2868760e90fd521a4665aa76520")), OP_EQUALVERIFY, OP_CHECKSIG)))) assertEquals(tx.txOut[1].publicKeyScript, ByteVector(Script.write(listOf(OP_HASH160, OP_PUSHDATA(ByteVector("3545e6e33b832c47050f24d3eeb93c9c03948bc7")), OP_EQUAL)))) @@ -98,7 +98,7 @@ class TransactionTestsCommon { ) // step #2: sign the tx - val sig = Transaction.signInput(tx1, 0, previousTx.txOut[0].publicKeyScript, SigHash.SIGHASH_ALL, privateKey) + val sig = Transaction.signInput(tx1, 0, previousTx.txOut[0].publicKeyScript, SIGHASH_ALL, privateKey) val tx2 = tx1.updateSigScript(0, listOf(OP_PUSHDATA(sig), OP_PUSHDATA(publicKey))) // redeem the tx @@ -147,7 +147,7 @@ class TransactionTestsCommon { ) // and sign it - val sig = Transaction.signInput(tx, 0, previousTx.txOut[0].publicKeyScript, SigHash.SIGHASH_ALL, privateKey) + val sig = Transaction.signInput(tx, 0, previousTx.txOut[0].publicKeyScript, SIGHASH_ALL, privateKey) val signedTx = tx.updateSigScript(0, listOf(OP_PUSHDATA(sig), OP_PUSHDATA(privateKey.publicKey().toUncompressedBin()))) Transaction.correctlySpends(signedTx, listOf(previousTx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) @@ -167,8 +167,8 @@ class TransactionTestsCommon { ) // we need at least 2 signatures - val sig1 = Transaction.signInput(spendingTx, 0, redeemScript, SigHash.SIGHASH_ALL, key1) - val sig2 = Transaction.signInput(spendingTx, 0, redeemScript, SigHash.SIGHASH_ALL, key2) + val sig1 = Transaction.signInput(spendingTx, 0, redeemScript, SIGHASH_ALL, key1) + val sig2 = Transaction.signInput(spendingTx, 0, redeemScript, SIGHASH_ALL, key2) // update our tx with the correct sig script val sigScript = listOf(OP_0, OP_PUSHDATA(sig1), OP_PUSHDATA(sig2), OP_PUSHDATA(redeemScript)) @@ -215,7 +215,7 @@ class TransactionTestsCommon { .updateSigScript(0, listOf(OP_PUSHDATA(sig1), OP_PUSHDATA(keys[0].publicKey().value))) .updateSigScript(1, listOf(OP_PUSHDATA(sig2), OP_PUSHDATA(keys[1].publicKey().toUncompressedBin()))) - assertEquals(ByteVector32("882e971dbdb7b762cd07e5db016d3c81267ec5233186a31e6f40457a0a56a311"), tx1.txid) + assertEquals(TxId("882e971dbdb7b762cd07e5db016d3c81267ec5233186a31e6f40457a0a56a311"), tx1.txid) assertEquals( "01000000026c8a0bb4fef409509800066578a718e9a771082d94e96e0885a4b6a15b720c02000000006b483045022100e5510a2f15f03788ee2aeb2115edc96089596e3a0f0c1b1abfbbf069f4beedb802203faf6ec92a5a4ed2ce5fd42621be99746b57eca0eb46d322dc076080338b6c5a0121030533e1d2e9b7576fef26de1f34d67887158b7af1b040850aab6024b07925d70affffffffaf01f14881716b8acb062c33e7a66fc71e77bb2e4359b1f91b959aeb4f8837f1000000008b483045022100d3e5756f36e39a801c71c406124b3e0a66f0893a7fea46c69939b84715137c40022070a0e96e37c0a8e8c920e84fc63ed1914b4cef114a027f2d027d0a4a04b0b52d0141040081a4cce4c497d51d2f9be2d2109c00cbdef252185ca23074889604ace3504d73fd5f5aaac6423b04e776e467a948e1e79cb8793ded5f4b59c730c4460a0f86ffffffff02c0c62d00000000001976a914558c6b340f5abd22bf97b15cbc1483f8f1b54f5f88aca0f01900000000001976a914a1f93b5b00f9f5e8ade5549b58ed06cdc5c8203e88ac00000000", tx1.toString(), @@ -274,7 +274,7 @@ class TransactionTestsCommon { .updateSigScript(1, listOf(OP_PUSHDATA(sig2), OP_PUSHDATA(keys[1].publicKey().toUncompressedBin()))) .updateSigScript(2, listOf(OP_PUSHDATA(sig3), OP_PUSHDATA(keys[2].publicKey().toUncompressedBin()))) - assertEquals(signedTx.txid, ByteVector32("e8570dd062de8e354b18f6308ff739a51f25db75563c4ee2bc5849281263528f")) + assertEquals(signedTx.txid, TxId("e8570dd062de8e354b18f6308ff739a51f25db75563c4ee2bc5849281263528f")) assertEquals( "0100000003864d5e5ec82c9e6f4ac52b8fa47b77f8616bbc26fcf668432c097c5add169584010000006a47304402203be0cff1faacadce3b02d615a8ac15532f9a90bd30e109eaa3e01bfa3a97d90b0220355f3bc382e35b9cae24e5d674f200b289bb948675ce1b5c931029ccb23ae836012102fd18c2a069488288ae93c2157dff3fd657a39426e8753512a5547f046b4a2cbbffffffffd587b10688e6d56225dd4dc488b74229a353e4613cbe1deadaef52b56616baa9000000008b483045022100ab98145e8526b32e821beeaed41a98da68c3c75ee13c477ee0e3d66a626217e902204d015af2e7dba834bbe421dd0b1353a1060dafee58c284dd763e07639858f9340141043ca81d9fe7996372eb21b2588af07c7fbdb6d4fc1da13aaf953c520ba1da4f87d53dfcba3525369fdb248e60233fdf6df0a8183a6dd5699c9a6f5c537367c627ffffffff94a162b4aab080a09fa982a5d7f586045ba2a4c653c98ff47b952d43c25b45fd000000008a47304402200e0c0223d169282a48731b58ff0673c00205deb3f3f4f28d99b50730ada1571402202fa9f051762d8e0199791ea135df1f393578c1eea530bec00fa16f6bba7e3aa3014104626f9b06c44bcfd5d2f6bdeab456591287e2d2b2e299815edf0c9fd0f23c21364ed5dbe97c9c6e2be40fff40c31f8561a9dee015146fe59ecf68b8a377292c72ffffffff02c0c62d00000000001976a914e410e8bc694e8a39c32a273eb1d71930f63648fe88acc0cf6a00000000001976a914324505870d6f21dca7d2f90642cd9603553f6fa688ac00000000", signedTx.toString() diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/psbt/PsbtTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/psbt/PsbtTestsCommon.kt index 5a5f3661..eec88935 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/psbt/PsbtTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/psbt/PsbtTestsCommon.kt @@ -179,7 +179,7 @@ class PsbtTestsCommon { fun `invalids psbts -- non-witness input utxos don't match tx`() { val inputTx1 = Transaction( version = 2, - txIn = listOf(TxIn(OutPoint(ByteVector32("75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858"), 1), ByteVector("00208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903"), 0)), + txIn = listOf(TxIn(OutPoint(TxHash("75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858"), 1), ByteVector("00208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903"), 0)), txOut = listOf( TxOut(500.toSatoshi(), ByteVector("0014d85c2b71d0060b09c9886aeb815e50991dda124d")), TxOut(750.toSatoshi(), ByteVector("0014d85c2b71d0060b09c9886aeb815e50991dda124d")) @@ -188,7 +188,7 @@ class PsbtTestsCommon { ) val inputTx2 = Transaction( version = 2, - txIn = listOf(TxIn(OutPoint(ByteVector32("1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83"), 0), ByteVector("00208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903"), 0)), + txIn = listOf(TxIn(OutPoint(TxHash("1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83"), 0), ByteVector("00208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903"), 0)), txOut = listOf( TxOut(800.toSatoshi(), ByteVector("0014d85c2b71d0060b09c9886aeb815e50991dda124d")), TxOut(600.toSatoshi(), ByteVector("0014d85c2b71d0060b09c9886aeb815e50991dda124d")) @@ -469,8 +469,8 @@ class PsbtTestsCommon { val unsignedTx = Transaction( version = 2, txIn = listOf( - TxIn(OutPoint(ByteVector32("75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858").reversed(), 0), listOf(), TxIn.SEQUENCE_FINAL), - TxIn(OutPoint(ByteVector32("1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83").reversed(), 1), listOf(), TxIn.SEQUENCE_FINAL) + TxIn(OutPoint(TxId("75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858"), 0), listOf(), TxIn.SEQUENCE_FINAL), + TxIn(OutPoint(TxId("1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83"), 1), listOf(), TxIn.SEQUENCE_FINAL) ), txOut = listOf( TxOut(149_990_000.toSatoshi(), ByteVector("0014d85c2b71d0060b09c9886aeb815e50991dda124d")), @@ -785,11 +785,11 @@ class PsbtTestsCommon { @Test fun `join PSBTs`() { - val input1 = TxIn(OutPoint(ByteVector32("2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"), 0), ByteVector("2a"), 42) + val input1 = TxIn(OutPoint(TxHash("2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"), 0), ByteVector("2a"), 42) val output1 = TxOut(500.toSatoshi(), ByteVector("2a2a")) val psbt1 = Psbt(Transaction(2, listOf(input1), listOf(output1), 0)) - val input2 = TxIn(OutPoint(ByteVector32("2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"), 3), ByteVector("2a2a2a"), 0) + val input2 = TxIn(OutPoint(TxHash("2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"), 3), ByteVector("2a2a2a"), 0) val psbt2 = Psbt(Transaction(2, listOf(input2), listOf(), 0)) val output2 = TxOut(1200.toSatoshi(), ByteVector("2a2a2a2a2a")) @@ -803,8 +803,8 @@ class PsbtTestsCommon { joined.right!!.global.tx, Transaction( version = 2, txIn = listOf( - TxIn(OutPoint(ByteVector32("2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"), 0), listOf(), 42), - TxIn(OutPoint(ByteVector32("2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"), 3), listOf(), 0) + TxIn(OutPoint(TxHash("2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"), 0), listOf(), 42), + TxIn(OutPoint(TxHash("2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"), 3), listOf(), 0) ), txOut = listOf(output1, output2), lockTime = 0 @@ -889,7 +889,7 @@ class PsbtTestsCommon { assertEquals(psbt.getInput(2), Input.PartiallySignedInputWithoutUtxo(null, mapOf(), setOf(), setOf(), setOf(), setOf(), listOf())) assertNull(psbt.getInput(6)) assertEquals(psbt.getInput(OutPoint(inputTx, 1)), Input.PartiallySignedInputWithoutUtxo(null, mapOf(), setOf(), setOf(), setOf(), setOf(), listOf())) - assertNull(psbt.getInput(OutPoint(ByteVector32.Zeroes, 0))) + assertNull(psbt.getInput(OutPoint(TxHash(ByteVector32.Zeroes), 0))) // We can't sign the psbt before adding the utxo details (updater role). assertTrue(psbt.sign(priv1, 0).isLeft) @@ -1124,8 +1124,8 @@ class PsbtTestsCommon { // see https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd for more details val priv1 = PrivateKey.fromHex("0101010101010101010101010101010101010101010101010101010101010101") val priv2 = PrivateKey.fromHex("0202020202020202020202020202020202020202020202020202020202020202") - val utxo1 = Transaction(2, listOf(TxIn(OutPoint(Hex.decode("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"), 0), TxIn.SEQUENCE_FINAL)), listOf(TxOut(Satoshi(15_000_000L), Script.pay2wpkh(priv1.publicKey()))), 0) - val utxo2 = Transaction(2, listOf(TxIn(OutPoint(Hex.decode("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"), 0), TxIn.SEQUENCE_FINAL)), listOf(TxOut(Satoshi(20_000_000L), Script.pay2wpkh(priv2.publicKey()))), 0) + val utxo1 = Transaction(2, listOf(TxIn(OutPoint(TxHash("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"), 0), TxIn.SEQUENCE_FINAL)), listOf(TxOut(Satoshi(15_000_000L), Script.pay2wpkh(priv1.publicKey()))), 0) + val utxo2 = Transaction(2, listOf(TxIn(OutPoint(TxHash("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"), 0), TxIn.SEQUENCE_FINAL)), listOf(TxOut(Satoshi(20_000_000L), Script.pay2wpkh(priv2.publicKey()))), 0) // create a tx that spends our utxo, with an output of 20_000_000 sats: it pays a huge fee of 15_000_000 sats val tx = Transaction( diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/ScriptTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/ScriptTestsCommon.kt index 18288fcc..4ec7ce85 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/ScriptTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/ScriptTestsCommon.kt @@ -78,7 +78,7 @@ class ScriptTestsCommon { } companion object { - val mapFlagNames = mapOf( + private val mapFlagNames = mapOf( "NONE" to SCRIPT_VERIFY_NONE, "P2SH" to SCRIPT_VERIFY_P2SH, "STRICTENC" to SCRIPT_VERIFY_STRICTENC, @@ -136,30 +136,29 @@ class ScriptTestsCommon { try { val tokens = input.split(' ').filterNot { it.isEmpty() }.map { it.removePrefix("OP_") }.toList() - val bytes = parseInternal(tokens) - return bytes + return parseInternal(tokens) } catch (t: Throwable) { throw RuntimeException("cannot parse $input", t) } } - fun creditTx(scriptPubKey: ByteArray, amount: Satoshi) = Transaction( + private fun creditTx(scriptPubKey: ByteArray, amount: Satoshi) = Transaction( version = 1, - txIn = listOf(TxIn(OutPoint(ByteArray(32), -1), listOf(OP_0, OP_0), 0xffffffff)), + txIn = listOf(TxIn(OutPoint(TxHash(ByteArray(32)), -1), listOf(OP_0, OP_0), 0xffffffff)), txOut = listOf(TxOut(amount, scriptPubKey)), lockTime = 0 ) - fun spendingTx(scriptSig: ByteArray, tx: Transaction) = Transaction( + private fun spendingTx(scriptSig: ByteArray, tx: Transaction) = Transaction( version = 1, - txIn = listOf(TxIn(OutPoint(Crypto.hash256(Transaction.write(tx)), 0), scriptSig, 0xffffffff)), + txIn = listOf(TxIn(OutPoint(TxHash(Crypto.hash256(Transaction.write(tx))), 0), scriptSig, 0xffffffff)), txOut = listOf(TxOut(tx.txOut[0].amount, ByteArray(0))), lockTime = 0 ) // use 0 btc if no amount is specified - fun runTest( + private fun runTest( witnessText: List, scriptSigText: String, scriptPubKeyText: String, @@ -168,7 +167,7 @@ class ScriptTestsCommon { expectedText: String ) = runTest(witnessText, 0L.toSatoshi(), scriptSigText, scriptPubKeyText, flags, comments, expectedText) - fun runTest( + private fun runTest( witnessText: List, amount: Satoshi, scriptSigText: String, diff --git a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/TransactionTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/TransactionTestsCommon.kt index 5a7a883f..1f4f4ea9 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/reference/TransactionTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/reference/TransactionTestsCommon.kt @@ -57,7 +57,7 @@ class TransactionTestsCommon { return count } - fun processSingle(testCase: JsonArray, valid: Boolean, comment: String? = null) { + private fun processSingle(testCase: JsonArray, valid: Boolean, comment: String? = null) { val prevoutMap = mutableMapOf() val prevamountMap = mutableMapOf() @@ -68,23 +68,23 @@ class TransactionTestsCommon { array.map { when (it.jsonArray.size) { 3 -> { - val hash = it.jsonArray[0].jsonPrimitive.content + val txid = it.jsonArray[0].jsonPrimitive.content val index = it.jsonArray[1].jsonPrimitive.int val scriptPubKey = it.jsonArray[2].jsonPrimitive.content val prevoutScript = ScriptTestsCommon.parseFromText(scriptPubKey) prevoutMap.put( - OutPoint(ByteVector32(hash).reversed(), index.toLong()), + OutPoint(TxId(txid), index.toLong()), prevoutScript.byteVector() ) } 4 -> { - val hash = it.jsonArray[0].jsonPrimitive.content + val txid = it.jsonArray[0].jsonPrimitive.content val index = it.jsonArray[1].jsonPrimitive.long val scriptPubKey = it.jsonArray[2].jsonPrimitive.content val prevoutScript = ScriptTestsCommon.parseFromText(scriptPubKey) - prevoutMap[OutPoint(ByteVector32(hash).reversed(), index)] = prevoutScript.byteVector() + prevoutMap[OutPoint(TxId(txid), index)] = prevoutScript.byteVector() val amount = it.jsonArray[3].jsonPrimitive.long.toSatoshi() - prevamountMap.put(OutPoint(ByteVector32(hash).reversed(), index), amount) + prevamountMap.put(OutPoint(TxId(txid), index), amount) } else -> { fail("unexpected test data $testCase $comment") @@ -140,7 +140,7 @@ class TransactionTestsCommon { val publicKey1 = PublicKey.fromHex("03949633a194a43a310c5a593aada2f2d4a4e3c181880e2b396facfb2130a7f0b5") val publicKey2 = PublicKey.fromHex("02cf5642ac302c004f429b1d9334ac3f93f65ae4df2fb6bf23af3a848166afc662") val sig = ByteVector("f55bcf4c0650024f421bef9f47f9967fe3015b8ceeda8328185d0f2e73e8c30980e95282b1a73c8d30ceae3c40a9d6df952fd93ea027f6d2a41f6b21dcb1afbef37e81988e8f770cca") - val txId = ByteVector32("2f8dbf25b36aef3ab1c14c302e3d07fddd8a9d860126bc6a03e8533bb6a31cbe") + val txId = TxId("2f8dbf25b36aef3ab1c14c302e3d07fddd8a9d860126bc6a03e8533bb6a31cbe") val p2wpkhInputNoWitness = TxIn(OutPoint(txId, 3), ByteVector.empty, 0) val p2wpkhInputWithWitness = TxIn(OutPoint(txId, 3), ByteVector.empty, 0, Script.witnessPay2wpkh(publicKey1, sig))