Class: Tapyrus::Tx
Overview
Transaction class
Constant Summary collapse
- MAX_STANDARD_VERSION =
2
- MAX_STANDARD_TX_WEIGHT =
The maximum weight for transactions we’re willing to relay/mine
400_000
Instance Attribute Summary collapse
-
#features ⇒ Object
Returns the value of attribute features.
-
#inputs ⇒ Object
(also: #in)
readonly
Returns the value of attribute inputs.
-
#lock_time ⇒ Object
Returns the value of attribute lock_time.
-
#outputs ⇒ Object
(also: #out)
readonly
Returns the value of attribute outputs.
Class Method Summary collapse
Instance Method Summary collapse
- #==(other) ⇒ Object
- #coinbase_tx? ⇒ Boolean
- #hash ⇒ Object
-
#initialize ⇒ Tx
constructor
A new instance of Tx.
-
#sighash_for_input(input_index, output_script, hash_type: ) ⇒ String
Generate signature hash.
-
#size ⇒ Object
The serialized transaction size.
-
#standard? ⇒ Boolean
check this tx is standard.
- #to_h ⇒ Object
- #to_payload ⇒ Object
- #tx_hash ⇒ Object
- #txid ⇒ Object
-
#valid? ⇒ Boolean
Verify transaction validity.
-
#verify_input_sig(input_index, script_pubkey, flags: STANDARD_SCRIPT_VERIFY_FLAGS) ⇒ Object
verify input signature.
Methods included from HexConverter
Constructor Details
#initialize ⇒ Tx
Returns a new instance of Tx.
19 20 21 22 23 24 |
# File 'lib/tapyrus/tx.rb', line 19 def initialize @inputs = [] @outputs = [] @features = 1 @lock_time = 0 end |
Instance Attribute Details
#features ⇒ Object
Returns the value of attribute features.
14 15 16 |
# File 'lib/tapyrus/tx.rb', line 14 def features @features end |
#inputs ⇒ Object (readonly) Also known as: in
Returns the value of attribute inputs.
15 16 17 |
# File 'lib/tapyrus/tx.rb', line 15 def inputs @inputs end |
#lock_time ⇒ Object
Returns the value of attribute lock_time.
17 18 19 |
# File 'lib/tapyrus/tx.rb', line 17 def lock_time @lock_time end |
#outputs ⇒ Object (readonly) Also known as: out
Returns the value of attribute outputs.
16 17 18 |
# File 'lib/tapyrus/tx.rb', line 16 def outputs @outputs end |
Class Method Details
.parse_from_payload(payload) ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/tapyrus/tx.rb', line 29 def self.parse_from_payload(payload) buf = payload.is_a?(String) ? StringIO.new(payload) : payload tx = new tx.features = buf.read(4).unpack("V").first in_count = Tapyrus.unpack_var_int_from_io(buf) in_count.times { tx.inputs << TxIn.parse_from_payload(buf) } out_count = Tapyrus.unpack_var_int_from_io(buf) out_count.times { tx.outputs << TxOut.parse_from_payload(buf) } tx.lock_time = buf.read(4).unpack("V").first tx end |
Instance Method Details
#==(other) ⇒ Object
74 75 76 |
# File 'lib/tapyrus/tx.rb', line 74 def ==(other) to_payload == other.to_payload end |
#coinbase_tx? ⇒ Boolean
70 71 72 |
# File 'lib/tapyrus/tx.rb', line 70 def coinbase_tx? inputs.length == 1 && inputs.first.coinbase? end |
#hash ⇒ Object
46 47 48 |
# File 'lib/tapyrus/tx.rb', line 46 def hash to_hex.to_i(16) end |
#sighash_for_input(input_index, output_script, hash_type: ) ⇒ String
Generate signature hash
111 112 113 114 115 116 |
# File 'lib/tapyrus/tx.rb', line 111 def sighash_for_input(input_index, output_script, hash_type: SIGHASH_TYPE[:all]) raise ArgumentError, "input_index must be specified." unless input_index raise ArgumentError, "does not exist input corresponding to input_index." if input_index >= inputs.size raise ArgumentError, "script_pubkey must be specified." unless output_script sighash_for_legacy(input_index, output_script, hash_type) end |
#size ⇒ Object
The serialized transaction size
102 103 104 |
# File 'lib/tapyrus/tx.rb', line 102 def size to_payload.bytesize end |
#standard? ⇒ Boolean
check this tx is standard.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/tapyrus/tx.rb', line 79 def standard? return false if features > MAX_STANDARD_VERSION inputs.each do |i| # Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed keys (remember the 520 byte limit on redeemScript size). # That works out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627 # bytes of scriptSig, which we round off to 1650 bytes for some minor future-proofing. # That's also enough to spend a 20-of-20 CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not considered standard. return false if i.script_sig.size > 1650 return false unless i.script_sig.push_only? end data_count = 0 outputs.each do |o| return false unless o.script_pubkey.standard? data_count += 1 if o.script_pubkey.op_return? # TODO add non P2SH multisig relay(permitbaremultisig) return false if o.dust? end return false if data_count > 1 true end |
#to_h ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/tapyrus/tx.rb', line 127 def to_h { txid: txid, hash: tx_hash, features: features, size: size, locktime: lock_time, vin: inputs.map(&:to_h), vout: outputs.map.with_index { |tx_out, index| tx_out.to_h.merge({ n: index }) } } end |
#to_payload ⇒ Object
62 63 64 65 66 67 68 |
# File 'lib/tapyrus/tx.rb', line 62 def to_payload buf = [features].pack("V") buf << Tapyrus.pack_var_int(inputs.length) << inputs.map(&:to_payload).join buf << Tapyrus.pack_var_int(outputs.length) << outputs.map(&:to_payload).join buf << [lock_time].pack("V") buf end |
#tx_hash ⇒ Object
50 51 52 |
# File 'lib/tapyrus/tx.rb', line 50 def tx_hash Tapyrus.double_sha256(to_payload).bth end |
#txid ⇒ Object
54 55 56 57 58 59 60 |
# File 'lib/tapyrus/tx.rb', line 54 def txid buf = [features].pack("V") buf << Tapyrus.pack_var_int(inputs.length) << inputs.map { |i| i.to_payload(use_malfix: true) }.join buf << Tapyrus.pack_var_int(outputs.length) << outputs.map(&:to_payload).join buf << [lock_time].pack("V") Tapyrus.double_sha256(buf).reverse.bth end |
#valid? ⇒ Boolean
Verify transaction validity.
141 142 143 144 145 |
# File 'lib/tapyrus/tx.rb', line 141 def valid? state = Tapyrus::ValidationState.new validation = Tapyrus::Validation.new validation.check_tx(self, state) && state.valid? end |
#verify_input_sig(input_index, script_pubkey, flags: STANDARD_SCRIPT_VERIFY_FLAGS) ⇒ Object
verify input signature.
122 123 124 125 |
# File 'lib/tapyrus/tx.rb', line 122 def verify_input_sig(input_index, script_pubkey, flags: STANDARD_SCRIPT_VERIFY_FLAGS) flags << SCRIPT_VERIFY_P2SH if script_pubkey.p2sh? verify_input_sig_for_legacy(input_index, script_pubkey, flags) end |