Class: OnChain::Sweeper

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

Class Method Summary collapse

Class Method Details

.create_payment_tx_from_sweep(minimum_sigs, incoming, destination_address, mpks) ⇒ Object



90
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
120
121
122
123
124
125
126
# File 'lib/onchain/sweeper.rb', line 90

def create_payment_tx_from_sweep(minimum_sigs, incoming, destination_address, mpks)
    
  tx = Bitcoin::Protocol::Tx.new
  total_amount = 0
    
  incoming.each do |output|
    
    txin = Bitcoin::Protocol::TxIn.new
    
    rs = generate_redemption_script_from_mpks(minimum_sigs, mpks, output[1])

    txin.prev_out = OnChain.hex_to_bin(output[3]).reverse
    txin.prev_out_index = output[4]
    txin.script = OnChain.hex_to_bin(rs)

    tx.add_in(txin)
    
    total_amount = total_amount + output[2].to_i
    
  end
  
  total_amount = total_amount - 10000
  
  if total_amount < 0
    return "Not enough coins to create a transaction."
  end
  
  # Add an output and we're done.
  txout = Bitcoin::Protocol::TxOut.new(total_amount, 
    Bitcoin::Script.to_address_script(destination_address))
  
  tx.add_out(txout)
  
  paths = incoming.map { |i| i[1] }
  
  return OnChain.bin_to_hex(tx.to_payload), paths
end

.generate_address_of_redemption_script(redemption_script) ⇒ Object



32
33
34
35
36
# File 'lib/onchain/sweeper.rb', line 32

def generate_address_of_redemption_script(redemption_script)
  hash160 = Bitcoin.hash160(redemption_script)

  return Bitcoin.hash160_to_p2sh_address(hash160)
end

.generate_redemption_script(minimum_sigs, addresses) ⇒ Object



27
28
29
30
# File 'lib/onchain/sweeper.rb', line 27

def generate_redemption_script(minimum_sigs, addresses)
  address, redeem_script = Bitcoin.pubkeys_to_p2sh_multisig_address(minimum_sigs, *addresses)
  return redeem_script.hth
end

.generate_redemption_script_from_mpks(minimum_sigs, mpks, path) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/onchain/sweeper.rb', line 15

def generate_redemption_script_from_mpks(minimum_sigs, mpks, path)
  
  addresses = []
  mpks.each do |mpk|
    master = MoneyTree::Node.from_serialized_address(mpk)
    m = master.node_for_path(path)
    addresses << m.public_key.to_hex
  end
  
  return generate_redemption_script(minimum_sigs, addresses)
end

.get_block_heightObject



38
39
40
# File 'lib/onchain/sweeper.rb', line 38

def get_block_height
  return Chain.get_latest_block["height"].to_i
end

.multi_sig_address_from_mpks(minimum_sigs, mpks, path) ⇒ Object

Turn a bunch of master keys into a redemption scriopt i.e. derive the path.



8
9
10
11
12
13
# File 'lib/onchain/sweeper.rb', line 8

def multi_sig_address_from_mpks(minimum_sigs, mpks, path)
  
  rs = generate_redemption_script_from_mpks(minimum_sigs, mpks, path)
  
  return generate_address_of_redemption_script(rs)
end

.post_tx_for_signing(tx_hex, paths, address) ⇒ Object



128
129
130
131
132
133
134
135
136
# File 'lib/onchain/sweeper.rb', line 128

def post_tx_for_signing(tx_hex, paths, address)
  
  return HTTParty.post('https://onchain.herokuapp.com/api/v1/transaction', 
    :body => { :tx => tx_hex, 
    :address => address,
    :meta_data => paths.join(','),
    :user_email => ENV['ONCHAIN_EMAIL'],
    :user_token => ENV['ONCHAIN_TOKEN'] }) 
end

.sweep(minimum_sigs, mpks, path, limit, last_block_checked) ⇒ Object

With a bunch of HD wallet paths, build a transaction That pays all the coins to a certain address



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
82
83
84
85
86
87
88
# File 'lib/onchain/sweeper.rb', line 44

def sweep(minimum_sigs, mpks, path, limit, last_block_checked)
  
  block_height_now = get_block_height
  
  to_sweep = {}
  # Get all the addresses we are interested in.
  for i in 0..limit do
    r = path.sub('#{index}', i.to_s)
    a = multi_sig_address_from_mpks(minimum_sigs, mpks, r)
    # store address as lookup for path.
    to_sweep[a] = r
  end
  
  incoming_coins = []
  
  to_sweep.each do |address, path|
    
    txs = Chain.get_address_transactions(address)
    
    txs.each do |tx|
      
      block_height = tx["block_height"].to_i 
      if block_height > last_block_checked
        
        tx["outputs"].each do |output|
          output["addresses"].each do |address|
            if to_sweep[address] != nil
              incoming_coins << [address, 
                to_sweep[address], 
                output["value"], 
                output["transaction_hash"], 
                output["output_index"], 
                output["script"]]
            end
          end
        end
        
      else
        break
      end
      
    end
  end
  return incoming_coins, block_height_now
end