Class: Bitcoin::Protocol::TxIn

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

Overview

Constant Summary collapse

DEFAULT_SEQUENCE =
"\xff\xff\xff\xff".freeze
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.


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

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


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

def prev_out_hash
  @prev_out_hash
end

#prev_out_indexObject

previous output index


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

def prev_out_index
  @prev_out_index
end

#script_sigObject Also known as: script

script_sig input Script (signature)


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

def script_sig
  @script_sig
end

#script_sig_lengthObject Also known as: script_length

Returns the value of attribute script_sig_length


19
20
21
# File 'lib/bitcoin/protocol/txin.rb', line 19

def script_sig_length
  @script_sig_length
end

#script_witnessObject

segregated witness


26
27
28
# File 'lib/bitcoin/protocol/txin.rb', line 26

def script_witness
  @script_witness
end

#sequenceObject

sequence


32
33
34
# File 'lib/bitcoin/protocol/txin.rb', line 32

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)


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

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)


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

def sig_hash
  @sig_hash
end

Class Method Details

.from_hash(input) ⇒ Object


108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/bitcoin/protocol/txin.rb', line 108

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)
  txin.script_sig = if input['coinbase']
                      [input['coinbase']].pack('H*')
                    else
                      Script.binary_from_string(input['scriptSig'] || input['script'])
                    end
  input['witness'].each { |w| txin.script_witness.stack << w.htb } if input['witness']
  txin.sequence = [input['sequence'] || 0xffffffff].pack('V')
  txin
end

.from_hex_hash(hash, index) ⇒ Object


122
123
124
# File 'lib/bitcoin/protocol/txin.rb', line 122

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

.from_io(buf) ⇒ Object


74
75
76
77
78
# File 'lib/bitcoin/protocol/txin.rb', line 74

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

Instance Method Details

#==(other) ⇒ Object

compare to another txout


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

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 StandardError
  false
end

#add_signature_pubkey_script(sig, pubkey_hex) ⇒ Object


143
144
145
# File 'lib/bitcoin/protocol/txin.rb', line 143

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)

132
133
134
# File 'lib/bitcoin/protocol/txin.rb', line 132

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

#final?Boolean

returns true if the sequence number is final (DEFAULT_SEQUENCE)

Returns:

  • (Boolean)

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

def final?
  sequence == DEFAULT_SEQUENCE
end

#is_final?Boolean

rubocop:disable Naming/PredicateName

Returns:

  • (Boolean)

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

def is_final? # rubocop:disable Naming/PredicateName
  warn '[DEPRECATION] `TxIn.is_final?` is deprecated. Use `final?` instead.'
  final?
end

#parse_data(data) ⇒ Object

parse raw binary data for transaction input


68
69
70
71
72
# File 'lib/bitcoin/protocol/txin.rb', line 68

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


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

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


87
88
89
# File 'lib/bitcoin/protocol/txin.rb', line 87

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

#prev_out=(hash) ⇒ Object


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

def prev_out=(hash)
  @prev_out_hash = hash
end

#previous_outputObject

previous output in hex


127
128
129
# File 'lib/bitcoin/protocol/txin.rb', line 127

def previous_output
  @prev_out_hash.reverse_hth
end

#to_hash(_options = {}) ⇒ Object


96
97
98
99
100
101
102
103
104
105
106
# File 'lib/bitcoin/protocol/txin.rb', line 96

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(&:bth) unless @script_witness.empty?
  t
end

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


91
92
93
94
# File 'lib/bitcoin/protocol/txin.rb', line 91

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