Class: OnChain::Transaction

Inherits:
Object
  • Object
show all
Defined in:
lib/onchain/transaction.rb

Class Method Summary collapse

Class Method Details

.create_transaction(redemption_scripts, address, amount_in_satoshi, miners_fee) ⇒ Object

Given a send address and an amount produce a transaction and a list of hashes that need to be signed.

The transaction will be in hex format.

The list of hashes that need to be signed will be in this format

[input index]=> { :hash => hash }

i.e.

0][:hash => ‘345435345…’
0][:hash => ‘122133445.…’


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/onchain/transaction.rb', line 18

def create_transaction(redemption_scripts, address, amount_in_satoshi, miners_fee)

  tx = Bitcoin::Protocol::Tx.new
  
  total_amount = miners_fee
  
  total_amount = total_amount + amount_in_satoshi
  
  addresses = redemption_scripts.map { |rs| 
    OnChain::Sweeper.generate_address_of_redemption_script(rs)
  }
  
  unspents, indexes, change = OnChain::BlockChain.get_unspent_for_amount(addresses, total_amount)
  
  # OK, let's build a transaction.
  tx = Bitcoin::Protocol::Tx.new
  
  # Process the unpsent outs.
  unspents.each_with_index do |spent, index|

    script = redemption_scripts[indexes[index]]
    
    txin = Bitcoin::Protocol::TxIn.new([ spent[0] ].pack('H*').reverse, spent[1])
    txin.script_sig = OnChain::hex_to_bin(script)
    tx.add_in(txin)
  end
  
  # Do we have enough in the fund.
  #if(total_amount > btc_balance)
  #  raise 'Balance is not enough to cover payment'
  #end

  txout = Bitcoin::Protocol::TxOut.new(amount_in_satoshi, 
      Bitcoin::Script.to_address_script(address))
  
  tx.add_out(txout)
  
  change_address = addresses[0]

  # Send the change back.
  if change > 0
  
    txout = Bitcoin::Protocol::TxOut.new(change, 
      Bitcoin::Script.to_address_script(change_address))
  
    tx.add_out(txout)
  end

  inputs_to_sign = []
  tx.in.each_with_index do |txin, index|
    hash = tx.signature_hash_for_input(index, txin.script, 1)
    
    rsscript = Bitcoin::Script.new txin.script
    rsscript.get_multisig_pubkeys.each do |key|
      
      if inputs_to_sign[index] == nil
        inputs_to_sign[index] = {}
      end
      inputs_to_sign[index][OnChain.bin_to_hex(key)] = {'hash' => OnChain::bin_to_hex(hash)}
    end
  end

  return OnChain::bin_to_hex(tx.to_payload), inputs_to_sign
end

.sign_transaction(transaction_hex, sig_list) ⇒ Object

Given a transaction in hex string format, apply the given signature list to it.

Signatures should be in the format

[0]=> {’hash’ => ‘345435345.…’, ‘sig’ => ‘435fgdf4553…’} [0]=> {’hash’ => ‘122133445.…’, ‘sig’ => ‘435fgdf4553…’}



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/onchain/transaction.rb', line 91

def sign_transaction(transaction_hex, sig_list)
  
  tx = Bitcoin::Protocol::Tx.new OnChain::hex_to_bin(transaction_hex)
  
  tx.in.each_with_index do |txin, index|
    
    hash = OnChain.bin_to_hex(tx.signature_hash_for_input(index, txin.script, 1))
    
    sigs = []
    
    rscript = Bitcoin::Script.new txin.script
    rscript.get_multisig_pubkeys.each do |key|
      
      hkey = OnChain.bin_to_hex(key)
      if sig_list[index][hkey] != nil and sig_list[index][hkey]['sig'] != nil
        
        # Add the signature to the list.
        sigs << OnChain.hex_to_bin(sig_list[index][hkey]['sig'])
        
      end
    end
    
    if sigs.count > 0
      txin.script = Bitcoin::Script.to_p2sh_multisig_script_sig(rscript.to_payload, sigs)
    end
  end
  
  return OnChain::bin_to_hex(tx.to_payload)
end