From b9b8397748184a4e1c7fee7f750cc4cbe4963a09 Mon Sep 17 00:00:00 2001 From: t-bast Date: Tue, 11 Apr 2023 17:05:47 +0200 Subject: [PATCH] Introduce BlockId and BlockHash It was footgunny to use a `ByteVector32` here as well, as we can easily mistake one for the other. --- .../kotlin/fr/acinq/bitcoin/Bech32.kt | 2 +- .../kotlin/fr/acinq/bitcoin/Bitcoin.kt | 18 ++++---- .../kotlin/fr/acinq/bitcoin/Block.kt | 44 +++++++++++++------ .../kotlin/fr/acinq/bitcoin/Descriptor.kt | 6 +-- .../kotlin/fr/acinq/bitcoin/PublicKey.kt | 6 +-- .../fr/acinq/bitcoin/BitcoinTestsCommon.kt | 16 +++---- .../fr/acinq/bitcoin/BlockTestsCommon.kt | 8 ++-- .../kotlin/fr/acinq/bitcoin/PowTestsCommon.kt | 2 +- 8 files changed, 59 insertions(+), 43 deletions(-) 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 6adc77c1..2cacd2d4 100644 --- a/src/commonMain/kotlin/fr/acinq/bitcoin/Bitcoin.kt +++ b/src/commonMain/kotlin/fr/acinq/bitcoin/Bitcoin.kt @@ -28,10 +28,10 @@ public fun List.updated(i: Int, t: T): List = when (i) { 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 @@ -39,10 +39,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 @@ -51,13 +51,13 @@ public object Bitcoin { * understood only by native sewgit 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) @JvmStatic - public fun addressFromPublicKeyScript(chainHash: ByteVector32, pubkeyScript: List): String? { + public fun addressFromPublicKeyScript(chainHash: BlockHash, pubkeyScript: List): String? { return try { when { Script.isPay2pkh(pubkeyScript) -> { @@ -111,7 +111,7 @@ public object Bitcoin { } @JvmStatic - public fun addressFromPublicKeyScript(chainHash: ByteVector32, pubkeyScript: ByteArray): String? { + public fun addressFromPublicKeyScript(chainHash: BlockHash, pubkeyScript: ByteArray): String? { return try { addressFromPublicKeyScript(chainHash, Script.parse(pubkeyScript)) } catch (e: Exception) { @@ -120,7 +120,7 @@ public object Bitcoin { } @JvmStatic - public fun addressToPublicKeyScript(chainHash: ByteVector32, address: String): List { + public fun addressToPublicKeyScript(chainHash: BlockHash, address: String): List { 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 4ac7a7d5..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) { @@ -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/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/commonTest/kotlin/fr/acinq/bitcoin/BitcoinTestsCommon.kt b/src/commonTest/kotlin/fr/acinq/bitcoin/BitcoinTestsCommon.kt index 12168c37..a132b7c8 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/BitcoinTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/BitcoinTestsCommon.kt @@ -31,16 +31,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), computeP2PkhAddress(pub, it)) assertEquals(address(Script.pay2wpkh(pub), it), computeP2WpkhAddress(pub, it)) assertEquals(address(Script.pay2sh(Script.pay2wpkh(pub)), it), computeP2ShOfP2WpkhAddress(pub, it)) // all these chain hashes are invalid - assertEquals(address(Script.pay2pkh(pub), it.reversed()), null) - assertEquals(address(Script.pay2wpkh(pub), it.reversed()), null) - assertEquals(address(Script.pay2sh(Script.pay2wpkh(pub)), it.reversed()), null) + assertEquals(address(Script.pay2pkh(pub), BlockHash(it.value.reversed())), null) + assertEquals(address(Script.pay2wpkh(pub), BlockHash(it.value.reversed())), null) + assertEquals(address(Script.pay2sh(Script.pay2wpkh(pub)), BlockHash(it.value.reversed())), null) } listOf( @@ -115,9 +115,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 2fcf36ce..a14633b6 100644 --- a/src/commonTest/kotlin/fr/acinq/bitcoin/BlockTestsCommon.kt +++ b/src/commonTest/kotlin/fr/acinq/bitcoin/BlockTestsCommon.kt @@ -100,7 +100,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 +121,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 +132,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 +150,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/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))