Class: Bitcoin::Wallet::TxDP
- Inherits:
-
Object
- Object
- Bitcoin::Wallet::TxDP
- Defined in:
- lib/bitcoin/wallet/txdp.rb
Instance Attribute Summary collapse
-
#id ⇒ Object
Returns the value of attribute id.
-
#inputs ⇒ Object
Returns the value of attribute inputs.
-
#tx ⇒ Object
Returns the value of attribute tx.
Class Method Summary collapse
Instance Method Summary collapse
- #add_sig(in_idx, value, addr, sig) ⇒ Object
-
#initialize(tx = []) ⇒ TxDP
constructor
A new instance of TxDP.
- #parse(str) ⇒ Object
- #parse_input(input) ⇒ Object
- #parse_sigs(sigs) ⇒ Object
- #parse_txdist(txdist) ⇒ Object
- #serialize ⇒ Object
- #sign_inputs ⇒ Object
Constructor Details
#initialize(tx = []) ⇒ TxDP
Returns a new instance of TxDP.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/bitcoin/wallet/txdp.rb', line 6 def initialize tx = [] @id = Bitcoin.int_to_base58(rand(1e14)) @tx = tx @inputs = [] return unless tx.any? @tx[0].in.each_with_index do |input, i| prev_out_hash = input.prev_out.reverse_hth prev_tx = @tx[1..-1].find {|tx| tx.hash == prev_out_hash} raise "prev tx #{prev_out_hash} not found" unless prev_tx prev_out = prev_tx.out[input.prev_out_index] raise "prev out ##{input.prev_out_index} not found in tx #{@tx.hash}" unless prev_out out_script = Bitcoin::Script.new(prev_out.pk_script) out_script.get_addresses.each do |addr| add_sig(i, prev_out.value, addr, input.script_sig) end end end |
Instance Attribute Details
#id ⇒ Object
Returns the value of attribute id.
5 6 7 |
# File 'lib/bitcoin/wallet/txdp.rb', line 5 def id @id end |
#inputs ⇒ Object
Returns the value of attribute inputs.
5 6 7 |
# File 'lib/bitcoin/wallet/txdp.rb', line 5 def inputs @inputs end |
#tx ⇒ Object
Returns the value of attribute tx.
5 6 7 |
# File 'lib/bitcoin/wallet/txdp.rb', line 5 def tx @tx end |
Class Method Details
.parse(str) ⇒ Object
115 116 117 |
# File 'lib/bitcoin/wallet/txdp.rb', line 115 def self.parse str new.parse str end |
Instance Method Details
#add_sig(in_idx, value, addr, sig) ⇒ Object
24 25 26 27 |
# File 'lib/bitcoin/wallet/txdp.rb', line 24 def add_sig(in_idx, value, addr, sig) sig = sig ? [[addr, sig.unpack("H*")[0]]] : [] @inputs[in_idx] = [value, sig] end |
#parse(str) ⇒ Object
72 73 74 75 76 77 78 79 80 81 |
# File 'lib/bitcoin/wallet/txdp.rb', line 72 def parse str str.match(/-+BEGIN-TRANSACTION-(.*?)-+$(.*?)END-TRANSACTION-#{$1}/m) do |m| _, id, content = *m txdist, *inputs = content.split(/_TXINPUT_/) @id = id @txdist = parse_txdist(txdist) inputs.each {|input| parse_input(input) } end self end |
#parse_input(input) ⇒ Object
95 96 97 98 99 100 101 |
# File 'lib/bitcoin/wallet/txdp.rb', line 95 def parse_input input m = input.match(/(\d+)_(\d+\.\d+)\n(.*)/m) _, idx, value, sigs = *m value = (value.sub('.','').to_i) sigs = parse_sigs(sigs) @inputs[idx.to_i] = [value, sigs] end |
#parse_sigs(sigs) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/bitcoin/wallet/txdp.rb', line 103 def parse_sigs sigs return nil unless sigs["_SIG_"] sigs = sigs.split("_SIG_").map do |s| if s == "" nil else m = s.match(/(.*?)_(\d+)_(.*?)\n(.*)/m) [$1, $4.gsub("\n", '').gsub('-', '')] end end.compact end |
#parse_txdist(txdist) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/bitcoin/wallet/txdp.rb', line 83 def parse_txdist txdist _, magic, txdp_id, size, serialized_tx = *txdist.match(/_TXDIST_(.*?)_(.*?)_(.*?)$(.*)/m) raise "Wrong network magic" unless [magic].pack("H*") == Bitcoin.network[:magic_head] tx = Bitcoin::P::Tx.new(nil) rest = [serialized_tx.gsub!("\n", '')].pack("H*") while rest = tx.parse_data(rest) @tx << tx break if rest == true tx = Bitcoin::P::Tx.new(nil) end end |
#serialize ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/bitcoin/wallet/txdp.rb', line 49 def serialize lines = [] lines << "-----BEGIN-TRANSACTION-#{@id}".ljust(80, '-') size = [@tx.first.to_payload.bytesize].pack("C").ljust(2, "\x00").reverse_hth lines << "_TXDIST_#{Bitcoin.network[:magic_head].unpack("H*")[0]}_#{@id}_#{size}" tx = @tx.map(&:to_payload).join.unpack("H*")[0] tx_str = ""; tx.split('').each_with_index{|c,i| tx_str << (i % 80 == 0 ? "\n#{c}" : c)} lines << tx_str.strip @inputs.each_with_index do |input, idx| lines << "_TXINPUT_#{idx.to_s.rjust(2, '0')}_#{"%.8f" % (input[0].to_f / 1e8)}" next unless input[1] input[1].each do |sig| size = [sig[1]].pack("H*").bytesize size = [size].pack("C").ljust(2, "\x00").reverse_hth lines << "_SIG_#{sig[0]}_#{idx.to_s.rjust(2, '0')}_#{size}" sig_str = ""; sig[1].split('').each_with_index{|c,i| sig_str << (i % 80 == 0 ? "\n#{c}" : c)} lines << sig_str.strip end end lines << "-------END-TRANSACTION-#{@id}".ljust(80, '-') lines.join("\n") end |
#sign_inputs ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/bitcoin/wallet/txdp.rb', line 29 def sign_inputs @inputs.each_with_index do |txin, i| input = @tx[0].in[i] prev_out_hash = input.prev_out.reverse_hth prev_tx = @tx[1..-1].find {|tx| tx.hash == prev_out_hash} raise "prev tx #{prev_out_hash} not found" unless prev_tx prev_out = prev_tx.out[input.prev_out_index] raise "prev out ##{input.prev_out_index} not found in tx #{@tx.hash}" unless prev_out out_script = Bitcoin::Script.new(prev_out.pk_script) out_script.get_addresses.each do |addr| sig = yield(@tx[0], prev_tx, i, addr) if sig @inputs[i][1] ||= [] @inputs[i][1] << [addr, sig] break end end end end |