Class: BTC::TransactionInput
- Inherits:
-
Object
- Object
- BTC::TransactionInput
- Defined in:
- lib/btcruby/transaction_input.rb
Constant Summary collapse
- INVALID_INDEX =
aka "(unsigned int) -1" in BitcoinQT.
0xFFFFFFFF- MAX_SEQUENCE =
0xFFFFFFFF- ZERO_HASH256 =
"\x00".b*32
Instance Attribute Summary collapse
-
#coinbase_data ⇒ Object
Binary String contained in signature script in coinbase input.
-
#data ⇒ Object
readonly
Binary representation of the input in wire format (aka payload).
-
#dictionary ⇒ Object
readonly
Dictionary representation of transaction ready to be encoded in JSON, PropertyList etc.
-
#index ⇒ Object
Optional index within owning transaction.
-
#previous_hash ⇒ Object
Hash of the previous transaction (raw binary hash).
-
#previous_id ⇒ Object
ID of a previous transaction (reversed hash in hex).
-
#previous_index ⇒ Object
Index of the previous transaction's output (uint32_t).
-
#sequence ⇒ Object
Input sequence (uint32_t).
-
#signature_script ⇒ Object
BTC::Script instance that proves ownership of the previous transaction output.
-
#transaction ⇒ Object
Optional reference to the owning transaction.
-
#transaction_output ⇒ Object
Optional attribute referencing an output that this input is spending.
-
#value ⇒ Object
Optional attribute containing a value in the corresponding output (in satoshis).
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
-
#coinbase? ⇒ Boolean
Returns true if this input is a coinbase input.
-
#dup ⇒ Object
Makes a deep copy of a transaction input.
- #final? ⇒ Boolean
- #init_with_dictionary(dict) ⇒ Object
- #init_with_stream(stream) ⇒ Object
-
#initialize(data: nil, stream: nil, dictionary: nil, previous_hash: ZERO_HASH256, previous_id: nil, previous_index: INVALID_INDEX, coinbase_data: nil, signature_script: BTC::Script.new, sequence: MAX_SEQUENCE, transaction: nil, transaction_output: nil, value: nil) ⇒ TransactionInput
constructor
Initializes transaction input with its attributes.
- #inspect(style = :full) ⇒ Object
- #outpoint ⇒ Object
- #outpoint=(outpoint) ⇒ Object
- #to_h ⇒ Object
- #to_s ⇒ Object
Constructor Details
#initialize(data: nil, stream: nil, dictionary: nil, previous_hash: ZERO_HASH256, previous_id: nil, previous_index: INVALID_INDEX, coinbase_data: nil, signature_script: BTC::Script.new, sequence: MAX_SEQUENCE, transaction: nil, transaction_output: nil, value: nil) ⇒ TransactionInput
Initializes transaction input with its attributes. Every attribute has a valid default value.
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 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/btcruby/transaction_input.rb', line 59 def initialize(data: nil, stream: nil, dictionary: nil, previous_hash: ZERO_HASH256, previous_id: nil, previous_index: INVALID_INDEX, coinbase_data: nil, signature_script: BTC::Script.new, sequence: MAX_SEQUENCE, # optional attributes transaction: nil, transaction_output: nil, value: nil) if stream || data init_with_stream(stream || StringIO.new(data)) elsif dictionary init_with_dictionary(dictionary) else @previous_hash = previous_hash || ZERO_HASH256 @previous_hash = BTC.hash_from_id(previous_id) if previous_id @previous_index = previous_index || INVALID_INDEX @coinbase_data = coinbase_data || "".b @signature_script = signature_script || BTC::Script.new @sequence = sequence || MAX_SEQUENCE end @transaction = transaction @transaction_output = transaction_output # Try to set outpoint data based on transaction output. if @transaction_output if @previous_hash == ZERO_HASH256 @previous_hash = @transaction_output.transaction_hash || ZERO_HASH256 end if @previous_index == INVALID_INDEX @previous_index = @transaction_output.index || INVALID_INDEX end end @value = value end |
Instance Attribute Details
#coinbase_data ⇒ Object
Binary String contained in signature script in coinbase input. Returns nil if it is not a coinbase input.
28 29 30 |
# File 'lib/btcruby/transaction_input.rb', line 28 def coinbase_data @coinbase_data end |
#data ⇒ Object (readonly)
Binary representation of the input in wire format (aka payload).
36 37 38 |
# File 'lib/btcruby/transaction_input.rb', line 36 def data @data end |
#dictionary ⇒ Object (readonly)
Dictionary representation of transaction ready to be encoded in JSON, PropertyList etc.
39 40 41 |
# File 'lib/btcruby/transaction_input.rb', line 39 def dictionary @dictionary end |
#index ⇒ Object
Optional index within owning transaction.
It is set in tx.add_input and reset to nil in tx.remove_all_inputs.
Default is nil.
49 50 51 |
# File 'lib/btcruby/transaction_input.rb', line 49 def index @index end |
#previous_hash ⇒ Object
Hash of the previous transaction (raw binary hash)
13 14 15 |
# File 'lib/btcruby/transaction_input.rb', line 13 def previous_hash @previous_hash end |
#previous_id ⇒ Object
ID of a previous transaction (reversed hash in hex)
16 17 18 |
# File 'lib/btcruby/transaction_input.rb', line 16 def previous_id @previous_id end |
#previous_index ⇒ Object
Index of the previous transaction's output (uint32_t).
19 20 21 |
# File 'lib/btcruby/transaction_input.rb', line 19 def previous_index @previous_index end |
#sequence ⇒ Object
Input sequence (uint32_t). Default is maximum value 0xFFFFFFFF. Sequence is used to update a timelocked tx stored in memory of the nodes. It is only relevant when tx lock_time > 0. Currently, for DoS and security reasons, nodes do not store timelocked transactions making the sequence number meaningless.
33 34 35 |
# File 'lib/btcruby/transaction_input.rb', line 33 def sequence @sequence end |
#signature_script ⇒ Object
BTC::Script instance that proves ownership of the previous transaction output. We intentionally do not call it "script" to avoid accidental confusion with TransactionOutput#script.
24 25 26 |
# File 'lib/btcruby/transaction_input.rb', line 24 def signature_script @signature_script end |
#transaction ⇒ Object
Optional reference to the owning transaction.
It is set in tx.add_input and reset to nil in tx.remove_all_inputs.
Default is nil.
44 45 46 |
# File 'lib/btcruby/transaction_input.rb', line 44 def transaction @transaction end |
#transaction_output ⇒ Object
Optional attribute referencing an output that this input is spending.
52 53 54 |
# File 'lib/btcruby/transaction_input.rb', line 52 def transaction_output @transaction_output end |
#value ⇒ Object
Optional attribute containing a value in the corresponding output (in satoshis). Default is transaction_output.value or nil.
56 57 58 |
# File 'lib/btcruby/transaction_input.rb', line 56 def value @value end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
266 267 268 269 270 |
# File 'lib/btcruby/transaction_input.rb', line 266 def ==(other) return true if super(other) return true if self.data == other.data return false end |
#coinbase? ⇒ Boolean
Returns true if this input is a coinbase input.
192 193 194 |
# File 'lib/btcruby/transaction_input.rb', line 192 def coinbase? return self.previous_index == INVALID_INDEX && self.previous_hash == ZERO_HASH256 end |
#dup ⇒ Object
Makes a deep copy of a transaction input
274 275 276 277 278 279 280 281 282 283 |
# File 'lib/btcruby/transaction_input.rb', line 274 def dup TransactionInput.new(previous_hash: @previous_hash.dup, previous_index: @previous_index, signature_script: @signature_script ? @signature_script.dup : nil, coinbase_data: @coinbase_data ? @coinbase_data.dup : nil, sequence: @sequence, transaction: @transaction, transaction_output: @transaction_output, # not dup-ing txout because it's a transient object without #== value: @value) end |
#final? ⇒ Boolean
213 214 215 |
# File 'lib/btcruby/transaction_input.rb', line 213 def final? self.sequence == MAX_SEQUENCE end |
#init_with_dictionary(dict) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/btcruby/transaction_input.rb', line 134 def init_with_dictionary(dict) raise ArgumentError, "Dictionary is missing" if !dict # Supports bitcoin-QT RPC format if dict["prev_out"] && !dict["prev_out"].is_a?(Hash) raise ArgumentError, "prev_out is not a dictionary." end prevhash = ZERO_HASH256 previndex = INVALID_INDEX script = nil seq = MAX_SEQUENCE if dict["prev_out"] if hashhex = dict["prev_out"]["hash"] prevhash = BTC.from_hex(hashhex) if prevhash.bytesize != 32 raise ArgumentError, "prev_out.hash is not 32 bytes long." end end if n = dict["prev_out"]["n"] index = n.to_i if index < 0 || index > 0xffffffff raise ArgumentError, "prev_out.n is out of bounds (#{index})." end previndex = index end end coinbase_data = nil script = nil if hex = dict["coinbase"] coinbase_data = BTC.from_hex(hex) elsif dict["scriptSig"] if dict["scriptSig"].is_a?(Hash) if hex = dict["scriptSig"]["hex"] script = BTC::Script.new(data: BTC.from_hex(hex)) end end end if dict["sequence"] seq = dict["sequence"].to_i if seq < 0 || seq > MAX_SEQUENCE raise ArgumentError, "sequence is out of bounds (#{index})." end end @previous_hash = prevhash @previous_index = previndex, @coinbase_data = coinbase_data @signature_script = script @sequence = seq end |
#init_with_stream(stream) ⇒ Object
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 127 128 129 130 131 132 |
# File 'lib/btcruby/transaction_input.rb', line 101 def init_with_stream(stream) if stream.eof? raise ArgumentError, "Can't parse transaction input from stream because it is already closed." end if !(@previous_hash = stream.read(32)) || @previous_hash.bytesize != 32 raise ArgumentError, "Failed to read 32-byte previous_hash from stream." end if !(@previous_index = BTC::WireFormat.read_uint32le(stream: stream).first) raise ArgumentError, "Failed to read previous_index from stream." end is_coinbase = (@previous_hash == ZERO_HASH256 && @previous_index == INVALID_INDEX) if !(scriptdata = BTC::WireFormat.read_string(stream: stream).first) raise ArgumentError, "Failed to read signature_script data from stream." end @coinbase_data = nil @signature_script = nil if is_coinbase @coinbase_data = scriptdata else @signature_script = BTC::Script.new(data: scriptdata) end if !(@sequence = BTC::WireFormat.read_uint32le(stream: stream).first) raise ArgumentError, "Failed to read sequence from stream." end end |
#inspect(style = :full) ⇒ Object
285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/btcruby/transaction_input.rb', line 285 def inspect(style = :full) if style == :full %{#<#{self.class.name} prev:#{self.previous_id}[#{self.previous_index}]} + %{ script:#{self.signature_script.to_s.inspect}} + %{ seq:#{self.sequence}} + %{>} else %{#<#{self.class.name} prev:#{self.previous_id[0,10]}[#{self.previous_index}]} + %{ script:#{self.signature_script.to_s.inspect}} + (self.sequence != MAX_SEQUENCE ? %{ seq:#{self.sequence}} : %{}) + %{>} end end |
#outpoint ⇒ Object
204 205 206 |
# File 'lib/btcruby/transaction_input.rb', line 204 def outpoint Outpoint.new(transaction_hash: previous_hash, index: previous_index) end |
#outpoint=(outpoint) ⇒ Object
208 209 210 211 |
# File 'lib/btcruby/transaction_input.rb', line 208 def outpoint=(outpoint) self.previous_hash = outpoint.transaction_hash self.previous_index = outpoint.index end |
#to_h ⇒ Object
258 259 260 |
# File 'lib/btcruby/transaction_input.rb', line 258 def to_h self.dictionary end |