scale.rb 0.2.17 → 0.3.1

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.
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