Class: RawTx
- Inherits:
-
Object
- Object
- RawTx
- Defined in:
- lib/counterparty/raw_tx.rb
Overview
This class is mostly used to decode json transactions from raw transactions much of this implementation was inspired from: gist.github.com/shesek/5835695
Constant Summary collapse
- BASE64_CHARS =
This is a map of offset to characters used for decoding base64 strings:
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
- MAX_32BIT_INTEGER =
2**32-1
Class Method Summary collapse
-
.bytes_to_base64_s(input_bytes) ⇒ Object
Convert an array of bytes to a base64 string.
-
.bytes_to_ui(bytes) ⇒ Object
Convert an array of 8 bit numbers into an unsigned int, Remember that for each input byte, the most significant nibble comes last.
-
.nibbles_to_ui(nibbles) ⇒ Object
Convert an array of 4 bit numbers into an unsigned int, works for numbers up to 32-bit only.
Instance Method Summary collapse
-
#initialize(as_hexstring) ⇒ RawTx
constructor
Creates a raw transaction from a hexstring.
-
#to_hash(options = {}) ⇒ Object
Returns this transaction in a standard json format.
Constructor Details
#initialize(as_hexstring) ⇒ RawTx
Creates a raw transaction from a hexstring
11 12 13 14 |
# File 'lib/counterparty/raw_tx.rb', line 11 def initialize(as_hexstring) @hexstring = as_hexstring.downcase raise ArgumentError, "Unsupported hex" unless /\A[0-9a-f]+\Z/.match @hexstring end |
Class Method Details
.bytes_to_base64_s(input_bytes) ⇒ Object
Convert an array of bytes to a base64 string.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/counterparty/raw_tx.rb', line 73 def self.bytes_to_base64_s(input_bytes) input_bytes.each_slice(3).collect.with_index{ |bytes,i| # This is the base offset of this 3-byte slice in the sequence: i_triplet = i*3 # Here we compose a triplet by or'ing the shifted bytes: triplet = bytes.collect.with_index{|b,j| b << 8*(2-j) }.reduce(:|) # And here we convert to chars, unless with equals as nil-padding: 0.upto(3).collect do |j| (i_triplet * 8 + j * 6 <= input_bytes.length * 8) ? BASE64_CHARS[((triplet >> 6 * (3 - j)) & 0x3F)] : '=' end }.join end |
.bytes_to_ui(bytes) ⇒ Object
Convert an array of 8 bit numbers into an unsigned int, Remember that for each input byte, the most significant nibble comes last.
67 68 69 70 |
# File 'lib/counterparty/raw_tx.rb', line 67 def self.bytes_to_ui(bytes) nibbles = bytes.collect{|b| [b & 0x0f, (b & 0xf0) >> 4]}.flatten nibbles.each_with_index.inject(0){|sum,(b,i)| sum += b * 16**i} end |
.nibbles_to_ui(nibbles) ⇒ Object
Convert an array of 4 bit numbers into an unsigned int, works for numbers up to 32-bit only
58 59 60 61 62 63 |
# File 'lib/counterparty/raw_tx.rb', line 58 def self.nibbles_to_ui(nibbles) raise ArgumentError if nibbles.length > 4 nibbles.each_with_index.inject(0){ |sum, (b,i)| sum += (b.to_i & 0xff) << (4 * i) } end |
Instance Method Details
#to_hash(options = {}) ⇒ Object
Returns this transaction in a standard json format
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/counterparty/raw_tx.rb', line 17 def to_hash( = {}) bytes = @hexstring.scan(/../).collect(&:hex) size = bytes.length # Now we start shift elements off the byte stack: version = shift_u32(bytes) raise ArgumentError, "Unsupported Version/Tx" unless version == 0x01 # Parse the inputs: ins = (0...shift_varint(bytes)).collect do hash = bytes.slice!(0,32).reverse.collect{|n| '%02x' % n}.join index,script,seq = shift_u32(bytes),shift_varchar(bytes),shift_u32(bytes) # NOTE: We may want to base64 encode the hash, or support this via an # option : self.class.bytes_to_base64_s(hash).reverse), # NOTE: The :seq field isnt actually used right now, so some rawtx decoders # return the varint (like decoder), and some return UINT_MAX (4294967295) { 'txid' => hash, 'vout' => index, 'sequence' => MAX_32BIT_INTEGER, 'scriptSig' => {'hex' => hex_stringify(script), 'asm' => disassemble_script(script) } } end # Parse outputs: outs = (0...shift_varint(bytes)).collect do |i| value, script = shift_u64(bytes), shift_varchar(bytes) { 'value' => self.class.bytes_to_ui(value).to_f/1e8, 'n' => i, 'scriptPubKey' => {'hex' => hex_stringify(script), 'asm' => disassemble_script(script) } } end lock_time = shift_u32 bytes {'vin' => ins, 'vout' => outs, 'lock_time' => lock_time, 'ver' => version, 'vin_sz' => ins.length, 'vout_sz' => outs.length, 'size' => size} end |