scale.rb 0.2.18 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Cargo.lock +8 -4
- data/Cargo.toml +2 -3
- data/Dockerfile +4 -1
- data/Gemfile.lock +3 -3
- data/README.md +20 -4
- data/Rakefile +6 -0
- data/lib/helper.rb +19 -4
- data/lib/metadata/metadata.rb +27 -17
- data/lib/metadata/metadata_v0.rb +24 -20
- data/lib/metadata/metadata_v1.rb +13 -9
- data/lib/metadata/metadata_v10.rb +2 -2
- data/lib/metadata/metadata_v11.rb +2 -2
- data/lib/metadata/metadata_v12.rb +9 -8
- data/lib/metadata/metadata_v13.rb +161 -0
- data/lib/metadata/metadata_v2.rb +2 -2
- data/lib/metadata/metadata_v3.rb +2 -2
- data/lib/metadata/metadata_v4.rb +21 -11
- data/lib/metadata/metadata_v5.rb +21 -11
- data/lib/metadata/metadata_v6.rb +9 -9
- data/lib/metadata/metadata_v7.rb +26 -15
- data/lib/metadata/metadata_v8.rb +9 -9
- data/lib/metadata/metadata_v9.rb +2 -2
- data/lib/scale/base.rb +136 -96
- data/lib/scale/block.rb +10 -10
- data/lib/scale/trie.rb +1 -1
- data/lib/scale/types.rb +91 -40
- data/lib/scale/version.rb +1 -1
- data/lib/scale.rb +38 -377
- data/lib/scale_bytes.rb +63 -0
- data/lib/substrate_client.rb +11 -8
- data/lib/type_builder.rb +280 -0
- data/lib/type_registry/darwinia.json +730 -554
- data/lib/type_registry/default.json +1 -0
- data/lib/type_registry/pangolin.json +571 -132
- data/lib/type_registry.rb +91 -0
- data/scripts/mmr_root_to_sign.rb +10 -0
- data/src/lib.rs +80 -25
- metadata +7 -3
- data/src/storage_key.rs +0 -41
data/lib/scale/block.rb
CHANGED
@@ -2,11 +2,11 @@ module Scale
|
|
2
2
|
module Types
|
3
3
|
|
4
4
|
class Extrinsic
|
5
|
-
include
|
5
|
+
include Base
|
6
6
|
# attr_accessor :address, :signature, :nonce, :era, :extrinsic_hash, :call_index, :params_raw, :params
|
7
7
|
|
8
|
-
def self.generate_hash(
|
9
|
-
|
8
|
+
def self.generate_hash(bytes)
|
9
|
+
Crypto.blake2_256 bytes
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.decode(scale_bytes)
|
@@ -61,10 +61,10 @@ module Scale
|
|
61
61
|
|
62
62
|
if contains_transaction
|
63
63
|
result[:address] = Scale::Types.get("Address").decode(scale_bytes).value
|
64
|
-
result[:signature] =
|
65
|
-
result[:era] =
|
66
|
-
result[:nonce] =
|
67
|
-
result[:tip] =
|
64
|
+
result[:signature] = Scale::Types.get("MultiSignature").decode(scale_bytes).value
|
65
|
+
result[:era] = Scale::Types.get("Era").decode(scale_bytes).value
|
66
|
+
result[:nonce] = Scale::Types.get("Compact").decode(scale_bytes).value
|
67
|
+
result[:tip] = Scale::Types.get("Compact").decode(scale_bytes).value
|
68
68
|
result[:extrinsic_hash] = generate_hash(scale_bytes.bytes)
|
69
69
|
end
|
70
70
|
result[:call_index] = scale_bytes.get_next_bytes(2).bytes_to_hex[2..]
|
@@ -116,7 +116,7 @@ module Scale
|
|
116
116
|
end
|
117
117
|
|
118
118
|
class EventRecords
|
119
|
-
include
|
119
|
+
include Base
|
120
120
|
|
121
121
|
def self.decode(scale_bytes)
|
122
122
|
|
@@ -129,7 +129,7 @@ module Scale
|
|
129
129
|
end
|
130
130
|
|
131
131
|
class EventRecord
|
132
|
-
include
|
132
|
+
include Base
|
133
133
|
|
134
134
|
def self.decode(scale_bytes)
|
135
135
|
metadata = Scale::TypeRegistry.instance.metadata.value
|
@@ -211,7 +211,7 @@ module Scale
|
|
211
211
|
|
212
212
|
class LogDigest
|
213
213
|
include Enum
|
214
|
-
|
214
|
+
inner_types *%w[Other AuthoritiesChange ChangesTrieRoot SealV0 Consensus Seal PreRuntime]
|
215
215
|
end
|
216
216
|
|
217
217
|
end
|
data/lib/scale/trie.rb
CHANGED
data/lib/scale/types.rb
CHANGED
@@ -2,7 +2,7 @@ module Scale
|
|
2
2
|
module Types
|
3
3
|
|
4
4
|
class Bool
|
5
|
-
include
|
5
|
+
include Base
|
6
6
|
BYTES_LENGTH = 1
|
7
7
|
|
8
8
|
def self.decode(scale_bytes)
|
@@ -10,10 +10,10 @@ module Scale
|
|
10
10
|
bytes = scale_bytes.get_next_bytes(self::BYTES_LENGTH)
|
11
11
|
if bytes == [0]
|
12
12
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
13
|
-
|
13
|
+
new(false)
|
14
14
|
elsif bytes == [1]
|
15
15
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
16
|
-
|
16
|
+
new(true)
|
17
17
|
else
|
18
18
|
raise "Bad data"
|
19
19
|
end
|
@@ -24,6 +24,35 @@ module Scale
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
class OptionBool
|
28
|
+
include Base
|
29
|
+
def self.decode(scale_bytes)
|
30
|
+
byte = scale_bytes.get_next_bytes(1)[0]
|
31
|
+
value = if byte == 0x00
|
32
|
+
nil
|
33
|
+
elsif byte == 0x01
|
34
|
+
true
|
35
|
+
elsif byte == 0x02
|
36
|
+
false
|
37
|
+
else
|
38
|
+
raise BadDataError.new("Bad scale data for OptionBool #{byte.to_s(16)}")
|
39
|
+
end
|
40
|
+
new(value)
|
41
|
+
end
|
42
|
+
|
43
|
+
def encode
|
44
|
+
if value.nil?
|
45
|
+
"00"
|
46
|
+
elsif value === true
|
47
|
+
"01"
|
48
|
+
elsif value === false
|
49
|
+
"02"
|
50
|
+
else
|
51
|
+
raise WrongValueError.new("OptionBool can not have value other than `nil`, `true`, `false`")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
27
56
|
class U8
|
28
57
|
include FixedWidthUInt
|
29
58
|
BYTE_LENGTH = 1
|
@@ -54,6 +83,11 @@ module Scale
|
|
54
83
|
BYTE_LENGTH = 32
|
55
84
|
end
|
56
85
|
|
86
|
+
class U512
|
87
|
+
include FixedWidthUInt
|
88
|
+
BYTE_LENGTH = 64
|
89
|
+
end
|
90
|
+
|
57
91
|
class I8
|
58
92
|
include FixedWidthInt
|
59
93
|
BYTE_LENGTH = 1
|
@@ -80,7 +114,7 @@ module Scale
|
|
80
114
|
end
|
81
115
|
|
82
116
|
class Compact
|
83
|
-
include
|
117
|
+
include Base
|
84
118
|
|
85
119
|
def self.decode(scale_bytes)
|
86
120
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
@@ -118,7 +152,7 @@ module Scale
|
|
118
152
|
end
|
119
153
|
|
120
154
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
121
|
-
|
155
|
+
new(value)
|
122
156
|
end
|
123
157
|
|
124
158
|
def encode
|
@@ -143,7 +177,7 @@ module Scale
|
|
143
177
|
end
|
144
178
|
|
145
179
|
class Bytes
|
146
|
-
include
|
180
|
+
include Base
|
147
181
|
|
148
182
|
def self.decode(scale_bytes)
|
149
183
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
@@ -153,12 +187,13 @@ module Scale
|
|
153
187
|
# [67, 97, 102, 195, 169].pack('C*').force_encoding('utf-8')
|
154
188
|
# => "Café"
|
155
189
|
str = bytes.pack("C*").force_encoding("utf-8")
|
156
|
-
|
190
|
+
# TODO: ?
|
191
|
+
if (not str.include?("\u0000")) && str.valid_encoding?
|
157
192
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
158
|
-
|
193
|
+
new str
|
159
194
|
else
|
160
195
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
161
|
-
|
196
|
+
new bytes.bytes_to_hex
|
162
197
|
end
|
163
198
|
end
|
164
199
|
|
@@ -176,35 +211,40 @@ module Scale
|
|
176
211
|
end
|
177
212
|
|
178
213
|
class Hex
|
179
|
-
include
|
214
|
+
include Base
|
180
215
|
|
181
216
|
def self.decode(scale_bytes)
|
182
217
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
183
218
|
length = Scale::Types::Compact.decode(scale_bytes).value
|
184
219
|
hex_string = scale_bytes.get_next_bytes(length).bytes_to_hex
|
185
220
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
186
|
-
|
221
|
+
new(hex_string)
|
222
|
+
end
|
223
|
+
|
224
|
+
def encode
|
225
|
+
length = Compact.new((value.length - 2)/2).encode
|
226
|
+
"#{length}#{value[2..]}"
|
187
227
|
end
|
188
228
|
end
|
189
229
|
|
190
230
|
class String
|
191
|
-
include
|
231
|
+
include Base
|
192
232
|
def self.decode(scale_bytes)
|
193
233
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
194
234
|
length = Scale::Types::Compact.decode(scale_bytes).value
|
195
235
|
bytes = scale_bytes.get_next_bytes(length)
|
196
236
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
197
|
-
|
237
|
+
new bytes.pack("C*").force_encoding("utf-8")
|
198
238
|
end
|
199
239
|
end
|
200
240
|
|
201
241
|
class H160
|
202
|
-
include
|
242
|
+
include Base
|
203
243
|
def self.decode(scale_bytes)
|
204
244
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
205
245
|
bytes = scale_bytes.get_next_bytes(20)
|
206
246
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
207
|
-
|
247
|
+
new(bytes.bytes_to_hex)
|
208
248
|
end
|
209
249
|
|
210
250
|
def encode
|
@@ -214,12 +254,12 @@ module Scale
|
|
214
254
|
end
|
215
255
|
|
216
256
|
class H256
|
217
|
-
include
|
257
|
+
include Base
|
218
258
|
def self.decode(scale_bytes)
|
219
259
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
220
260
|
bytes = scale_bytes.get_next_bytes(32)
|
221
261
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
222
|
-
|
262
|
+
new(bytes.bytes_to_hex)
|
223
263
|
end
|
224
264
|
|
225
265
|
def encode
|
@@ -229,12 +269,12 @@ module Scale
|
|
229
269
|
end
|
230
270
|
|
231
271
|
class H512
|
232
|
-
include
|
272
|
+
include Base
|
233
273
|
def self.decode(scale_bytes)
|
234
274
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
235
275
|
bytes = scale_bytes.get_next_bytes(64)
|
236
276
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
237
|
-
|
277
|
+
new(bytes.bytes_to_hex)
|
238
278
|
end
|
239
279
|
|
240
280
|
def encode
|
@@ -244,7 +284,7 @@ module Scale
|
|
244
284
|
end
|
245
285
|
|
246
286
|
class GenericAddress
|
247
|
-
include
|
287
|
+
include Base
|
248
288
|
|
249
289
|
# https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)
|
250
290
|
# base58encode ( concat ( <address-type>, <address>, <checksum> ) )
|
@@ -260,7 +300,7 @@ module Scale
|
|
260
300
|
account_length = [account_length].bytes_to_hex
|
261
301
|
|
262
302
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
263
|
-
|
303
|
+
new({
|
264
304
|
account_id: account_id,
|
265
305
|
account_length: account_length
|
266
306
|
})
|
@@ -279,7 +319,7 @@ module Scale
|
|
279
319
|
account_length = [account_length].bytes_to_hex
|
280
320
|
|
281
321
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
282
|
-
|
322
|
+
new({
|
283
323
|
account_index: account_index,
|
284
324
|
account_length: account_length
|
285
325
|
})
|
@@ -302,7 +342,7 @@ module Scale
|
|
302
342
|
class AccountIdAddress < GenericAddress
|
303
343
|
def self.decode(scale_bytes)
|
304
344
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
305
|
-
result =
|
345
|
+
result = new({
|
306
346
|
account_id: AccountId.decode(scale_bytes).value,
|
307
347
|
account_length: "0xff"
|
308
348
|
})
|
@@ -316,6 +356,17 @@ module Scale
|
|
316
356
|
end
|
317
357
|
end
|
318
358
|
|
359
|
+
class GenericMultiAddress
|
360
|
+
include Enum
|
361
|
+
items(
|
362
|
+
Id: "AccountId",
|
363
|
+
Index: "Compact",
|
364
|
+
Raw: "Hex",
|
365
|
+
Address32: "H256",
|
366
|
+
Address20: "H160"
|
367
|
+
)
|
368
|
+
end
|
369
|
+
|
319
370
|
class AccountId < H256; end
|
320
371
|
|
321
372
|
class Balance < U128; end
|
@@ -327,14 +378,14 @@ module Scale
|
|
327
378
|
class AccountIndex < U32; end
|
328
379
|
|
329
380
|
class Era
|
330
|
-
include
|
381
|
+
include Base
|
331
382
|
def self.decode(scale_bytes)
|
332
383
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
333
384
|
byte = scale_bytes.get_next_bytes(1).bytes_to_hex
|
334
385
|
result = if byte == "0x00"
|
335
|
-
|
386
|
+
new byte
|
336
387
|
else
|
337
|
-
|
388
|
+
new byte + scale_bytes.get_next_bytes(1).bytes_to_hex()[2..]
|
338
389
|
end
|
339
390
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
340
391
|
result
|
@@ -346,7 +397,7 @@ module Scale
|
|
346
397
|
class Moment < U64; end
|
347
398
|
|
348
399
|
class CompactMoment
|
349
|
-
include
|
400
|
+
include Base
|
350
401
|
def self.decode(scale_bytes)
|
351
402
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
352
403
|
value = Compact.decode(scale_bytes).value
|
@@ -355,7 +406,7 @@ module Scale
|
|
355
406
|
end
|
356
407
|
|
357
408
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
358
|
-
|
409
|
+
new Time.at(value).strftime("%F %T")
|
359
410
|
end
|
360
411
|
end
|
361
412
|
|
@@ -459,9 +510,9 @@ module Scale
|
|
459
510
|
end
|
460
511
|
|
461
512
|
class Null
|
462
|
-
include
|
513
|
+
include Base
|
463
514
|
def self.decode(scale_bytes)
|
464
|
-
|
515
|
+
new nil
|
465
516
|
end
|
466
517
|
|
467
518
|
def encode
|
@@ -652,20 +703,20 @@ module Scale
|
|
652
703
|
include Struct
|
653
704
|
items(
|
654
705
|
id: "VecU8Length8",
|
655
|
-
amount: "Balance",
|
706
|
+
amount: "Scale::Types::Balance",
|
656
707
|
until: "U32",
|
657
|
-
reasons: "WithdrawReasons"
|
708
|
+
reasons: "Scale::Types::WithdrawReasons"
|
658
709
|
)
|
659
710
|
end
|
660
711
|
|
661
712
|
class EthereumAddress
|
662
|
-
include
|
713
|
+
include Base
|
663
714
|
|
664
715
|
def self.decode(scale_bytes)
|
665
716
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
666
717
|
bytes = scale_bytes.get_next_bytes(20)
|
667
718
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
668
|
-
|
719
|
+
new(bytes.bytes_to_hex)
|
669
720
|
end
|
670
721
|
|
671
722
|
def encode
|
@@ -678,12 +729,12 @@ module Scale
|
|
678
729
|
end
|
679
730
|
|
680
731
|
class EcdsaSignature
|
681
|
-
include
|
732
|
+
include Base
|
682
733
|
|
683
734
|
def self.decode(scale_bytes)
|
684
735
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
685
736
|
bytes = scale_bytes.get_next_bytes(65)
|
686
|
-
|
737
|
+
new(bytes.bytes_to_hex)
|
687
738
|
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
688
739
|
end
|
689
740
|
|
@@ -790,7 +841,7 @@ module Scale
|
|
790
841
|
end
|
791
842
|
|
792
843
|
class VoteOutcome
|
793
|
-
include
|
844
|
+
include Base
|
794
845
|
def self.decode(scale_bytes)
|
795
846
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
796
847
|
result = new(scale_bytes.get_next_bytes(32))
|
@@ -834,7 +885,7 @@ module Scale
|
|
834
885
|
end
|
835
886
|
|
836
887
|
class BoxProposal
|
837
|
-
include
|
888
|
+
include Base
|
838
889
|
|
839
890
|
def self.decode(scale_bytes, metadata, chain_spec)
|
840
891
|
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
@@ -872,7 +923,7 @@ module Scale
|
|
872
923
|
end
|
873
924
|
|
874
925
|
class VecH512Length2
|
875
|
-
include
|
926
|
+
include Base
|
876
927
|
|
877
928
|
def self.decode(scale_bytes)
|
878
929
|
end
|
@@ -885,7 +936,7 @@ module Scale
|
|
885
936
|
end
|
886
937
|
|
887
938
|
class GenericBlock
|
888
|
-
include
|
939
|
+
include Base
|
889
940
|
|
890
941
|
def self.decode(scale_bytes)
|
891
942
|
end
|
data/lib/scale/version.rb
CHANGED
data/lib/scale.rb
CHANGED
@@ -5,6 +5,11 @@ require "common"
|
|
5
5
|
require "json"
|
6
6
|
require "singleton"
|
7
7
|
|
8
|
+
require "scale_bytes"
|
9
|
+
|
10
|
+
require "type_registry"
|
11
|
+
require "type_builder"
|
12
|
+
|
8
13
|
require "scale/base"
|
9
14
|
require "scale/types"
|
10
15
|
require "scale/block"
|
@@ -24,399 +29,36 @@ require "metadata/metadata_v9"
|
|
24
29
|
require "metadata/metadata_v10"
|
25
30
|
require "metadata/metadata_v11"
|
26
31
|
require "metadata/metadata_v12"
|
32
|
+
require "metadata/metadata_v13"
|
27
33
|
|
28
34
|
require "substrate_client"
|
29
35
|
require "logger"
|
30
36
|
require "helper"
|
31
37
|
|
32
|
-
class String
|
33
|
-
def upcase_first
|
34
|
-
self.sub(/\S/, &:upcase)
|
35
|
-
end
|
36
|
-
|
37
|
-
def camelize2
|
38
|
-
self.split('_').collect(&:upcase_first).join
|
39
|
-
end
|
40
|
-
|
41
|
-
def underscore2
|
42
|
-
self.gsub(/::/, '/').
|
43
|
-
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
44
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
45
|
-
tr("-", "_").
|
46
|
-
downcase
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
38
|
module Scale
|
51
|
-
class
|
52
|
-
|
53
|
-
class
|
54
|
-
|
55
|
-
|
56
|
-
# init by load, and will not change
|
57
|
-
attr_reader :spec_name, :types
|
58
|
-
attr_reader :versioning, :custom_types # optional
|
59
|
-
|
60
|
-
# will change by different spec version
|
61
|
-
attr_accessor :spec_version # optional
|
62
|
-
attr_accessor :metadata
|
63
|
-
|
64
|
-
def load(spec_name: nil, custom_types: nil)
|
65
|
-
@spec_name = nil
|
66
|
-
@types = nil
|
67
|
-
@versioning = nil
|
68
|
-
@custom_types = nil
|
69
|
-
|
70
|
-
default_types, _, _ = load_chain_spec_types("default")
|
71
|
-
|
72
|
-
if spec_name
|
73
|
-
begin
|
74
|
-
@spec_name = spec_name
|
75
|
-
spec_types, @versioning, @spec_version = load_chain_spec_types(spec_name)
|
76
|
-
@types = default_types.merge(spec_types)
|
77
|
-
rescue => ex
|
78
|
-
puts "There is no types json file named #{spec_name}"
|
79
|
-
@types = default_types
|
80
|
-
end
|
81
|
-
else
|
82
|
-
@spec_name = "default"
|
83
|
-
@types = default_types
|
84
|
-
end
|
85
|
-
|
86
|
-
self.custom_types = custom_types
|
87
|
-
true
|
88
|
-
end
|
89
|
-
|
90
|
-
def get(type_name)
|
91
|
-
raise "Types not loaded" if @types.nil?
|
92
|
-
|
93
|
-
all_types = {}.merge(@types)
|
94
|
-
|
95
|
-
if @spec_version && @versioning
|
96
|
-
@versioning.each do |item|
|
97
|
-
if @spec_version >= item["runtime_range"][0] &&
|
98
|
-
( item["runtime_range"][1].nil? || @spec_version <= item["runtime_range"][1] )
|
99
|
-
all_types.merge!(item["types"])
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
all_types.merge!(@custom_types) if @custom_types
|
105
|
-
|
106
|
-
type = type_traverse(type_name, all_types)
|
107
|
-
|
108
|
-
Scale::Types.constantize(type)
|
109
|
-
end
|
110
|
-
|
111
|
-
def custom_types=(custom_types)
|
112
|
-
@custom_types = custom_types.stringify_keys if (not custom_types.nil?) && custom_types.class.name == "Hash"
|
113
|
-
end
|
114
|
-
|
115
|
-
private
|
116
|
-
|
117
|
-
def load_chain_spec_types(spec_name)
|
118
|
-
file = File.join File.expand_path("../..", __FILE__), "lib", "type_registry", "#{spec_name}.json"
|
119
|
-
json_string = File.open(file).read
|
120
|
-
json = JSON.parse(json_string)
|
121
|
-
|
122
|
-
runtime_id = json["runtime_id"]
|
123
|
-
|
124
|
-
[json["types"], json["versioning"], runtime_id]
|
125
|
-
end
|
126
|
-
|
127
|
-
def type_traverse(type, types)
|
128
|
-
type = rename(type) if type.class == ::String
|
129
|
-
if types.has_key?(type) && types[type] != type
|
130
|
-
type_traverse(types[type], types)
|
131
|
-
else
|
132
|
-
type
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
# TODO: == implement
|
138
|
-
|
139
|
-
class Bytes
|
140
|
-
attr_reader :data, :bytes
|
141
|
-
attr_reader :offset
|
142
|
-
|
143
|
-
def initialize(data)
|
144
|
-
if (data.class == Array) && data.is_byte_array?
|
145
|
-
@bytes = data
|
146
|
-
elsif (data.class == String) && data.start_with?("0x") && (data.length % 2 == 0)
|
147
|
-
arr = data[2..].scan(/../).map(&:hex)
|
148
|
-
@bytes = arr
|
149
|
-
else
|
150
|
-
raise "Provided data is not valid"
|
151
|
-
end
|
152
|
-
|
153
|
-
@data = data
|
154
|
-
@offset = 0
|
155
|
-
end
|
156
|
-
|
157
|
-
def reset_offset
|
158
|
-
@offset = 0
|
159
|
-
end
|
160
|
-
|
161
|
-
def get_next_bytes(length)
|
162
|
-
result = @bytes[@offset...@offset + length]
|
163
|
-
if result.length < length
|
164
|
-
str = @data[(2 + @offset * 2)..]
|
165
|
-
str = str.length > 40 ? (str[0...40]).to_s + "..." : str
|
166
|
-
raise "No enough data: #{str}, expect length: #{length}, but #{result.length}"
|
167
|
-
end
|
168
|
-
@offset += length
|
169
|
-
result
|
170
|
-
rescue RangeError => ex
|
171
|
-
puts "length: #{length}"
|
172
|
-
puts ex.message
|
173
|
-
puts ex.backtrace
|
174
|
-
end
|
175
|
-
|
176
|
-
def get_remaining_bytes
|
177
|
-
@bytes[offset..]
|
178
|
-
end
|
179
|
-
|
180
|
-
def to_hex_string
|
181
|
-
@bytes.bytes_to_hex
|
182
|
-
end
|
183
|
-
|
184
|
-
def to_bin_string
|
185
|
-
@bytes.bytes_to_bin
|
186
|
-
end
|
187
|
-
|
188
|
-
def to_ascii
|
189
|
-
@bytes[0...offset].pack("C*") + "<================================>" + @bytes[offset..].pack("C*")
|
190
|
-
end
|
191
|
-
|
192
|
-
def ==(other)
|
193
|
-
bytes == other.bytes && offset == other.offset
|
194
|
-
end
|
195
|
-
|
196
|
-
def to_s
|
197
|
-
green(@bytes[0...offset].bytes_to_hex) + yellow(@bytes[offset..].bytes_to_hex[2..])
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
class TypesLoader
|
202
|
-
def self.load(filename)
|
203
|
-
path = File.join File.dirname(__FILE__), "types", filename
|
204
|
-
content = File.open(path).read
|
205
|
-
result = JSON.parse content
|
206
|
-
|
207
|
-
types = result["default"]
|
208
|
-
types.each do |name, body|
|
209
|
-
if body.class == String
|
210
|
-
target_type = "Scale::Types::#{body}"
|
211
|
-
klass = Class.new(target_type.constantize2) do
|
212
|
-
end
|
213
|
-
elsif body.class == Hash
|
214
|
-
if body["type"] == "struct"
|
215
|
-
struct_params = {}
|
216
|
-
body["type_mapping"].each do |mapping|
|
217
|
-
struct_params[mapping[0].to_sym] = mapping[1]
|
218
|
-
end
|
219
|
-
klass = Class.new do
|
220
|
-
end
|
221
|
-
klass.send(:include, Scale::Types::Struct)
|
222
|
-
klass.send(:items, struct_params)
|
223
|
-
Scale::Types.const_set name, klass
|
224
|
-
elsif body["type"] = "enum"
|
225
|
-
klass = Class.new do
|
226
|
-
end
|
227
|
-
klass.send(:include, Scale::Types::Enum)
|
228
|
-
if body["type_mapping"]
|
229
|
-
struct_params = {}
|
230
|
-
body["type_mapping"].each do |mapping|
|
231
|
-
struct_params[mapping[0].to_sym] = mapping[1]
|
232
|
-
end
|
233
|
-
klass.send(:items, struct_params)
|
234
|
-
else
|
235
|
-
klass.send(:values, body["value_list"])
|
236
|
-
end
|
237
|
-
Scale::Types.const_set name, klass
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
39
|
+
class ScaleError < StandardError; end
|
40
|
+
class TypeBuildError < ScaleError; end
|
41
|
+
class BadDataError < ScaleError; end
|
42
|
+
class TypeRegistryNotLoadYet < ScaleError; end
|
43
|
+
class StorageInputTypeError < ScaleError; end
|
243
44
|
|
244
45
|
module Types
|
245
46
|
class << self
|
246
|
-
attr_accessor :debug
|
247
|
-
end
|
248
|
-
|
249
|
-
def self.list
|
250
|
-
TypeRegistry.instance.types
|
251
|
-
end
|
252
|
-
|
253
|
-
def self.get(type_name)
|
254
|
-
type = TypeRegistry.instance.get(type_name)
|
255
|
-
raise "Type '#{type_name}' not exist" if type.nil?
|
256
|
-
type
|
257
|
-
end
|
258
|
-
|
259
|
-
def self.constantize(type)
|
260
|
-
if type.class == ::String
|
261
|
-
type_of(type.strip)
|
262
|
-
else
|
263
|
-
if type["type"] == "enum" && type.has_key?("type_mapping")
|
264
|
-
type_of("Enum", type["type_mapping"].to_h)
|
265
|
-
elsif type["type"] == "enum" && type.has_key?("value_list")
|
266
|
-
type_of("Enum", type["value_list"])
|
267
|
-
elsif type["type"] == "struct"
|
268
|
-
type_of("Struct", type["type_mapping"].to_h)
|
269
|
-
elsif type["type"] == "set"
|
270
|
-
type_of("Set", type["value_list"])
|
271
|
-
end
|
272
|
-
end
|
47
|
+
attr_accessor :debug, :logger
|
273
48
|
end
|
274
49
|
|
275
|
-
def self.
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
if type_str == "Vec"
|
282
|
-
name = "#{type_str}<#{inner_type_str.camelize2}>"
|
283
|
-
name = fix(name)
|
284
|
-
|
285
|
-
if !Scale::Types.const_defined?(name)
|
286
|
-
klass = Class.new do
|
287
|
-
include Scale::Types::Vec
|
288
|
-
inner_type inner_type_str
|
289
|
-
end
|
290
|
-
Scale::Types.const_set name, klass
|
291
|
-
else
|
292
|
-
Scale::Types.const_get name
|
293
|
-
end
|
294
|
-
elsif type_str == "Option"
|
295
|
-
name = "#{type_str}<#{inner_type_str.camelize2}>"
|
296
|
-
name = fix(name)
|
297
|
-
|
298
|
-
if !Scale::Types.const_defined?(name)
|
299
|
-
klass = Class.new do
|
300
|
-
include Scale::Types::Option
|
301
|
-
inner_type inner_type_str
|
302
|
-
end
|
303
|
-
Scale::Types.const_set name, klass
|
304
|
-
else
|
305
|
-
Scale::Types.const_get name
|
306
|
-
end
|
307
|
-
else
|
308
|
-
raise "#{type_str} not support inner type: #{type_string}"
|
309
|
-
end
|
310
|
-
elsif type_string.start_with?("(") && type_string.end_with?(")") # tuple
|
311
|
-
# TODO: add nested tuple support
|
312
|
-
types_with_inner_type = type_string[1...-1].scan(/([A-Za-z]+<[^>]*>)/).first
|
313
|
-
|
314
|
-
types_with_inner_type&.each do |type_str|
|
315
|
-
new_type_str = type_str.tr(",", ";")
|
316
|
-
type_string = type_string.gsub(type_str, new_type_str)
|
317
|
-
end
|
318
|
-
|
319
|
-
type_strs = type_string[1...-1].split(",").map do |type_str|
|
320
|
-
type_str.strip.tr(";", ",")
|
321
|
-
end
|
322
|
-
|
323
|
-
name = "TupleOf#{type_strs.map(&:camelize2).join("")}"
|
324
|
-
name = fix(name)
|
325
|
-
if !Scale::Types.const_defined?(name)
|
326
|
-
klass = Class.new do
|
327
|
-
include Scale::Types::Tuple
|
328
|
-
inner_types *type_strs
|
329
|
-
end
|
330
|
-
Scale::Types.const_set name, klass
|
331
|
-
else
|
332
|
-
Scale::Types.const_get name
|
333
|
-
end
|
334
|
-
else
|
335
|
-
if type_string == "Enum"
|
336
|
-
# TODO: combine values to items
|
337
|
-
klass = Class.new do
|
338
|
-
include Scale::Types::Enum
|
339
|
-
if values.class == ::Hash
|
340
|
-
items values
|
341
|
-
else
|
342
|
-
values(*values)
|
343
|
-
end
|
344
|
-
end
|
345
|
-
name = values.class == ::Hash ? values.values.map(&:camelize2).join("_") : values.map(&:camelize2).join("_")
|
346
|
-
name = "Enum_Of_#{name}_#{klass.object_id}"
|
347
|
-
Scale::Types.const_set fix(name), klass
|
348
|
-
elsif type_string == "Struct"
|
349
|
-
klass = Class.new do
|
350
|
-
include Scale::Types::Struct
|
351
|
-
items values
|
352
|
-
end
|
353
|
-
name = "Struct_Of_#{values.values.map(&:camelize2).join("_")}_#{klass.object_id}"
|
354
|
-
Scale::Types.const_set fix(name), klass
|
355
|
-
elsif type_string == "Set"
|
356
|
-
klass = Class.new do
|
357
|
-
include Scale::Types::Set
|
358
|
-
items values, 1
|
359
|
-
end
|
360
|
-
name = "Set_Of_#{values.keys.map(&:camelize2).join("_")}_#{klass.object_id}"
|
361
|
-
Scale::Types.const_set fix(name), klass
|
362
|
-
else
|
363
|
-
type_name = (type_string.start_with?("Scale::Types::") ? type_string : "Scale::Types::#{type_string}")
|
364
|
-
begin
|
365
|
-
type_name.constantize2
|
366
|
-
rescue NameError => e
|
367
|
-
puts "#{type_string} is not defined"
|
368
|
-
end
|
50
|
+
def self.check_types
|
51
|
+
TypeRegistry.instance.all_types.keys.each do |key|
|
52
|
+
begin
|
53
|
+
type = self.get(key)
|
54
|
+
rescue => ex
|
55
|
+
puts "[[ERROR]] #{key}: #{ex}"
|
369
56
|
end
|
370
57
|
end
|
58
|
+
true
|
371
59
|
end
|
372
|
-
end
|
373
|
-
|
374
|
-
end
|
375
|
-
|
376
|
-
# def fix(name)
|
377
|
-
# name
|
378
|
-
# .gsub("<", "˂").gsub(">", "˃")
|
379
|
-
# .gsub("(", "⁽").gsub(")", "⁾")
|
380
|
-
# .gsub(" ", "").gsub(",", "‚")
|
381
|
-
# .gsub(":", "։")
|
382
|
-
# end
|
383
|
-
|
384
|
-
def fix(name)
|
385
|
-
name
|
386
|
-
.gsub("<", "").gsub(">", "")
|
387
|
-
.gsub("(", "").gsub(")", "")
|
388
|
-
.gsub(" ", "").gsub(",", "")
|
389
|
-
.gsub(":", "")
|
390
|
-
end
|
391
60
|
|
392
|
-
def rename(type)
|
393
|
-
type = type.gsub("T::", "")
|
394
|
-
.gsub("<T>", "")
|
395
|
-
.gsub("<T as Trait>::", "")
|
396
|
-
.delete("\n")
|
397
|
-
.gsub("EventRecord<Event, Hash>", "EventRecord")
|
398
|
-
.gsub(/(u)(\d+)/, 'U\2')
|
399
|
-
return "Bool" if type == "bool"
|
400
|
-
return "Null" if type == "()"
|
401
|
-
return "String" if type == "Vec<u8>"
|
402
|
-
return "Compact" if type == "Compact<u32>" || type == "Compact<U32>"
|
403
|
-
return "Address" if type == "<Lookup as StaticLookup>::Source"
|
404
|
-
return "Vec<Address>" if type == "Vec<<Lookup as StaticLookup>::Source>"
|
405
|
-
return "Compact" if type == "<Balance as HasCompact>::Type"
|
406
|
-
return "Compact" if type == "<BlockNumber as HasCompact>::Type"
|
407
|
-
return "Compact" if type == "Compact<Balance>"
|
408
|
-
return "Compact" if type == "Compact<BlockNumber>"
|
409
|
-
return "CompactMoment" if type == "<Moment as HasCompact>::Type"
|
410
|
-
return "CompactMoment" if type == "Compact<Moment>"
|
411
|
-
return "InherentOfflineReport" if type == "<InherentOfflineReport as InherentOfflineReport>::Inherent"
|
412
|
-
return "AccountData" if type == "AccountData<Balance>"
|
413
|
-
|
414
|
-
if type =~ /\[U\d+; \d+\]/
|
415
|
-
byte_length = type.scan(/\[U\d+; (\d+)\]/).first.first.to_i
|
416
|
-
return "VecU8Length#{byte_length}"
|
417
61
|
end
|
418
|
-
|
419
|
-
type
|
420
62
|
end
|
421
63
|
|
422
64
|
def green(text)
|
@@ -427,6 +69,24 @@ def yellow(text)
|
|
427
69
|
"\033[33m#{text}\033[0m"
|
428
70
|
end
|
429
71
|
|
72
|
+
class String
|
73
|
+
def upcase_first
|
74
|
+
self.sub(/\S/, &:upcase)
|
75
|
+
end
|
76
|
+
|
77
|
+
def camelize2
|
78
|
+
self.split('_').collect(&:upcase_first).join
|
79
|
+
end
|
80
|
+
|
81
|
+
def underscore2
|
82
|
+
self.gsub(/::/, '/').
|
83
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
84
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
85
|
+
tr("-", "_").
|
86
|
+
downcase
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
430
90
|
# https://www.ruby-forum.com/t/question-about-hex-signed-int/125510/4
|
431
91
|
# machine bit length:
|
432
92
|
# machine_byte_length = ['foo'].pack('p').size
|
@@ -466,3 +126,4 @@ class ::Hash
|
|
466
126
|
end
|
467
127
|
|
468
128
|
Scale::Types.debug = false
|
129
|
+
Scale::Types.logger = Logger.new(STDOUT)
|