From 4cad0ab01c897b5b36d4da16a883dd08b018b2f4 Mon Sep 17 00:00:00 2001 From: Xuejie Xiao Date: Tue, 28 May 2019 08:30:41 +0000 Subject: [PATCH 1/4] feat: update SDK based on new verification model --- lib/ckb/api.rb | 2 +- lib/ckb/types/input.rb | 12 ++++++------ lib/ckb/types/transaction.rb | 27 ++++++++++++++++++++++----- lib/ckb/wallet.rb | 21 +++++++++++++-------- 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/lib/ckb/api.rb b/lib/ckb/api.rb index 93c031d9..163c1816 100644 --- a/lib/ckb/api.rb +++ b/lib/ckb/api.rb @@ -16,7 +16,7 @@ def initialize(host: CKB::RPC::DEFAULT_URL, mode: MODE::TESTNET) @rpc = CKB::RPC.new(host: host) if mode == MODE::TESTNET # Testnet system script code_hash - expected_code_hash = "0x9e3b3557f11b2b3532ce352bfe8017e9fd11d154c4c7f9b7aaaa1e621b539a08" + expected_code_hash = "0xa4a3d87cd69733562865ddfaf12dd44cf4cd396c4128ff1a5839c2fe48b2a1a1" # For testnet chain, we can assume the second cell of the first transaction # in the genesis block contains default lock script we can use here. system_cell_transaction = genesis_block.transactions.first diff --git a/lib/ckb/types/input.rb b/lib/ckb/types/input.rb index dc39fb16..1b7ffce3 100644 --- a/lib/ckb/types/input.rb +++ b/lib/ckb/types/input.rb @@ -3,20 +3,20 @@ module CKB module Types class Input - attr_reader :args, :previous_output, :since + attr_reader :block_number, :previous_output, :since - # @param args [String[]] ["0x..."] # @param previous_output [CKB::Types::OutPoint] # @param since [String] - def initialize(args:, previous_output:, since: "0") - @args = args + # @param block_number [String] + def initialize(previous_output:, since: "0", block_number: "0") @previous_output = previous_output @since = since.to_s + @block_number = block_number.to_s end def to_h { - args: @args, + block_number: block_number, previous_output: @previous_output.to_h, since: since } @@ -26,7 +26,7 @@ def self.from_h(hash) return if hash.nil? new( - args: hash[:args], + block_number: hash[:block_number], previous_output: OutPoint.from_h(hash[:previous_output]), since: hash[:since] ) diff --git a/lib/ckb/types/transaction.rb b/lib/ckb/types/transaction.rb index d4a0e71f..dccfa656 100644 --- a/lib/ckb/types/transaction.rb +++ b/lib/ckb/types/transaction.rb @@ -30,10 +30,12 @@ def initialize( # @param key [CKB::Key] # @param tx_hash [String] 0x... def sign(key, tx_hash) - signature_hex_var = key.sign(tx_hash) - signature_size = Utils.hex_to_bin(signature_hex_var).size - data = [key.pubkey, signature_hex_var, Utils.bin_to_hex([signature_size].pack("Q<"))] - witnesses = inputs.size.times.map do + raise "Invalid number of witnesses!" if witnesses.length < inputs.length + + signed_witnesses = witnesses.map do |witness| + old_data = witness.data || [] + signature_hex_var = signature_hex(key, [tx_hash] + old_data) + data = [key.pubkey, signature_hex_var] + old_data Types::Witness.from_h(data: data) end @@ -43,7 +45,7 @@ def sign(key, tx_hash) deps: deps, inputs: inputs, outputs: outputs, - witnesses: witnesses + witnesses: signed_witnesses ) end @@ -71,6 +73,21 @@ def self.from_h(hash) witnesses: hash[:witnesses].map { |witness| Witness.from_h(witness) } ) end + + private + + def signature_hex(key, data) + blake2b = CKB::Blake2b.new + data.each do |datum| + blake2b.update(Utils.hex_to_bin(datum)) + end + privkey_bin = Utils.hex_to_bin(key.privkey) + secp_key = Secp256k1::PrivateKey.new(privkey: privkey_bin) + signature_bin = secp_key.ecdsa_serialize( + secp_key.ecdsa_sign(blake2b.digest, raw: true) + ) + Utils.bin_to_hex(signature_bin) + end end end end diff --git a/lib/ckb/wallet.rb b/lib/ckb/wallet.rb index 05e2022b..dfa7066d 100644 --- a/lib/ckb/wallet.rb +++ b/lib/ckb/wallet.rb @@ -75,7 +75,8 @@ def generate_tx(target_address, capacity, data = "0x") version: 0, deps: [api.system_script_out_point], inputs: i.inputs, - outputs: outputs + outputs: outputs, + witnesses: i.witnesses ) tx_hash = api.compute_transaction_hash(tx) @@ -116,7 +117,8 @@ def deposit_to_dao(capacity) version: 0, deps: [api.system_script_out_point], inputs: i.inputs, - outputs: outputs + outputs: outputs, + witnesses: i.witnesses, ) tx_hash = api.compute_transaction_hash(tx) send_transaction(tx.sign(key, tx_hash)) @@ -156,11 +158,15 @@ def generate_withdraw_from_dao_transaction(cell_out_point) version: 0, deps: [{block_hash: current_block.hash}], inputs: [ - Types::Input.new(args: [current_block.hash], previous_output: new_cell_out_point, since: since), - Types::Input.new(args: [], previous_output: DAO_ISSUING_OUT_POINT) + Types::Input.new(previous_output: new_cell_out_point, since: since), + Types::Input.new(previous_output: DAO_ISSUING_OUT_POINT) ], outputs: [ Types::Output.new(capacity: output_capacity, lock: lock) + ], + witnesses: [ + Types::Witness.new(data: [current_block.hash]), + Types::Witness.new(data: []), ] ) tx_hash = api.compute_transaction_hash(tx) @@ -200,15 +206,14 @@ def gather_inputs(capacity, min_capacity, min_charge_capacity) input_capacities = 0 inputs = [] - pubkeys = [] + witnesses = [] get_unspent_cells.each do |cell| input = Types::Input.new( previous_output: cell.out_point, - args: [], since: "0" ) - pubkeys << pubkey inputs << input + witnesses << Types::Witness.new(data: []) input_capacities += cell.capacity.to_i diff = input_capacities - capacity @@ -217,7 +222,7 @@ def gather_inputs(capacity, min_capacity, min_charge_capacity) raise "Capacity not enough!" if input_capacities < capacity - OpenStruct.new(inputs: inputs, capacities: input_capacities, pubkeys: pubkeys) + OpenStruct.new(inputs: inputs, capacities: input_capacities, witnesses: witnesses) end def pubkey From a16ab01d3c0a17d6edff0afe7a68f71c11cf210c Mon Sep 17 00:00:00 2001 From: Xuejie Xiao Date: Tue, 28 May 2019 08:58:59 +0000 Subject: [PATCH 2/4] fix: unit test --- spec/ckb/types/transaction_spec.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/spec/ckb/types/transaction_spec.rb b/spec/ckb/types/transaction_spec.rb index 339da7cc..c37751a2 100644 --- a/spec/ckb/types/transaction_spec.rb +++ b/spec/ckb/types/transaction_spec.rb @@ -48,7 +48,11 @@ "data": "0x" } ], - "witnesses": [] + "witnesses": [ + { + data: [] + } + ] } end @@ -63,8 +67,7 @@ { data: [ "0x024a501efd328e062c8675f2365970728c859c592beeefd6be8ead3d901330bc01", - "0x304402207c82346909c13b86a97c38a50b4868b52735ca2e7e59b14f99102159c12ff25f0220511ef5974060510e8cb363877843bd85550805f668676771bfc47e36bc5b8aa2", - "0x4600000000000000" + "0x304402202c643579e47045be050d3842ed9270151af8885e33954bddad0e53e81d1c2dbe02202dc637877a8302110846ebc6a16d9148c106e25f945063ad1c4d4db2b6952408" ] } ]) From 4be8ac80dec7695237daa2641b558c91099950d7 Mon Sep 17 00:00:00 2001 From: Xuejie Xiao Date: Mon, 3 Jun 2019 09:31:10 +0800 Subject: [PATCH 3/4] fix: test --- lib/ckb/types/transaction.rb | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/lib/ckb/types/transaction.rb b/lib/ckb/types/transaction.rb index dccfa656..a298a7c2 100644 --- a/lib/ckb/types/transaction.rb +++ b/lib/ckb/types/transaction.rb @@ -34,8 +34,13 @@ def sign(key, tx_hash) signed_witnesses = witnesses.map do |witness| old_data = witness.data || [] - signature_hex_var = signature_hex(key, [tx_hash] + old_data) - data = [key.pubkey, signature_hex_var] + old_data + blake2b = CKB::Blake2b.new + blake2b.update(Utils.hex_to_bin(tx_hash)) + data.each do |datum| + blake2b.update(Utils.hex_to_bin(datum)) + end + message = Utils.bin_to_hex(blake2b.digest) + data = [key.pubkey, key.sign(message)] + old_data Types::Witness.from_h(data: data) end @@ -73,21 +78,6 @@ def self.from_h(hash) witnesses: hash[:witnesses].map { |witness| Witness.from_h(witness) } ) end - - private - - def signature_hex(key, data) - blake2b = CKB::Blake2b.new - data.each do |datum| - blake2b.update(Utils.hex_to_bin(datum)) - end - privkey_bin = Utils.hex_to_bin(key.privkey) - secp_key = Secp256k1::PrivateKey.new(privkey: privkey_bin) - signature_bin = secp_key.ecdsa_serialize( - secp_key.ecdsa_sign(blake2b.digest, raw: true) - ) - Utils.bin_to_hex(signature_bin) - end end end end From c675b3e5e86d273e2bf7633c0ba05595c4958399 Mon Sep 17 00:00:00 2001 From: Xuejie Xiao Date: Mon, 3 Jun 2019 09:44:51 +0800 Subject: [PATCH 4/4] fix: one more test fix --- lib/ckb/types/transaction.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ckb/types/transaction.rb b/lib/ckb/types/transaction.rb index a298a7c2..616596ea 100644 --- a/lib/ckb/types/transaction.rb +++ b/lib/ckb/types/transaction.rb @@ -36,7 +36,7 @@ def sign(key, tx_hash) old_data = witness.data || [] blake2b = CKB::Blake2b.new blake2b.update(Utils.hex_to_bin(tx_hash)) - data.each do |datum| + old_data.each do |datum| blake2b.update(Utils.hex_to_bin(datum)) end message = Utils.bin_to_hex(blake2b.digest)