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..616596ea 100644 --- a/lib/ckb/types/transaction.rb +++ b/lib/ckb/types/transaction.rb @@ -30,10 +30,17 @@ 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 || [] + blake2b = CKB::Blake2b.new + blake2b.update(Utils.hex_to_bin(tx_hash)) + old_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 @@ -43,7 +50,7 @@ def sign(key, tx_hash) deps: deps, inputs: inputs, outputs: outputs, - witnesses: witnesses + witnesses: signed_witnesses ) 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 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" ] } ])