Class: MixinBot::Transaction::Decoder

Inherits:
Object
  • Object
show all
Defined in:
lib/mixin_bot/transaction/decoder.rb

Overview

Parses raw transaction bytes into a MixinBot::Transaction instance.

Instance Method Summary collapse

Constructor Details

#initialize(transaction) ⇒ Decoder

Returns a new instance of Decoder.



9
10
11
# File 'lib/mixin_bot/transaction/decoder.rb', line 9

def initialize(transaction)
  @tx = transaction
end

Instance Method Details

#decodeObject

Raises:



13
14
15
16
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
55
56
57
58
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
# File 'lib/mixin_bot/transaction/decoder.rb', line 13

def decode
  raw = [@tx.hex].pack('H*').bytes
  @tx.hash = SHA3::Digest::SHA256.hexdigest(raw.pack('C*'))
  @buf = Buffer.new(raw)

  magic = @buf.shift(2)
  raise ArgumentError, 'Not valid raw' unless magic == Transaction::MAGIC

  _version = @buf.shift(2)
  @tx.version = MixinBot.utils.decode_int _version

  asset = @buf.shift(32)
  @tx.asset = asset.pack('C*').unpack1('H*')

  decode_inputs
  decode_outputs
  decode_references if @tx.version >= Transaction::REFERENCES_TX_VERSION && @tx.references.present?

  extra_size = MixinBot.utils.decode_uint32 @buf.shift(4)
  @tx.extra = @buf.shift(extra_size).pack('C*')

  num = MixinBot.utils.decode_uint16 @buf.shift(2)
  if num == Transaction::MAX_ENCODE_INT
    @tx.aggregated = {}

    prefix = MixinBot.utils.decode_uint16(@buf.shift(2))
    raise ArgumentError, 'invalid aggregated' unless prefix == Transaction::AGGREGATED_SIGNATURE_PREFIX

    @tx.aggregated['signature'] = @buf.shift(64).pack('C*').unpack1('H*')

    byte = @buf.shift
    case byte
    when Transaction::AGGREGATED_SIGNATURE_ORDINAY_MASK.first
      @tx.aggregated['signers'] = []
      masks_size = MixinBot.utils.decode_uint16 @buf.shift(2)
      masks = @buf.shift(masks_size)
      masks = Array(masks)

      masks.each_with_index do |mask, i|
        8.times do |j|
          k = 1 << j
          @tx.aggregated['signers'].push((i * 8) + j) if mask & k == k
        end
      end
    when Transaction::AGGREGATED_SIGNATURE_SPARSE_MASK.first
      signers_size = MixinBot.utils.decode_uint16 @buf.shift(2)
      @tx.aggregated['signers'] = []
      unless signers_size.zero?
        signers_size.times do
          @tx.aggregated['signers'].push MixinBot.utils.decode_uint16(@buf.shift(2))
        end
      end
    end
  elsif num.present? && num.positive? && @buf.size.positive?
    @tx.signatures = []
    num.times do
      signature = {}

      keys_size = MixinBot.utils.decode_uint16 @buf.shift(2)

      keys_size.times do
        index = MixinBot.utils.decode_uint16 @buf.shift(2)
        signature[index] = @buf.shift(64).pack('C*').unpack1('H*')
      end

      @tx.signatures << signature
    end
  end

  @tx
end