Class: Hive::Marshal
  
  
  
  
    
      Constant Summary
      collapse
    
    
      
        - PUBLIC_KEY_DISABLED =
          
        
- '1111111111111111111111111111111114T1Anm'
 
Constants included
     from ChainConfig
  ChainConfig::EXPIRE_IN_SECS, ChainConfig::EXPIRE_IN_SECS_PROPOSAL, ChainConfig::NETWORKS_HIVE_ADDRESS_PREFIX, ChainConfig::NETWORKS_HIVE_CHAIN_ID, ChainConfig::NETWORKS_HIVE_CORE_ASSET, ChainConfig::NETWORKS_HIVE_DEBT_ASSET, ChainConfig::NETWORKS_HIVE_DEFAULT_NODE, ChainConfig::NETWORKS_HIVE_LEGACY_CHAIN_ID, ChainConfig::NETWORKS_HIVE_VEST_ASSET, ChainConfig::NETWORKS_TEST_ADDRESS_PREFIX, ChainConfig::NETWORKS_TEST_CHAIN_ID, ChainConfig::NETWORKS_TEST_CORE_ASSET, ChainConfig::NETWORKS_TEST_DEBT_ASSET, ChainConfig::NETWORKS_TEST_DEFAULT_NODE, ChainConfig::NETWORKS_TEST_VEST_ASSET, ChainConfig::NETWORK_CHAIN_IDS
  Instance Attribute Summary collapse
  
  
    
      Instance Method Summary
      collapse
    
    
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  Methods included from Utils
  #hexlify, #unhexlify
  Constructor Details
  
    
  
  
    #initialize(options = {})  ⇒ Marshal 
  
  
  
  
    
Returns a new instance of Marshal.
   
 
  
  
    | 
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | # File 'lib/hive/marshal.rb', line 13
def initialize(options = {})
  @bytes = if !!(hex = options[:hex])
    unhexlify hex
  else
    options[:bytes]
  end
  
  @chain = options[:chain] || :hive
  @prefix ||= case @chain
  when :hive then NETWORKS_HIVE_ADDRESS_PREFIX
  when :test then NETWORKS_TEST_ADDRESS_PREFIX
  else; raise UnsupportedChainError, "Unsupported chain: #{@chain}"
  end
  @cursor = 0
end
 | 
 
  
 
  
    Instance Attribute Details
    
      
      
      
  
  
    #bytes  ⇒ Object  
  
  
  
  
    
Returns the value of attribute bytes.
   
 
  
  
    | 
11
12
13 | # File 'lib/hive/marshal.rb', line 11
def bytes
  @bytes
end
 | 
 
    
      
      
      
  
  
    #cursor  ⇒ Object  
  
  
  
  
    
Returns the value of attribute cursor.
   
 
  
  
    | 
11
12
13 | # File 'lib/hive/marshal.rb', line 11
def cursor
  @cursor
end
 | 
 
    
   
  
    Instance Method Details
    
      
  
  
    #amount  ⇒ Object 
  
  
  
  
    | 
101
102
103
104
105
106
107
108
109 | # File 'lib/hive/marshal.rb', line 101
def amount
  amount = uint64.to_f
  precision = signed_char
  asset = scan(7).strip
  
  amount = "%.#{precision}f #{asset}" % (amount / 10 ** precision)
  Hive::Type::Amount.new(amount)
end
 | 
 
    
      
  
  
    #authority(options = {optional: false})  ⇒ Object 
  
  
  
  
    | 
115
116
117
118
119
120
121
122
123 | # File 'lib/hive/marshal.rb', line 115
def authority(options = {optional: false})
  return if !!options[:optional] && unsigned_char == 0
  
  {
    weight_threshold: uint32,
    account_auths: varint.times.map { [string, uint16] },
    key_auths: varint.times.map { [public_key, uint16] }
  }
end
 | 
 
    
      
  
  
    #beneficiaries  ⇒ Object 
  
  
  
  
    | 
137
138
139
140
141 | # File 'lib/hive/marshal.rb', line 137
def beneficiaries
  if scan(1) == "\x00"
    varint.times.map {{account: string, weight: uint16}}
  end
end
 | 
 
    
      
  
  
    #boolean  ⇒ Object 
  
  
  
  
    | 
59 | # File 'lib/hive/marshal.rb', line 59
def boolean; scan(1) == "\x01"; end
 | 
 
    
      
  
  
    #chain_properties  ⇒ Object 
  
  
  
  
    | 
143
144
145
146
147
148
149 | # File 'lib/hive/marshal.rb', line 143
def chain_properties
  {
    account_creation_fee: amount,
    maximum_block_size: uint32,
    sbd_interest_rate: uint16
  }
end
 | 
 
    
      
  
  
    | 
129
130
131
132
133
134
135 | # File 'lib/hive/marshal.rb', line 129
def 
  if scan(1) == "\x01"
    beneficiaries
  else
    []
  end
end
 | 
 
    
      
  
  
    #empty_array  ⇒ Object 
  
  
  
  
    | 
178
179
180 | # File 'lib/hive/marshal.rb', line 178
def empty_array
  unsigned_char == 0 and [] or raise "Found non-empty array."
end
 | 
 
    
      
  
  
    #hex  ⇒ Object 
  
  
  
  
    | 
29
30
31 | # File 'lib/hive/marshal.rb', line 29
def hex
  hexlify bytes
end
 | 
 
    
      
  
  
    #int16  ⇒ Object 
  
  
  
  
    
16-bit signed, little-endian
   
 
  
  
    | 
55 | # File 'lib/hive/marshal.rb', line 55
def int16; BinData::Int16le.read(scan(2)); end
 | 
 
    
      
  
  
    #int32  ⇒ Object 
  
  
  
  
    
32-bit signed, little-endian
   
 
  
  
    | 
56 | # File 'lib/hive/marshal.rb', line 56
def int32; BinData::Int32le.read(scan(4)); end
 | 
 
    
      
  
  
    #int64  ⇒ Object 
  
  
  
  
    
64-bit signed, little-endian
   
 
  
  
    | 
57 | # File 'lib/hive/marshal.rb', line 57
def int64; BinData::Int64le.read(scan(8)); end
 | 
 
    
      
  
  
    #operation_type  ⇒ Object 
  
  
  
  
    | 
45
46
47 | # File 'lib/hive/marshal.rb', line 45
def operation_type
  Operation::IDS[unsigned_char]
end
 | 
 
    
      
  
  
    #operations  ⇒ Object 
  
  
  
  
    | 
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232 | # File 'lib/hive/marshal.rb', line 200
def operations
  operations_len = signed_char
  operations = []
  
  while operations.size < operations_len do
    begin
      type = operation_type
      break if type.nil?
      
      op_class_name = type.to_s.sub!(/_operation$/, '')
      op_class_name = "Hive::Operation::" + op_class_name.split('_').map(&:capitalize).join
      op_class = Object::const_get(op_class_name)
      op = op_class.new
      
      op_class::serializable_types.each do |k, v|
        begin
          
          op.send("#{k}=", send(v))
        rescue => e
          raise DeserializationError.new("#{type}.#{k} (#{v}) failed", e)
        end
      end
      
      operations << {type: type, value: op}
    rescue => e
      raise DeserializationError.new("#{type} failed", e)
    end
  end
  
  operations
rescue => e
  raise DeserializationError.new("Operations failed", e)
end
 | 
 
    
      
  
  
    #optional_authority  ⇒ Object 
  
  
  
  
    | 
125
126
127 | # File 'lib/hive/marshal.rb', line 125
def optional_authority
  authority(optional: true)
end
 | 
 
    
      
  
  
    #point_in_time  ⇒ Object 
  
  
  
  
    | 
85
86
87
88
89
90
91 | # File 'lib/hive/marshal.rb', line 85
def point_in_time
  if (time = uint32) == 2**32-1
    Time.at -1
  else
    Time.at time
  end.utc
end
 | 
 
    
      
  
  
    #price  ⇒ Object 
  
  
  
  
    | 
111
112
113 | # File 'lib/hive/marshal.rb', line 111
def price
  {base: amount, quote: amount}
end
 | 
 
    
      
  
  
    #public_key(prefix = @prefix)  ⇒ Object 
  
  
  
  
    | 
93
94
95
96
97
98
99 | # File 'lib/hive/marshal.rb', line 93
def public_key(prefix = @prefix)
  raw_public_key = raw_bytes(33)
  checksum = OpenSSL::Digest::RIPEMD160.digest(raw_public_key)
  key = Base58.binary_to_base58(raw_public_key + checksum.slice(0, 4), :bitcoin)
  
  prefix + key unless key == PUBLIC_KEY_DISABLED
end
 | 
 
    
      
  
  
    #raw_bytes(len = nil)  ⇒ Object 
  
  
  
  
    | 
83 | # File 'lib/hive/marshal.rb', line 83
def raw_bytes(len = nil); scan(len || varint).force_encoding('BINARY'); end
 | 
 
    
      
  
  
    #required_auths  ⇒ Object 
  
  
  
  
    | 
151
152
153 | # File 'lib/hive/marshal.rb', line 151
def required_auths
  varint.times.map { string }
end
 | 
 
    
      
  
  
    #rewind!  ⇒ Object 
  
  
  
  
    | 
33
34
35 | # File 'lib/hive/marshal.rb', line 33
def rewind!
  @cursor = 0
end
 | 
 
    
      
  
  
    #scan(len)  ⇒ Object 
  
  
  
  
    | 
41
42
43 | # File 'lib/hive/marshal.rb', line 41
def scan(len)
  bytes.slice(@cursor..(@cursor - 1) + len).tap { |_| @cursor += len }
end
 | 
 
    
      
  
  
    #signed_char  ⇒ Object 
  
  
  
  
  
    | 
54 | # File 'lib/hive/marshal.rb', line 54
def signed_char; BinData::Int8le.read(scan(1)); end
 | 
 
    
      
  
  
    #step(n = 0)  ⇒ Object 
  
  
  
  
    | 
37
38
39 | # File 'lib/hive/marshal.rb', line 37
def step(n = 0)
  @cursor += n
end
 | 
 
    
      
  
  
    #string(len = nil)  ⇒ Object 
  
  
  
  
    | 
81 | # File 'lib/hive/marshal.rb', line 81
def string(len = nil); scan(len || varint); end
 | 
 
    
      
  
  
    #transaction(options = {})  ⇒ Object 
  
  
  
  
    | 
186
187
188
189
190
191
192
193
194
195
196
197
198 | # File 'lib/hive/marshal.rb', line 186
def transaction(options = {})
  trx = options[:trx] || Transaction.new
  
  trx.ref_block_num = uint16
  trx.ref_block_prefix = uint32
  trx.expiration = point_in_time
  
  trx.operations = operations
  
  trx
rescue => e
  raise DeserializationError.new("Transaction failed\nOriginal serialized bytes:\n[#{hex[0..(@cursor * 2) - 1]}]#{hex[((@cursor) * 2)..-1]}", e)
end
 | 
 
    
      
  
  
    #uint16  ⇒ Object 
  
  
  
  
    
16-bit unsigned, VAX (little-endian) byte order
   
 
  
  
    | 
50 | # File 'lib/hive/marshal.rb', line 50
def uint16; BinData::Uint16le.read(scan(2)); end
 | 
 
    
      
  
  
    #uint32  ⇒ Object 
  
  
  
  
    
32-bit unsigned, VAX (little-endian) byte order
   
 
  
  
    | 
51 | # File 'lib/hive/marshal.rb', line 51
def uint32; BinData::Uint32le.read(scan(4)); end
 | 
 
    
      
  
  
    #uint64  ⇒ Object 
  
  
  
  
    
64-bit unsigned, little-endian
   
 
  
  
    | 
52 | # File 'lib/hive/marshal.rb', line 52
def uint64; BinData::Uint64le.read(scan(8)); end
 | 
 
    
      
  
  
    #uint64_array  ⇒ Object 
  
  
  
  
    | 
182
183
184 | # File 'lib/hive/marshal.rb', line 182
def uint64_array
  varint.times{ uint64 }
end
 | 
 
    
      
  
  
    #unsigned_char  ⇒ Object 
  
  
  
  
  
    | 
49 | # File 'lib/hive/marshal.rb', line 49
def unsigned_char; BinData::Uint8le.read(scan(1)); end
 | 
 
    
      
  
  
    #varint  ⇒ Object 
  
  
  
  
    | 
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 | # File 'lib/hive/marshal.rb', line 61
def varint
  shift = 0
  result = 0
  bytes = []
  
  while (n = unsigned_char) >> 7 == 1
    bytes << n
  end
  
  bytes << n
  
  bytes.each do |b|
    result += ((b & 0x7f) << shift)
    break unless (b & 0x80)
    shift += 7
  end
  
  result
end
 | 
 
    
      
  
  
    #witness_properties  ⇒ Object 
  
  
  
  
    | 
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176 | # File 'lib/hive/marshal.rb', line 155
def witness_properties
  properties = {}
  
  varint.times do
    key = string.to_sym
    properties[key] = case key
    when :account_creation_fee then Hive::Type::Amount.new(string)
    
    
    when :sbd_exchange_rate
      JSON[string].tap do |rate|
        rate["base"] = Hive::Type::Amount.new(rate["base"])
        rate["quote"] = Hive::Type::Amount.new(rate["quote"])
      end
    
    when :url, :key, :new_signing_key then string
    else; warn "Unsupported witness property: #{key}"
    end
  end
  
  properties
end
 |