scale_rb 0.1.14 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,180 @@
1
+ module ScaleRb
2
+ module HttpClient
3
+ class << self
4
+ # get_storage3 is a more ruby style function
5
+ #
6
+ # pallet_name and storage_name is pascal style like 'darwinia_staking'
7
+ def get_storage3(url, pallet_name, storage_name, key_part1: nil, key_part2: nil, metadata: nil, at: nil)
8
+ # Get metadata if not provided, and cache it.
9
+ # The default dir is `metadata` dir under the caller's dir.
10
+ # You can change it by setting `SCALE_RB_METADATA_DIR` env variable
11
+ metadata = get_metadata_cached(url, at: at) if metadata.nil?
12
+
13
+ pallet_name = to_pascal pallet_name
14
+ storage_name = to_pascal storage_name
15
+ ScaleRb.logger.debug "#{pallet_name}.#{storage_name}(#{[key_part1, key_part2].compact.join(', ')})"
16
+
17
+ key = [key_part1, key_part2].compact.map { |part_of_key| c(part_of_key) }
18
+ ScaleRb.logger.debug "converted key: #{key}"
19
+
20
+ get_storage2(
21
+ url,
22
+ pallet_name,
23
+ storage_name,
24
+ key,
25
+ metadata,
26
+ at
27
+ )
28
+ end
29
+
30
+ private
31
+
32
+ def query_storage_at(url, storage_keys, type_id, default, registry, at = nil)
33
+ result = state_queryStorageAt(url, storage_keys, at)
34
+ result.map do |item|
35
+ item['changes'].map do |change|
36
+ storage_key = change[0]
37
+ data = change[1] || default
38
+ storage = data.nil? ? nil : PortableCodec.decode(type_id, data._to_bytes, registry)[0]
39
+ { storage_key: storage_key, storage: storage }
40
+ end
41
+ end.flatten
42
+ end
43
+
44
+ def get_storage_keys_by_partial_key(url, partial_storage_key, start_key = nil, at = nil)
45
+ storage_keys = state_getKeysPaged(url, partial_storage_key, 1000, start_key, at)
46
+ if storage_keys.length == 1000
47
+ storage_keys + get_storage_keys_by_partial_key(url, partial_storage_key, storage_keys.last, at)
48
+ else
49
+ storage_keys
50
+ end
51
+ end
52
+
53
+ def get_storages_by_partial_key(url, partial_storage_key, type_id_of_value, default, registry, at = nil)
54
+ storage_keys = get_storage_keys_by_partial_key(url, partial_storage_key, partial_storage_key, at)
55
+ storage_keys.each_slice(250).map do |slice|
56
+ query_storage_at(
57
+ url,
58
+ slice,
59
+ type_id_of_value,
60
+ default,
61
+ registry,
62
+ at
63
+ )
64
+ end.flatten
65
+ end
66
+
67
+ # 1. Plain
68
+ # key: nil
69
+ # value: { type: 3, modifier: 'Default', callback: '' }
70
+ #
71
+ # 2. Map
72
+ # key: { value: value, type: 0, hashers: ['Blake2128Concat'] }
73
+ # value: { type: 3, modifier: 'Default', callback: '' }
74
+ #
75
+ # 3. Map, but key.value is nil
76
+ # key: { value: nil, type: 0, hashers: ['Blake2128Concat'] }
77
+ # value: { type: 3, modifier: 'Default', callback: '' }
78
+ #
79
+ # example:
80
+ # 'System',
81
+ # 'Account',
82
+ # key = {
83
+ # value: [['0x724d50824542b56f422588421643c4a162b90b5416ef063f2266a1eae6651641'._to_bytes]], # [AccountId]
84
+ # type: 0,
85
+ # hashers: ['Blake2128Concat']
86
+ # },
87
+ # value = {
88
+ # type: 3,
89
+ # modifier: 'Default',
90
+ # callback: '0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
91
+ # },
92
+ # ..
93
+ #
94
+ # TODO: part of the key is provided, but not all
95
+ def get_storage(url, pallet_name, item_name, key, value, registry, at = nil)
96
+ if key
97
+ if key[:value].nil? || key[:value].empty?
98
+ # map, but no key's value provided. get all storages under the partial storage key
99
+ partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name)._to_hex
100
+ get_storages_by_partial_key(
101
+ url,
102
+ partial_storage_key,
103
+ value[:type],
104
+ value[:modifier] == 'Default' ? value[:fallback] : nil,
105
+ registry,
106
+ at
107
+ )
108
+ elsif key[:value].length != key[:hashers].length
109
+ # map with multi parts, but not have all values
110
+ partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry)._to_hex
111
+ get_storages_by_partial_key(
112
+ url,
113
+ partial_storage_key,
114
+ value[:type],
115
+ value[:modifier] == 'Default' ? value[:fallback] : nil,
116
+ registry,
117
+ at
118
+ )
119
+ end
120
+ else
121
+ storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry)._to_hex
122
+ data = state_getStorage(url, storage_key, at)
123
+ StorageHelper.decode_storage(data, value[:type], value[:modifier] == 'Optional', value[:fallback], registry)
124
+ end
125
+ end
126
+
127
+ def get_storage2(url, pallet_name, item_name, value_of_key, metadata, at = nil)
128
+ raise 'Metadata should not be nil' if metadata.nil?
129
+
130
+ registry = Metadata.build_registry(metadata)
131
+ item = Metadata.get_storage_item(
132
+ pallet_name, item_name, metadata
133
+ )
134
+ raise "No such storage item: `#{pallet_name}`.`#{item_name}`" if item.nil?
135
+
136
+ modifier = item._get(:modifier) # Default | Optional
137
+ fallback = item._get(:fallback)
138
+ type = item._get(:type)
139
+
140
+ plain = type._get(:plain)
141
+ map = type._get(:map)
142
+ # debug
143
+
144
+ key, value =
145
+ if plain
146
+ [
147
+ nil,
148
+ { type: plain,
149
+ modifier: modifier, fallback: fallback }
150
+ ]
151
+ elsif map
152
+ [
153
+ { value: value_of_key,
154
+ type: map._get(:key), hashers: map._get(:hashers) },
155
+ { type: map._get(:value),
156
+ modifier: modifier, fallback: fallback }
157
+ ]
158
+ else
159
+ raise 'NoSuchStorageType'
160
+ end
161
+ get_storage(url, pallet_name, item_name, key, value, registry, at)
162
+ end
163
+
164
+ def to_pascal(str)
165
+ str.split('_').collect(&:capitalize).join
166
+ end
167
+
168
+ # convert key to byte array
169
+ def c(key)
170
+ if key.start_with?('0x')
171
+ key._to_bytes
172
+ elsif key.to_i.to_s == key # check if key is a number
173
+ key.to_i
174
+ else
175
+ key
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
@@ -2,52 +2,54 @@
2
2
 
3
3
  require 'json'
4
4
 
5
- module RpcRequestBuilder
6
- def build_json_rpc_body(method, params, id)
7
- {
8
- 'id' => id,
9
- 'jsonrpc' => '2.0',
10
- 'method' => method,
11
- 'params' => params.reject(&:nil?)
12
- }.to_json
13
- end
5
+ module ScaleRb
6
+ module RpcRequestBuilder
7
+ def build_json_rpc_body(method, params, id)
8
+ {
9
+ 'id' => id,
10
+ 'jsonrpc' => '2.0',
11
+ 'method' => method,
12
+ 'params' => params.reject(&:nil?)
13
+ }.to_json
14
+ end
14
15
 
15
- def respond_to_missing?(*_args)
16
- true
17
- end
16
+ def respond_to_missing?(*_args)
17
+ true
18
+ end
18
19
 
19
- # example:
20
- # state_getStorage(1, '0x363a..', 563_868)
21
- #
22
- # ==
23
- #
24
- # build_json_rpc_body('state_getStorage', ['0x363a..', 563_868], 1)
25
- def method_missing(method, *args)
26
- build_json_rpc_body(method, args[1..], args[0])
27
- end
20
+ # example:
21
+ # state_getStorage(1, '0x363a..', 563_868)
22
+ #
23
+ # ==
24
+ #
25
+ # build_json_rpc_body('state_getStorage', ['0x363a..', 563_868], 1)
26
+ def method_missing(method, *args)
27
+ build_json_rpc_body(method, args[1..], args[0])
28
+ end
28
29
 
29
- ###################################
30
- # derived functions
31
- ###################################
32
- def derived_state_get_storage(rpc_id, pallet_name, item_name, key = nil, registry = nil)
33
- storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry).to_hex
34
- state_getStorage(rpc_id, [storage_key])
35
- end
30
+ ###################################
31
+ # derived functions
32
+ ###################################
33
+ def derived_state_get_storage(rpc_id, pallet_name, item_name, key = nil, registry = nil)
34
+ storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry)._to_hex
35
+ state_getStorage(rpc_id, [storage_key])
36
+ end
36
37
 
37
- def derived_state_subscribe_storage(rpc_id, pallet_name, item_name, key = nil, registry = nil)
38
- storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry).to_hex
39
- state_subscribeStorage(rpc_id, [storage_key])
40
- end
38
+ def derived_state_subscribe_storage(rpc_id, pallet_name, item_name, key = nil, registry = nil)
39
+ storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry)._to_hex
40
+ state_subscribeStorage(rpc_id, [storage_key])
41
+ end
41
42
 
42
- def derived_eth_call(rpc_id, to, data, at = nil)
43
- eth_call(
44
- rpc_id,
45
- [
46
- {
47
- 'from' => nil, 'to' => to, 'data' => data
48
- },
49
- at
50
- ]
51
- )
43
+ def derived_eth_call(rpc_id, to, data, at = nil)
44
+ eth_call(
45
+ rpc_id,
46
+ [
47
+ {
48
+ 'from' => nil, 'to' => to, 'data' => data
49
+ },
50
+ at
51
+ ]
52
+ )
53
+ end
52
54
  end
53
55
  end
data/lib/codec.rb CHANGED
@@ -145,12 +145,12 @@ module ScaleRb
145
145
  when 0
146
146
  [bytes[0] >> 2, bytes[1..]]
147
147
  when 1
148
- [bytes[0..1].flip.to_uint >> 2, bytes[2..]]
148
+ [bytes[0..1]._flip._to_uint >> 2, bytes[2..]]
149
149
  when 2
150
- [bytes[0..3].flip.to_uint >> 2, bytes[4..]]
150
+ [bytes[0..3]._flip._to_uint >> 2, bytes[4..]]
151
151
  when 3
152
152
  length = 4 + (bytes[0] >> 2)
153
- [bytes[1..length].flip.to_uint, bytes[length + 1..]]
153
+ [bytes[1..length]._flip._to_uint, bytes[length + 1..]]
154
154
  else
155
155
  raise Unreachable, 'type: Compact'
156
156
  end
@@ -191,9 +191,9 @@ module ScaleRb
191
191
  # Decode
192
192
  class << self
193
193
  def decode(type, bytes, registry = {})
194
- logger.debug '--------------------------------------------------'
195
- debug 'decoding type', type
196
- debug 'bytes', bytes&.length
194
+ # logger.debug '--------------------------------------------------'
195
+ # debug 'decoding type', type
196
+ # debug 'bytes', bytes&.length
197
197
 
198
198
  if type.instance_of?(String)
199
199
  return decode_bytes(bytes) if bytes?(type) # Bytes
@@ -220,9 +220,9 @@ module ScaleRb
220
220
 
221
221
  def decode_bytes(bytes)
222
222
  length, remaining_bytes = _do_decode_compact(bytes)
223
- value = remaining_bytes[0...length].to_hex
224
- debug 'length', length
225
- debug 'value', value
223
+ value = remaining_bytes[0...length]._to_hex
224
+ # debug 'length', length
225
+ # debug 'value', value
226
226
  [
227
227
  value,
228
228
  remaining_bytes[length..]
@@ -238,7 +238,7 @@ module ScaleRb
238
238
  else
239
239
  raise InvalidBytesError, 'type: Boolean'
240
240
  end
241
- debug 'value', value
241
+ # debug 'value', value
242
242
  [value, bytes[1..]]
243
243
  end
244
244
 
@@ -246,9 +246,9 @@ module ScaleRb
246
246
  length, remaining_bytes = _do_decode_compact(bytes)
247
247
  raise NotEnoughBytesError, 'type: String' if remaining_bytes.length < length
248
248
 
249
- value = remaining_bytes[0...length].to_utf8
250
- debug 'byte length', length
251
- debug 'value', value.inspect
249
+ value = remaining_bytes[0...length]._to_utf8
250
+ # debug 'byte length', length
251
+ # debug 'value', value.inspect
252
252
  [
253
253
  value,
254
254
  remaining_bytes[length..]
@@ -260,8 +260,8 @@ module ScaleRb
260
260
  byte_length = bit_length / 8
261
261
  raise NotEnoughBytesError, "type: #{type}" if bytes.length < byte_length
262
262
 
263
- value = bytes[0...byte_length].flip.to_int(bit_length)
264
- debug 'value', value
263
+ value = bytes[0...byte_length]._flip._to_int(bit_length)
264
+ # debug 'value', value
265
265
  [
266
266
  value,
267
267
  bytes[byte_length..]
@@ -273,8 +273,8 @@ module ScaleRb
273
273
  byte_length = bit_length / 8
274
274
  raise NotEnoughBytesError, "type: #{type_def}" if bytes.length < byte_length
275
275
 
276
- value = bytes[0...byte_length].flip.to_uint
277
- debug 'value', value
276
+ value = bytes[0...byte_length]._flip._to_uint
277
+ # debug 'value', value
278
278
  [
279
279
  value,
280
280
  bytes[byte_length..]
@@ -282,9 +282,8 @@ module ScaleRb
282
282
  end
283
283
 
284
284
  def decode_compact(bytes)
285
- result = _do_decode_compact(bytes)
286
- debug 'value', result[0]
287
- result
285
+ _do_decode_compact(bytes)
286
+ # debug 'value', result[0]
288
287
  end
289
288
 
290
289
  def decode_option(type_def, bytes, registry = {})
@@ -304,7 +303,7 @@ module ScaleRb
304
303
  def decode_vec(type_def, bytes, registry = {})
305
304
  inner_type = parse_vec(type_def)
306
305
  length, remaining_bytes = _do_decode_compact(bytes)
307
- debug 'length', length
306
+ # debug 'length', length
308
307
  _decode_types([inner_type] * length, remaining_bytes, registry)
309
308
  end
310
309
 
@@ -331,7 +330,7 @@ module ScaleRb
331
330
  raise IndexOutOfRangeError, "type: #{type_def}" if index > items.length - 1
332
331
 
333
332
  item = items.to_a[index] # 'name' or [:name, inner_type]
334
- debug 'value', item.inspect
333
+ # debug 'value', item.inspect
335
334
  return [item, bytes[1..]] if item.instance_of?(String)
336
335
 
337
336
  value, remaining_bytes = decode(item[1], bytes[1..], registry)
@@ -353,9 +352,9 @@ module ScaleRb
353
352
  # Encode
354
353
  class << self
355
354
  def encode(type, value, registry = {})
356
- logger.debug '--------------------------------------------------'
357
- debug 'encoding type', type
358
- debug 'value', value
355
+ # logger.debug '--------------------------------------------------'
356
+ # debug 'encoding type', type
357
+ # debug 'value', value
359
358
 
360
359
  if type.instance_of?(String)
361
360
  return encode_bytes(value) if bytes?(type)
@@ -397,16 +396,16 @@ module ScaleRb
397
396
 
398
397
  def encode_compact(value)
399
398
  return [value << 2] if (value >= 0) && (value < 64)
400
- return ((value << 2) + 1).to_bytes.flip if value < 2**14
401
- return ((value << 2) + 2).to_bytes.flip if value < 2**30
399
+ return ((value << 2) + 1)._to_bytes._flip if value < 2**14
400
+ return ((value << 2) + 2)._to_bytes._flip if value < 2**30
402
401
 
403
- bytes = value.to_bytes.flip
402
+ bytes = value._to_bytes._flip
404
403
  [(((bytes.length - 4) << 2) + 3)] + bytes
405
404
  end
406
405
 
407
406
  def encode_uint(type, value)
408
407
  bit_length = type[1..].to_i
409
- value.to_bytes(bit_length).flip
408
+ value._to_bytes(bit_length)._flip
410
409
  end
411
410
 
412
411
  def encode_option(type, value, registry = {})
data/lib/hasher.rb CHANGED
@@ -3,52 +3,54 @@
3
3
  require 'xxhash'
4
4
  require 'blake2b'
5
5
 
6
- module Hasher
7
- class << self
8
- # params:
9
- # hasher: 'Identity' | 'Twox64Concat' | 'Blake2128Concat'
10
- # bytes: u8 array
11
- # return: u8 array
12
- def apply_hasher(hasher, bytes)
13
- function_name = hasher.gsub('_', '').underscore
14
- Hasher.send(function_name, bytes)
6
+ module ScaleRb
7
+ module Hasher
8
+ class << self
9
+ # params:
10
+ # hasher: 'Identity' | 'Twox64Concat' | 'Blake2128Concat'
11
+ # bytes: u8 array
12
+ # return: u8 array
13
+ def apply_hasher(hasher, bytes)
14
+ function_name = hasher.gsub('_', '')._underscore
15
+ Hasher.send(function_name, bytes)
16
+ end
15
17
  end
16
- end
17
18
 
18
- class << self
19
- def identity(bytes)
20
- bytes
21
- end
19
+ class << self
20
+ def identity(bytes)
21
+ bytes
22
+ end
22
23
 
23
- def twox64_concat(bytes)
24
- data = bytes.to_utf8
25
- twox64(data) + bytes
26
- end
24
+ def twox64_concat(bytes)
25
+ data = bytes._to_utf8
26
+ twox64(data) + bytes
27
+ end
27
28
 
28
- def blake2128_concat(bytes)
29
- blake2_128(bytes) + bytes
30
- end
29
+ def blake2128_concat(bytes)
30
+ blake2_128(bytes) + bytes
31
+ end
31
32
 
32
- def twox64(str)
33
- result = XXhash.xxh64 str, 0
34
- result.to_bytes.reverse
35
- end
33
+ def twox64(str)
34
+ result = XXhash.xxh64 str, 0
35
+ result._to_bytes.reverse
36
+ end
36
37
 
37
- def twox128(str)
38
- bytes = []
39
- 2.times do |i|
40
- result = XXhash.xxh64 str, i
41
- bytes += result.to_bytes.reverse
38
+ def twox128(str)
39
+ bytes = []
40
+ 2.times do |i|
41
+ result = XXhash.xxh64 str, i
42
+ bytes += result._to_bytes.reverse
43
+ end
44
+ bytes
42
45
  end
43
- bytes
44
- end
45
46
 
46
- def blake2_128(bytes)
47
- Blake2b.hex(bytes, 16).to_bytes
48
- end
47
+ def blake2_128(bytes)
48
+ Blake2b.hex(bytes, 16)._to_bytes
49
+ end
49
50
 
50
- def blake2_256(bytes)
51
- Blake2b.hex(bytes, 32).to_bytes
51
+ def blake2_256(bytes)
52
+ Blake2b.hex(bytes, 32)._to_bytes
53
+ end
52
54
  end
53
55
  end
54
56
  end