Class: Bitcoin::Protocol::TxIn

Inherits:
Object
  • Object
show all
Defined in:
lib/bitcoin/protocol/txin.rb

Constant Summary collapse

DEFAULT_SEQUENCE =
"\xff\xff\xff\xff"
NULL_HASH =
"\x00"*32
COINBASE_INDEX =
0xffffffff

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ TxIn

Returns a new instance of TxIn.



36
37
38
39
40
41
42
43
# File 'lib/bitcoin/protocol/txin.rb', line 36

def initialize *args
  @prev_out_hash, @prev_out_index, @script_sig_length,
  @script_sig, @sequence = *args
  @script_sig_length ||= 0
  @script_sig ||= ''
  @sequence ||= DEFAULT_SEQUENCE
  @script_witness = ScriptWitness.new
end

Instance Attribute Details

#prev_out_hashObject Also known as: prev_out

previous output hash



9
10
11
# File 'lib/bitcoin/protocol/txin.rb', line 9

def prev_out_hash
  @prev_out_hash
end

#prev_out_indexObject

previous output index



14
15
16
# File 'lib/bitcoin/protocol/txin.rb', line 14

def prev_out_index
  @prev_out_index
end

#script_sigObject Also known as: script

script_sig input Script (signature)



17
18
19
# File 'lib/bitcoin/protocol/txin.rb', line 17

def script_sig
  @script_sig
end

#script_sig_lengthObject Also known as: script_length

script_sig input Script (signature)



17
18
19
# File 'lib/bitcoin/protocol/txin.rb', line 17

def script_sig_length
  @script_sig_length
end

#script_witnessObject

segregated witness



24
25
26
# File 'lib/bitcoin/protocol/txin.rb', line 24

def script_witness
  @script_witness
end

#sequenceObject

sequence



30
31
32
# File 'lib/bitcoin/protocol/txin.rb', line 30

def sequence
  @sequence
end

#sig_addressObject

signature hash and the address of the key that needs to sign it (used when dealing with unsigned or partly signed tx)



21
22
23
# File 'lib/bitcoin/protocol/txin.rb', line 21

def sig_address
  @sig_address
end

#sig_hashObject

signature hash and the address of the key that needs to sign it (used when dealing with unsigned or partly signed tx)



21
22
23
# File 'lib/bitcoin/protocol/txin.rb', line 21

def sig_hash
  @sig_hash
end

Class Method Details

.from_hash(input) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/bitcoin/protocol/txin.rb', line 98

def self.from_hash(input)
  previous_hash         = input['previous_transaction_hash'] || input['prev_out']['hash']
  previous_output_index = input['output_index'] || input['prev_out']['n']
  txin = TxIn.new([ previous_hash ].pack('H*').reverse, previous_output_index)
  if input['coinbase']
    txin.script_sig = [ input['coinbase'] ].pack("H*")
  else
    txin.script_sig = Script.binary_from_string(input['scriptSig'] || input['script'])
  end
  if input['witness']
    input['witness'].each {|w| txin.script_witness.stack << w.htb}
  end
  txin.sequence = [ input['sequence'] || 0xffffffff ].pack("V")
  txin
end

.from_hex_hash(hash, index) ⇒ Object



114
115
116
# File 'lib/bitcoin/protocol/txin.rb', line 114

def self.from_hex_hash(hash, index)
  TxIn.new([hash].pack("H*").reverse, index, 0)
end

.from_io(buf) ⇒ Object



67
68
69
# File 'lib/bitcoin/protocol/txin.rb', line 67

def self.from_io(buf)
  txin = new; txin.parse_data_from_io(buf); txin
end

Instance Method Details

#==(other) ⇒ Object

compare to another txout



46
47
48
49
50
51
52
53
# File 'lib/bitcoin/protocol/txin.rb', line 46

def ==(other)
  @prev_out_hash == other.prev_out_hash &&
    @prev_out_index == other.prev_out_index &&
    @script_sig == other.script_sig &&
    @sequence == other.sequence
rescue
  false
end

#add_signature_pubkey_script(sig, pubkey_hex) ⇒ Object



135
136
137
# File 'lib/bitcoin/protocol/txin.rb', line 135

def add_signature_pubkey_script(sig, pubkey_hex)
  self.script = Bitcoin::Script.to_signature_pubkey_script(sig, [pubkey_hex].pack("H*"))
end

#coinbase?Boolean

check if input is coinbase

Returns:

  • (Boolean)


124
125
126
# File 'lib/bitcoin/protocol/txin.rb', line 124

def coinbase?
  (@prev_out_index == COINBASE_INDEX) && (@prev_out_hash == NULL_HASH)
end

#is_final?Boolean

returns true if the sequence number is final (DEFAULT_SEQUENCE)

Returns:

  • (Boolean)


56
57
58
# File 'lib/bitcoin/protocol/txin.rb', line 56

def is_final?
  self.sequence == DEFAULT_SEQUENCE
end

#parse_data(data) ⇒ Object

parse raw binary data for transaction input



61
62
63
64
65
# File 'lib/bitcoin/protocol/txin.rb', line 61

def parse_data(data)
  buf = data.is_a?(String) ? StringIO.new(data) : data
  parse_data_from_io(buf)
  buf.pos
end

#parse_data_from_io(buf) ⇒ Object



71
72
73
74
75
76
# File 'lib/bitcoin/protocol/txin.rb', line 71

def parse_data_from_io(buf)
  @prev_out_hash, @prev_out_index = buf.read(36).unpack("a32V")
  @script_sig_length = Protocol.unpack_var_int_from_io(buf)
  @script_sig = buf.read(@script_sig_length)
  @sequence = buf.read(4)
end

#parsed_scriptObject



78
79
80
# File 'lib/bitcoin/protocol/txin.rb', line 78

def parsed_script
  @parsed_script ||= Bitcoin::Script.new(script_sig)
end

#prev_out=(hash) ⇒ Object



11
# File 'lib/bitcoin/protocol/txin.rb', line 11

def prev_out=(hash); @prev_out_hash = hash; end

#previous_outputObject

previous output in hex



119
120
121
# File 'lib/bitcoin/protocol/txin.rb', line 119

def previous_output
  @prev_out_hash.reverse_hth
end

#to_hash(options = {}) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/bitcoin/protocol/txin.rb', line 86

def to_hash(options = {})
  t = { 'prev_out'  => { 'hash' => @prev_out_hash.reverse_hth, 'n' => @prev_out_index } }
  if coinbase?
    t['coinbase']  = @script_sig.unpack("H*")[0]
  else # coinbase tx
    t['scriptSig'] = Bitcoin::Script.new(@script_sig).to_string
  end
  t['sequence']  = @sequence.unpack("V")[0] unless @sequence == "\xff\xff\xff\xff"
  t['witness'] = @script_witness.stack.map{|s|s.bth} unless @script_witness.empty?
  t
end

#to_payload(script = @script_sig, sequence = @sequence) ⇒ Object



82
83
84
# File 'lib/bitcoin/protocol/txin.rb', line 82

def to_payload(script=@script_sig, sequence=@sequence)
  [@prev_out_hash, @prev_out_index].pack("a32V") << Protocol.pack_var_int(script.bytesize) << script << (sequence || DEFAULT_SEQUENCE)
end