From 6367d7ac2df49701c2cff2334593f546ce4b7f45 Mon Sep 17 00:00:00 2001 From: azuchi Date: Fri, 20 May 2022 14:54:17 +0900 Subject: [PATCH] Support PSBT_IN_HASH256 of PSBT v0 --- lib/bitcoin/constants.rb | 2 ++ lib/bitcoin/psbt/input.rb | 7 +++++++ spec/bitcoin/psbt_spec.rb | 26 ++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/lib/bitcoin/constants.rb b/lib/bitcoin/constants.rb index 4ad1104..08e8b3b 100644 --- a/lib/bitcoin/constants.rb +++ b/lib/bitcoin/constants.rb @@ -9,6 +9,8 @@ module Bitcoin SHA256_SIZE = 32 # Byte size of the HASH160 hash HASH160_SIZE = 20 + # Byte size of the HASH256 hash + HASH256_SIZE = 32 # The maximum allowed size for a serialized block, in bytes (only for buffer size limits) MAX_BLOCK_SERIALIZED_SIZE = 4_000_000 diff --git a/lib/bitcoin/psbt/input.rb b/lib/bitcoin/psbt/input.rb index 421bc36..fcf71dd 100644 --- a/lib/bitcoin/psbt/input.rb +++ b/lib/bitcoin/psbt/input.rb @@ -17,6 +17,7 @@ class Input attr_accessor :ripemd160_preimages attr_accessor :sha256_preimages attr_accessor :hash160_preimages + attr_accessor :hash256_preimages attr_accessor :proprietaries attr_accessor :unknowns @@ -28,6 +29,7 @@ def initialize(non_witness_utxo: nil, witness_utxo: nil) @ripemd160_preimages = {} @sha256_preimages = {} @hash160_preimages = {} + @hash256_preimages = {} @proprietaries = [] @unknowns = {} end @@ -101,6 +103,10 @@ def self.parse_from_buf(buf) raise ArgumentError, 'Size of key was not the expected size for the type hash160 preimage' unless key.bytesize == HASH160_SIZE raise ArgumentError, 'Duplicate Key, input hash160 preimage already provided' if input.hash160_preimages[key.bth] input.hash160_preimages[key.bth] = value.bth + when PSBT_IN_TYPES[:hash256] + raise ArgumentError, 'Size of key was not the expected size for the type hash256 preimage' unless key.bytesize == HASH256_SIZE + raise ArgumentError, 'Duplicate Key, input hash256 preimage already provided' if input.hash256_preimages[key.bth] + input.hash256_preimages[key.bth] = value.bth when PSBT_IN_TYPES[:proprietary] raise ArgumentError, 'Duplicate Key, key for proprietary value already provided.' if input.proprietaries.any?{|p| p.key == key} input.proprietaries << Proprietary.new(key, value) @@ -128,6 +134,7 @@ def to_payload payload << ripemd160_preimages.map{|k, v|PSBT.serialize_to_vector(PSBT_IN_TYPES[:ripemd160], key: k.htb, value: v.htb)}.join payload << sha256_preimages.map{|k, v|PSBT.serialize_to_vector(PSBT_IN_TYPES[:sha256], key: k.htb, value: v.htb)}.join payload << hash160_preimages.map{|k, v|PSBT.serialize_to_vector(PSBT_IN_TYPES[:hash160], key: k.htb, value: v.htb)}.join + payload << hash256_preimages.map{|k, v|PSBT.serialize_to_vector(PSBT_IN_TYPES[:hash256], key: k.htb, value: v.htb)}.join end payload << PSBT.serialize_to_vector(PSBT_IN_TYPES[:script_sig], value: final_script_sig.to_payload) if final_script_sig payload << PSBT.serialize_to_vector(PSBT_IN_TYPES[:script_witness], value: final_script_witness.to_payload) if final_script_witness diff --git a/spec/bitcoin/psbt_spec.rb b/spec/bitcoin/psbt_spec.rb index 7c4521c..14d84a1 100644 --- a/spec/bitcoin/psbt_spec.rb +++ b/spec/bitcoin/psbt_spec.rb @@ -447,4 +447,30 @@ end end end + + context 'has PSBT_IN_HASH256' do + it 'parse sha256 data' do + base64 = 'cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAIQ12pWrO2RXSUT3NhMLDeLLoqlzWMrW3HKLyrFsOOmSb2wIBAiENnBLP3ATHRYTXh6w9I3chMsGFJLx6so3sQhm4/FtCX3ABAQAAAA==' + psbt = Bitcoin::PSBT::Tx.parse_from_base64(base64) + expect(psbt.inputs.size).to eq(1) + expect(psbt.inputs[0].hash256_preimages.size).to eq(2) + expect(psbt.inputs[0].hash256_preimages['76a56aced915d2513dcd84c2c378b2e8aa5cd632b5b71ca2f2ac5b0e3a649bdb']).to eq('0102') + expect(psbt.inputs[0].hash256_preimages['9c12cfdc04c74584d787ac3d23772132c18524bc7ab28dec4219b8fc5b425f70']).to eq('01') + expect(psbt.to_base64).to eq(base64) + end + + context 'duplicate PSBT_IN_HASH256 key' do + it 'raise ArgumentError' do + hex = '70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000210d9c12cfdc04c74584d787ac3d23772132c18524bc7ab28dec4219b8fc5b425f70020102210d9c12cfdc04c74584d787ac3d23772132c18524bc7ab28dec4219b8fc5b425f700101000000' + expect {Bitcoin::PSBT::Tx.parse_from_payload(hex.htb)}.to raise_error(ArgumentError, 'Duplicate Key, input hash256 preimage already provided') + end + end + + context 'invalid key size' do + it 'raise ArgumentError' do + hex = '70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000200da56aced915d2513dcd84c2c378b2e8aa5cd632b5b71ca2f2ac5b0e3a649bdb020102210d9c12cfdc04c74584d787ac3d23772132c18524bc7ab28dec4219b8fc5b425f700101000000' + expect {Bitcoin::PSBT::Tx.parse_from_payload(hex.htb)}.to raise_error(ArgumentError, 'Size of key was not the expected size for the type hash256 preimage') + end + end + end end