scale.rb 0.2.17 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Cargo.lock +8 -4
  4. data/Cargo.toml +2 -3
  5. data/Dockerfile +4 -1
  6. data/Gemfile.lock +23 -21
  7. data/README.md +44 -1
  8. data/Rakefile +6 -0
  9. data/exe/scale +49 -0
  10. data/lib/helper.rb +19 -4
  11. data/lib/metadata/metadata.rb +27 -17
  12. data/lib/metadata/metadata_v0.rb +24 -20
  13. data/lib/metadata/metadata_v1.rb +13 -9
  14. data/lib/metadata/metadata_v10.rb +2 -2
  15. data/lib/metadata/metadata_v11.rb +2 -2
  16. data/lib/metadata/metadata_v12.rb +9 -8
  17. data/lib/metadata/metadata_v13.rb +161 -0
  18. data/lib/metadata/metadata_v2.rb +2 -2
  19. data/lib/metadata/metadata_v3.rb +2 -2
  20. data/lib/metadata/metadata_v4.rb +21 -11
  21. data/lib/metadata/metadata_v5.rb +21 -11
  22. data/lib/metadata/metadata_v6.rb +9 -9
  23. data/lib/metadata/metadata_v7.rb +26 -15
  24. data/lib/metadata/metadata_v8.rb +9 -9
  25. data/lib/metadata/metadata_v9.rb +2 -2
  26. data/lib/scale.rb +40 -339
  27. data/lib/scale/base.rb +175 -93
  28. data/lib/scale/block.rb +10 -10
  29. data/lib/scale/trie.rb +1 -1
  30. data/lib/scale/types.rb +139 -40
  31. data/lib/scale/version.rb +1 -1
  32. data/lib/scale_bytes.rb +63 -0
  33. data/lib/substrate_client.rb +11 -8
  34. data/lib/type_builder.rb +280 -0
  35. data/lib/type_registry.rb +91 -0
  36. data/lib/type_registry/crab.json +676 -595
  37. data/lib/type_registry/darwinia.json +730 -554
  38. data/lib/type_registry/default.json +3 -2
  39. data/lib/type_registry/pangolin.json +771 -0
  40. data/scale.gemspec +1 -0
  41. data/scripts/mmr_root_to_sign.rb +10 -0
  42. data/src/lib.rs +80 -25
  43. metadata +25 -10
  44. data/lib/type_registry/edgeware.json +0 -124
  45. data/lib/type_registry/joystream.json +0 -49
  46. data/lib/type_registry/kulupu.json +0 -15
  47. data/lib/type_registry/plasm.json +0 -89
  48. data/lib/type_registry/robonomics.json +0 -39
  49. data/lib/type_registry/westend.json +0 -63
  50. data/src/storage_key.rs +0 -41
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b7ae809d469d6fb67c8fdf00ad6debf41b6c5f219d7cdf021f408d3368b7367
4
- data.tar.gz: 19c3ea53bcc3bfaeff46735b135bdf985cc9d79830e90e75e9afa279c48d1af9
3
+ metadata.gz: 861596854598a5ea2a2648cc9fe3b32915eeba97a372f2c49ba1839537cd6741
4
+ data.tar.gz: 222a2e692373bd1523f37927a304c12f2d24d252c428be3b6beb8b4dc52163c8
5
5
  SHA512:
6
- metadata.gz: 58f4cfe9d7430aff3c263be9e420d9779166f92ed42d9dd2e926238d8e5909073ed2241800123bb084ec513bc8fe1502f235392787d84dd81877ae61d2a54509
7
- data.tar.gz: 27421c1d163fc130194cfd44249cca443f440bf37faca104ca5fc9db7884554d8f5d14bd4378ba583ffa4555be91fe99f4fa2430953824a109ed87f5ec18863b
6
+ metadata.gz: 68406b9ce9d33d5bf4513fc825f7e76b5e290f52a6b144893ff9df130e513ff01f20b647e51eab61efef2f15bb4b4be0db0b0a817cba465f268577199731f4d3
7
+ data.tar.gz: d0225db7a736a2909dd8e3967658b9fef543457e2eea479e09af8944161830fbad114782ec8fa0014e6a4df5f8599c3b128dcc16cc00c3518dcd836f1b6dd4ef
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
  /.idea
11
11
  /target
12
12
  .DS_Store
13
+ /scripts/tmp.rb
data/Cargo.lock CHANGED
@@ -1,5 +1,7 @@
1
1
  # This file is automatically @generated by Cargo.
2
2
  # It is not intended for manual editing.
3
+ version = 3
4
+
3
5
  [[package]]
4
6
  name = "Inflector"
5
7
  version = "0.11.4"
@@ -15,6 +17,8 @@ name = "SCALE-testing-interface"
15
17
  version = "0.1.0"
16
18
  dependencies = [
17
19
  "frame-support",
20
+ "hex",
21
+ "libc",
18
22
  "parity-scale-codec",
19
23
  "sp-core",
20
24
  ]
@@ -642,9 +646,9 @@ dependencies = [
642
646
 
643
647
  [[package]]
644
648
  name = "hex"
645
- version = "0.4.2"
649
+ version = "0.4.3"
646
650
  source = "registry+https://github.com/rust-lang/crates.io-index"
647
- checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
651
+ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
648
652
 
649
653
  [[package]]
650
654
  name = "hmac"
@@ -744,9 +748,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
744
748
 
745
749
  [[package]]
746
750
  name = "libc"
747
- version = "0.2.82"
751
+ version = "0.2.94"
748
752
  source = "registry+https://github.com/rust-lang/crates.io-index"
749
- checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
753
+ checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
750
754
 
751
755
  [[package]]
752
756
  name = "libsecp256k1"
data/Cargo.toml CHANGED
@@ -8,11 +8,10 @@ edition = "2018"
8
8
  parity-scale-codec = { version = "1.3.6" }
9
9
  sp-core = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", features = ["full_crypto"]}
10
10
  frame-support = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git" }
11
+ libc = { version = "0.2.94" }
12
+ hex = { version = "0.4.3" }
11
13
 
12
14
  [lib]
13
15
  name = "scale_ffi"
14
16
  crate-type = ["dylib"]
15
17
 
16
- [[bin]]
17
- name = "storage_key"
18
- path = "src/storage_key.rs"
data/Dockerfile CHANGED
@@ -15,7 +15,10 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \
15
15
  export RUSTFLAGS='-C target-feature=-crt-static' && \
16
16
  make
17
17
 
18
- RUN gem install bundler:1.17.3 && \
18
+ ENV RUSTFLAGS='-C target-feature=-crt-static'
19
+ ENV PATH=/root/.cargo/bin:$PATH
20
+
21
+ RUN gem install bundler:2.2.13 && \
19
22
  bundle install && \
20
23
  rake install:local
21
24
 
data/Gemfile.lock CHANGED
@@ -1,11 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- scale.rb (0.2.17)
4
+ scale.rb (0.3.1)
5
5
  base58
6
6
  blake2b_rs (~> 0.1.2)
7
7
  faye-websocket
8
8
  json (~> 2.3.0)
9
+ thor (~> 1.0)
9
10
  xxhash
10
11
 
11
12
  GEM
@@ -15,39 +16,40 @@ GEM
15
16
  blake2b_rs (0.1.2)
16
17
  ffi (= 1.15.0)
17
18
  thermite (~> 0)
18
- coderay (1.1.2)
19
- diff-lcs (1.3)
19
+ coderay (1.1.3)
20
+ diff-lcs (1.4.4)
20
21
  eventmachine (1.2.7)
21
- faye-websocket (0.11.0)
22
+ faye-websocket (0.11.1)
22
23
  eventmachine (>= 0.12.0)
23
24
  websocket-driver (>= 0.5.1)
24
25
  ffi (1.15.0)
25
26
  json (2.3.1)
26
- method_source (0.9.2)
27
+ method_source (1.0.0)
27
28
  minitar (0.9)
28
- pry (0.12.2)
29
- coderay (~> 1.1.0)
30
- method_source (~> 0.9.0)
31
- rake (13.0.1)
32
- rspec (3.9.0)
33
- rspec-core (~> 3.9.0)
34
- rspec-expectations (~> 3.9.0)
35
- rspec-mocks (~> 3.9.0)
36
- rspec-core (3.9.0)
37
- rspec-support (~> 3.9.0)
38
- rspec-expectations (3.9.0)
29
+ pry (0.14.0)
30
+ coderay (~> 1.1)
31
+ method_source (~> 1.0)
32
+ rake (13.0.3)
33
+ rspec (3.10.0)
34
+ rspec-core (~> 3.10.0)
35
+ rspec-expectations (~> 3.10.0)
36
+ rspec-mocks (~> 3.10.0)
37
+ rspec-core (3.10.1)
38
+ rspec-support (~> 3.10.0)
39
+ rspec-expectations (3.10.1)
39
40
  diff-lcs (>= 1.2.0, < 2.0)
40
- rspec-support (~> 3.9.0)
41
- rspec-mocks (3.9.0)
41
+ rspec-support (~> 3.10.0)
42
+ rspec-mocks (3.10.2)
42
43
  diff-lcs (>= 1.2.0, < 2.0)
43
- rspec-support (~> 3.9.0)
44
- rspec-support (3.9.0)
44
+ rspec-support (~> 3.10.0)
45
+ rspec-support (3.10.2)
45
46
  thermite (0.13.0)
46
47
  minitar (~> 0.5)
47
48
  rake (>= 10)
48
49
  tomlrb (~> 1.2)
50
+ thor (1.1.0)
49
51
  tomlrb (1.3.0)
50
- websocket-driver (0.7.3)
52
+ websocket-driver (0.7.5)
51
53
  websocket-extensions (>= 0.1.0)
52
54
  websocket-extensions (0.1.5)
53
55
  xxhash (0.4.0)
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  ![grants_badge](./grants_badge.png)
2
2
 
3
+ **Warning: After v0.2.19, the develop branch will do a structure refactor and big optimization.**
4
+
3
5
  # scale.rb
4
6
 
5
7
  **Ruby SCALE Codec Library**
@@ -19,7 +21,7 @@ Because the feature of ruby 2.6 is used, the ruby version is required to be >= 2
19
21
  Add this line to your application's Gemfile:
20
22
 
21
23
  ```ruby
22
- gem 'scale.rb', '0.2.16'
24
+ gem 'scale.rb', '0.2.19'
23
25
  ```
24
26
 
25
27
  And then execute:
@@ -37,10 +39,22 @@ Or install it yourself as:
37
39
  ```ruby
38
40
  require "scale"
39
41
 
42
+ Scale::TypeRegistry.instance.load # default
43
+ # Scale::TypeRegistry.instance.load spec_name: "pangolin"
44
+ # Scale::TypeRegistry.instance.load spec_name: "kusama"
45
+
46
+ # print hex changes if you set debug to true, default is false
47
+ Scale::Types.debug = true
48
+
40
49
  # decode a compact integer
41
50
  scale_bytes = Scale::Bytes.new("0x1501") # create scale_bytes object from scale encoded hex string
42
51
  o = Scale::Types::Compact.decode(scale_bytes) # use scale type to decode scale_bytes object
43
52
  p o.value # 69
53
+
54
+ #
55
+ type = Scale::Types::get("Vec<U8>")
56
+ o = type.decode(Scale::Bytes.new("0x080001"))
57
+ assert_eq o.value, [Scale::Types::U8.new(0), Scale::Types::U8.new(1)]
44
58
  ```
45
59
 
46
60
  2. encode
@@ -48,8 +62,37 @@ p o.value # 69
48
62
  ```ruby
49
63
  require "scale"
50
64
 
65
+ Scale::TypeRegistry.instance.load
66
+
51
67
  o = Scale::Types::Compact.new(69)
52
68
  p o.encode # "1501"
69
+
70
+ type = Scale::Types::get("Vec<U8>")
71
+ o = type.new([Scale::Types::U8.new(0), Scale::Types::U8.new(1)])
72
+ p o.encode # "080001"
73
+ ```
74
+
75
+ 3. client
76
+ ```ruby
77
+ require "scale"
78
+ client = SubstrateClient.new "wss://rpc.darwinia.network"
79
+
80
+ v = Scale::Types.get("EthereumTransactionIndex")
81
+ .new(
82
+ [
83
+ Scale::Types::H256.new("0x803054c2beacabc36e15c3147bb87d8320a02e9b601be28820a622dedd1c7717"),
84
+ Scale::Types::U64.new(266)
85
+ ]
86
+ )
87
+
88
+ storage = client.get_storage("EthereumBacking", "VerifiedProof", [v])
89
+ puts storage.to_human
90
+
91
+ # get the raw data
92
+ key = client.generate_storage_key("EthereumBacking", "VerifiedProof", [v])[0]
93
+ storage_raw = client.state_getStorageAt(key)
94
+ puts storage_raw
95
+
53
96
  ```
54
97
  Please go to `spec` dir for more examples.
55
98
 
data/Rakefile CHANGED
@@ -1,2 +1,8 @@
1
1
  require 'bundler/gem_tasks'
2
+ require "scale"
2
3
  task default: :spec
4
+
5
+ desc 'Check types of a spec'
6
+ task :check_types do
7
+ TypeRegistry.instance.load spec_name: 'darwinia'
8
+ end
data/exe/scale ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "thor"
4
+ require "scale"
5
+
6
+ class ScaleCli < Thor
7
+ desc "list-types WS_ENDPOINT ", "list all types in metadata"
8
+ def list_types(ws)
9
+ client = SubstrateClient.new ws
10
+ metadata = client.get_metadata.value.to_human.to_json
11
+ metadata = JSON.parse(metadata)
12
+
13
+ types = []
14
+ metadata["metadata"]["modules"].each do |m|
15
+ if m["storage"]
16
+ m["storage"]["items"].each do |storage|
17
+ type = storage["type"]
18
+ if type["Plain"]
19
+ types << type["Plain"].gsub("\n ", "").gsub("\n", "")
20
+ elsif type["Map"]
21
+ types << type["Map"]["key"].gsub("\n", "")
22
+ types << type["Map"]["value"].gsub("\n", "")
23
+ end
24
+ end
25
+ end
26
+
27
+ if m["calls"]
28
+ m["calls"].each do |call|
29
+ call["args"].each do |arg|
30
+ types << arg["type"].gsub("\n", "")
31
+ end
32
+ end
33
+ end
34
+
35
+ if m["events"]
36
+ m["events"].each do |event|
37
+ event["args"].each do |arg|
38
+ types << arg.gsub("\n", "")
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ types.uniq!
45
+ puts types
46
+ end
47
+ end
48
+
49
+ ScaleCli.start(ARGV)
data/lib/helper.rb CHANGED
@@ -18,16 +18,30 @@ class SubstrateClient::Helper
18
18
  return_type = map[:value]
19
19
  # TODO: decode to account id if param is address
20
20
  # params[0] = decode(params[0]) if map[:key] == "AccountId"
21
+
21
22
  type = Scale::Types.get(map[:key])
22
- params[0] = type.new(params[0]).encode
23
+ if params[0].class != type
24
+ raise Scale::StorageInputTypeError.new("The type of first param is not equal to the type from metadata: #{map[:key]} => #{type}")
25
+ end
26
+ params[0] = params[0].encode
23
27
  elsif map = storage_item[:type][:DoubleMap]
24
28
  raise "Storage call of type \"DoubleMapType\" requires 2 parameters" if params.nil? || params.length != 2
25
29
 
26
30
  hasher = map[:hasher]
27
31
  hasher2 = map[:key2Hasher]
28
32
  return_type = map[:value]
29
- params[0] = Scale::Types.get(map[:key1]).new(params[0]).encode
30
- params[1] = Scale::Types.get(map[:key2]).new(params[1]).encode
33
+
34
+ type1 = Scale::Types.get(map[:key1])
35
+ if params[0].class != type1
36
+ raise Scale::StorageInputTypeError.new("The type of 1st param is not equal to the type from metadata: #{map[:key1]} => #{type1.class.name}")
37
+ end
38
+ params[0] = params[0].encode
39
+
40
+ type2 = Scale::Types.get(map[:key2])
41
+ if params[1].class != type2
42
+ raise Scale::StorageInputTypeError.new("The type of 2nd param is not equal to the type from metadata: #{map[:key2]} => #{type2.class.name}")
43
+ end
44
+ params[1] = params[1].encode
31
45
  else
32
46
  raise NotImplementedError
33
47
  end
@@ -41,7 +55,8 @@ class SubstrateClient::Helper
41
55
  hasher2,
42
56
  metadata.value.value[:metadata][:version]
43
57
  )
44
- [storage_key, return_type]
58
+ storage_modifier = storage_item[:modifier]
59
+ [storage_key, return_type, storage_item]
45
60
  end
46
61
 
47
62
  def generate_storage_key(module_name, storage_name, params = nil, hasher = nil, hasher2 = nil, metadata_version = nil)
@@ -1,12 +1,16 @@
1
1
  module Scale
2
2
  module Types
3
3
  class Metadata
4
- include SingleValue
4
+ include Base
5
5
  attr_accessor :version
6
6
  def self.decode(scale_bytes)
7
7
  bytes = scale_bytes.get_next_bytes(4)
8
8
  if bytes.bytes_to_utf8 == "meta"
9
- metadata_version = Scale::Types.type_of("Enum", %w[MetadataV0 MetadataV1 MetadataV2 MetadataV3 MetadataV4 MetadataV5 MetadataV6 MetadataV7 MetadataV8 MetadataV9 MetadataV10 MetadataV11 MetadataV12]).decode(scale_bytes).value
9
+ version_enum = {
10
+ "type" => "enum",
11
+ "value_list" => %w[MetadataV0 MetadataV1 MetadataV2 MetadataV3 MetadataV4 MetadataV5 MetadataV6 MetadataV7 MetadataV8 MetadataV9 MetadataV10 MetadataV11 MetadataV12 MetadataV13]
12
+ }
13
+ metadata_version = Scale::Types.get(version_enum).decode(scale_bytes).value
10
14
  metadata = Metadata.new "Scale::Types::#{metadata_version}".constantize2.decode(scale_bytes)
11
15
  metadata.version = metadata_version[9..].to_i
12
16
  else
@@ -48,7 +52,7 @@ module Scale
48
52
  end
49
53
 
50
54
  class MetadataModule
51
- include SingleValue
55
+ include Base
52
56
  def self.decode(scale_bytes)
53
57
  name = String.decode(scale_bytes).value
54
58
  prefix = String.decode(scale_bytes).value
@@ -60,19 +64,19 @@ module Scale
60
64
 
61
65
  has_storage = Bool.decode(scale_bytes).value
62
66
  if has_storage
63
- storages = Scale::Types.type_of("Vec<MetadataModuleStorage>").decode(scale_bytes).value
67
+ storages = Scale::Types.get("Vec<MetadataModuleStorage>").decode(scale_bytes).value
64
68
  result[:storage] = storages.map(&:value)
65
69
  end
66
70
 
67
71
  has_calls = Bool.decode(scale_bytes).value
68
72
  if has_calls
69
- calls = Scale::Types.type_of("Vec<MetadataModuleCall>").decode(scale_bytes).value
73
+ calls = Scale::Types.get("Vec<MetadataModuleCall>").decode(scale_bytes).value
70
74
  result[:calls] = calls.map(&:value)
71
75
  end
72
76
 
73
77
  has_events = Bool.decode(scale_bytes).value
74
78
  if has_events
75
- events = Scale::Types.type_of("Vec<MetadataModuleEvent>").decode(scale_bytes).value
79
+ events = Scale::Types.get("Vec<MetadataModuleEvent>").decode(scale_bytes).value
76
80
  result[:events] = events.map(&:value)
77
81
  end
78
82
 
@@ -85,11 +89,17 @@ module Scale
85
89
  end
86
90
 
87
91
  class MetadataModuleStorage
88
- include SingleValue
92
+ include Base
89
93
  def self.decode(scale_bytes)
94
+ name = String.decode(scale_bytes).value
95
+ enum = {
96
+ "type" => "enum",
97
+ "value_list" => ["Optional", "Default"]
98
+ }
99
+ modifier = Scale::Types.get(enum).decode(scale_bytes).value
90
100
  result = {
91
- name: String.decode(scale_bytes).value,
92
- modifier: Scale::Types.type_of("Enum", %w[Optional Default]).decode(scale_bytes).value
101
+ name: name,
102
+ modifier: modifier
93
103
  }
94
104
 
95
105
  is_key_value = Bool.decode(scale_bytes).value
@@ -108,25 +118,25 @@ module Scale
108
118
  end
109
119
 
110
120
  result[:fallback] = Hex.decode(scale_bytes).value
111
- result[:documentation] = Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
121
+ result[:documentation] = Scale::Types.get("Vec<String>").decode(scale_bytes).value.map(&:value)
112
122
 
113
123
  MetadataModuleStorage.new(result)
114
124
  end
115
125
  end
116
126
 
117
127
  class MetadataModuleCall
118
- include SingleValue
128
+ include Base
119
129
  def self.decode(scale_bytes)
120
130
  result = {}
121
131
  result[:name] = String.decode(scale_bytes).value
122
- result[:args] = Scale::Types.type_of("Vec<MetadataModuleCallArgument>").decode(scale_bytes).value.map(&:value)
123
- result[:documentation] = Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
132
+ result[:args] = Scale::Types.get("Vec<MetadataModuleCallArgument>").decode(scale_bytes).value.map(&:value)
133
+ result[:documentation] = Scale::Types.get("Vec<String>").decode(scale_bytes).value.map(&:value)
124
134
  MetadataModuleCall.new(result)
125
135
  end
126
136
  end
127
137
 
128
138
  class MetadataModuleCallArgument
129
- include SingleValue
139
+ include Base
130
140
  def self.decode(scale_bytes)
131
141
  result = {}
132
142
  result[:name] = String.decode(scale_bytes).value
@@ -137,12 +147,12 @@ module Scale
137
147
  end
138
148
 
139
149
  class MetadataModuleEvent
140
- include SingleValue
150
+ include Base
141
151
  def self.decode(scale_bytes)
142
152
  result = {}
143
153
  result[:name] = String.decode(scale_bytes).value
144
- result[:args] = Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
145
- result[:documentation] = Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
154
+ result[:args] = Scale::Types.get("Vec<String>").decode(scale_bytes).value.map(&:value)
155
+ result[:documentation] = Scale::Types.get("Vec<String>").decode(scale_bytes).value.map(&:value)
146
156
 
147
157
  MetadataModuleEvent.new(result)
148
158
  end