scale.rb 0.2.14 → 0.2.19

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.
data/Cargo.toml CHANGED
@@ -2,10 +2,17 @@
2
2
  name = "SCALE-testing-interface"
3
3
  version = "0.1.0"
4
4
  authors = ["Robert Hambrock <robert@web3.foundation>"]
5
+ edition = "2018"
5
6
 
6
7
  [dependencies]
7
- parity-scale-codec = { version = "1.2.0" }
8
+ parity-scale-codec = { version = "1.3.6" }
9
+ sp-core = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", features = ["full_crypto"]}
10
+ frame-support = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git" }
8
11
 
9
12
  [lib]
10
13
  name = "scale_ffi"
11
- crate-type = ["dylib"]
14
+ crate-type = ["dylib"]
15
+
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,70 +1,69 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- scale.rb (0.2.14)
5
- activesupport (>= 4.0.0)
4
+ scale.rb (0.2.19)
5
+ base58
6
+ blake2b_rs (~> 0.1.2)
7
+ faye-websocket
6
8
  json (~> 2.3.0)
7
- substrate_common.rb (~> 0.1.9)
8
- thor (~> 0.19.0)
9
+ thor (~> 1.0)
10
+ xxhash
9
11
 
10
12
  GEM
11
13
  remote: https://rubygems.org/
12
14
  specs:
13
- activesupport (6.0.3.4)
14
- concurrent-ruby (~> 1.0, >= 1.0.2)
15
- i18n (>= 0.7, < 2)
16
- minitest (~> 5.1)
17
- tzinfo (~> 1.1)
18
- zeitwerk (~> 2.2, >= 2.2.2)
19
15
  base58 (0.2.3)
20
- blake2b (0.10.0)
21
- coderay (1.1.2)
22
- concurrent-ruby (1.1.7)
23
- diff-lcs (1.3)
24
- ffi (1.12.2)
25
- i18n (1.8.5)
26
- concurrent-ruby (~> 1.0)
16
+ blake2b_rs (0.1.2)
17
+ ffi (= 1.15.0)
18
+ thermite (~> 0)
19
+ coderay (1.1.3)
20
+ diff-lcs (1.4.4)
21
+ eventmachine (1.2.7)
22
+ faye-websocket (0.11.0)
23
+ eventmachine (>= 0.12.0)
24
+ websocket-driver (>= 0.5.1)
25
+ ffi (1.15.0)
27
26
  json (2.3.1)
28
- method_source (0.9.2)
29
- minitest (5.14.2)
30
- pry (0.12.2)
31
- coderay (~> 1.1.0)
32
- method_source (~> 0.9.0)
33
- rake (13.0.1)
34
- rspec (3.9.0)
35
- rspec-core (~> 3.9.0)
36
- rspec-expectations (~> 3.9.0)
37
- rspec-mocks (~> 3.9.0)
38
- rspec-core (3.9.0)
39
- rspec-support (~> 3.9.0)
40
- rspec-expectations (3.9.0)
27
+ method_source (1.0.0)
28
+ minitar (0.9)
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)
41
40
  diff-lcs (>= 1.2.0, < 2.0)
42
- rspec-support (~> 3.9.0)
43
- rspec-mocks (3.9.0)
41
+ rspec-support (~> 3.10.0)
42
+ rspec-mocks (3.10.2)
44
43
  diff-lcs (>= 1.2.0, < 2.0)
45
- rspec-support (~> 3.9.0)
46
- rspec-support (3.9.0)
47
- substrate_common.rb (0.1.9)
48
- base58
49
- blake2b
50
- xxhash
51
- thor (0.19.4)
52
- thread_safe (0.3.6)
53
- tzinfo (1.2.8)
54
- thread_safe (~> 0.1)
44
+ rspec-support (~> 3.10.0)
45
+ rspec-support (3.10.2)
46
+ thermite (0.13.0)
47
+ minitar (~> 0.5)
48
+ rake (>= 10)
49
+ tomlrb (~> 1.2)
50
+ thor (1.1.0)
51
+ tomlrb (1.3.0)
52
+ websocket-driver (0.7.3)
53
+ websocket-extensions (>= 0.1.0)
54
+ websocket-extensions (0.1.5)
55
55
  xxhash (0.4.0)
56
- zeitwerk (2.4.1)
57
56
 
58
57
  PLATFORMS
59
58
  ruby
60
59
 
61
60
  DEPENDENCIES
62
- bundler (~> 1.17)
63
- ffi (~> 1.12)
61
+ bundler
62
+ ffi (~> 1.15.0)
64
63
  pry
65
64
  rake (~> 13.0)
66
65
  rspec (~> 3.2)
67
66
  scale.rb!
68
67
 
69
68
  BUNDLED WITH
70
- 1.17.3
69
+ 2.2.13
data/README.md CHANGED
@@ -19,7 +19,7 @@ Because the feature of ruby 2.6 is used, the ruby version is required to be >= 2
19
19
  Add this line to your application's Gemfile:
20
20
 
21
21
  ```ruby
22
- gem 'scale.rb'
22
+ gem 'scale.rb', '0.2.19'
23
23
  ```
24
24
 
25
25
  And then execute:
@@ -37,10 +37,22 @@ Or install it yourself as:
37
37
  ```ruby
38
38
  require "scale"
39
39
 
40
+ Scale::TypeRegistry.instance.load # default
41
+ # Scale::TypeRegistry.instance.load spec_name: "pangolin"
42
+ # Scale::TypeRegistry.instance.load spec_name: "kusama"
43
+
44
+ # print hex changes if you set debug to true, default is false
45
+ Scale::Types.debug = true
46
+
40
47
  # decode a compact integer
41
48
  scale_bytes = Scale::Bytes.new("0x1501") # create scale_bytes object from scale encoded hex string
42
49
  o = Scale::Types::Compact.decode(scale_bytes) # use scale type to decode scale_bytes object
43
50
  p o.value # 69
51
+
52
+ #
53
+ type = Scale::Types::get("Vec<U8>")
54
+ o = type.decode(Scale::Bytes.new("0x080001"))
55
+ assert_eq o.value, [Scale::Types::U8.new(0), Scale::Types::U8.new(1)]
44
56
  ```
45
57
 
46
58
  2. encode
@@ -48,8 +60,23 @@ p o.value # 69
48
60
  ```ruby
49
61
  require "scale"
50
62
 
63
+ Scale::TypeRegistry.instance.load
64
+
51
65
  o = Scale::Types::Compact.new(69)
52
66
  p o.encode # "1501"
67
+
68
+ type = Scale::Types::get("Vec<U8>")
69
+ o = type.new([Scale::Types::U8.new(0), Scale::Types::U8.new(1)])
70
+ p o.encode # "080001"
71
+ ```
72
+
73
+ 3. client
74
+ ```ruby
75
+ require "scale"
76
+
77
+ client = SubstrateClient.new "wss://pangolin-rpc.darwinia.network"
78
+ client.get_storage("EthereumRelay", "ConfirmedHeaderParcels", [0])
79
+
53
80
  ```
54
81
  Please go to `spec` dir for more examples.
55
82
 
data/exe/scale CHANGED
@@ -1,79 +1,48 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'scale'
4
- require 'thor'
3
+ require "thor"
4
+ require "scale"
5
5
 
6
6
  class ScaleCli < Thor
7
- desc "specs", "list all chain specs"
8
- def specs
9
- path = File.join File.expand_path('../..', __FILE__), "lib", "type_registry", "*.json"
10
- specs = Dir[path].map do |file|
11
- File.basename file, ".json"
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
12
42
  end
13
- puts specs.join(", ")
14
- end
15
-
16
- # exmaples:
17
- #
18
- # scale types darwinia
19
- # =>
20
- # ProposalCategory => Scale::Types::ProposalCategory
21
- # VoteStage => Scale::Types::VoteStage
22
- # TallyType => Scale::Types::TallyType
23
- # ...
24
- #
25
- # Count: 279
26
- desc "types SPEC_NAME SPEC_VERSION", "list all types implemented for chain"
27
- def types(spec_name = "default", spec_version = nil)
28
- Scale::TypeRegistry.instance.load(spec_name, spec_version)
29
- Scale::Types.list.each_pair do |type_name, type|
30
- puts "#{green(type_name)} => #{yellow(type.to_s)}"
31
- end
32
-
33
- puts "\nCount: #{Scale::Types.list.length}"
34
- end
35
-
36
- # exmaples:
37
- #
38
- # scale type Compact
39
- # => Scale::Types::Compact
40
- #
41
- # scale type SessionKeysPolkadot kusama
42
- # => nil
43
- #
44
- # scale type SessionKeysPolkadot kusama 1054
45
- # => Scale::Types::Struct_Of_AccountId_AccountId_AccountId_AccountId_AccountId_70247479160460
46
- #
47
- # scale type "UnappliedSlash<AccountId, BalanceOf>"
48
- # => Scale::Types::Struct_Of_AccountId_AccountId_Vec˂UnappliedSlashOther˃_Vec˂AccountId˃_Balance_70145184872260
49
- #
50
- desc "type TYPE_NAME SPEC_NAME SPEC_VERSION", "show type's ruby class"
51
- def type(type_name, spec_name = "default", spec_version = nil)
52
- Scale::TypeRegistry.instance.load(spec_name, spec_version)
53
- p Scale::Types.get(type_name)
54
- end
55
-
56
- # exmaples:
57
- #
58
- # scale decode Compact 0x0300000040
59
- # => #<Scale::Types::Compact:0x00007fc86b9d1198 @value=1073741824>
60
- desc "decode TYPE_NAME HEX SPEC_NAME SPEC_VERSION", "decode HEX string using TYPE_NAME"
61
- def decode(type_name, hex, spec_name = "default", spec_version = nil)
62
- Scale::TypeRegistry.instance.load(spec_name, spec_version)
63
- type = Scale::Types.get(type_name)
64
- scale_bytes = Scale::Bytes.new(hex)
65
- p type.decode(scale_bytes)
66
- end
67
43
 
68
- # exmaples:
69
- #
70
- # scale encode SessionIndex 2818
71
- # => #<Scale::Types::Compact:0x00007fc86b9d1198 @value=1073741824>
72
- desc "encode TYPE_NAME VALUE SPEC_NAME SPEC_VERSION", "encode value"
73
- def encode(type_name, value, spec_name = "default", spec_version = nil)
74
- Scale::TypeRegistry.instance.load(spec_name, spec_version)
75
- type = Scale::Types.get(type_name)
76
- p "0x" + type.new(value.to_i).encode
44
+ types.uniq!
45
+ puts types
77
46
  end
78
47
  end
79
48
 
data/lib/address.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'blake2b'
2
+ require 'base58'
3
+
data/lib/common.rb ADDED
@@ -0,0 +1,163 @@
1
+ require 'xxhash'
2
+ require 'blake2b'
3
+ require 'base58'
4
+
5
+ class Array
6
+ def bytes_to_hex
7
+ raise "Not a byte array" unless self.is_byte_array?
8
+ '0x' + self.map { |b| b.to_s(16).rjust(2, '0') }.join
9
+ end
10
+
11
+ def bytes_to_bin
12
+ raise "Not a byte array" unless self.is_byte_array?
13
+ '0b' + self.map { |b| b.to_s(2).rjust(8, '0') }.join
14
+ end
15
+
16
+ def bytes_to_bin
17
+ raise "Not a byte array" unless self.is_byte_array?
18
+ self.map { |b| b.to_s(2).rjust(8, '0') }
19
+ end
20
+
21
+ def bytes_to_utf8
22
+ raise "Not a byte array" unless self.is_byte_array?
23
+ self.pack('C*').force_encoding('utf-8')
24
+ end
25
+
26
+ def is_byte_array?
27
+ self.all? {|e| e >= 0 and e <= 255 }
28
+ end
29
+ end
30
+
31
+ class String
32
+ def constantize2
33
+ Object.const_get(self)
34
+ end
35
+
36
+ def hex_to_bytes
37
+ data = self.start_with?('0x') ? self[2..] : self
38
+ raise "Not valid hex string" if data.length % 2 != 0
39
+ data.scan(/../).map(&:hex)
40
+ end
41
+ end
42
+
43
+ module Crypto
44
+ def self.identity(bytes)
45
+ bytes.bytes_to_hex[2..]
46
+ end
47
+
48
+ def self.twox64(data)
49
+ result = XXhash.xxh64 data, 0
50
+ bytes = result.to_s(16).rjust(16, '0').hex_to_bytes.reverse
51
+ bytes.bytes_to_hex[2..]
52
+ end
53
+
54
+ def self.twox128(data)
55
+ bytes = []
56
+ 2.times do |i|
57
+ result = XXhash.xxh64 data, i
58
+ bytes = bytes + result.to_s(16).rjust(16, '0').hex_to_bytes.reverse
59
+ end
60
+ bytes.bytes_to_hex[2..]
61
+ end
62
+
63
+ def self.twox64_concat(bytes)
64
+ data = bytes.bytes_to_utf8
65
+ twox64(data) + bytes.bytes_to_hex[2..]
66
+ end
67
+
68
+ def self.blake2_128(bytes)
69
+ Blake2b.hex bytes, 16
70
+ end
71
+
72
+ def self.blake2_256(bytes)
73
+ Blake2b.hex bytes, 32
74
+ end
75
+
76
+ def self.blake2_128_concat(bytes)
77
+ blake2_128(bytes) + bytes.bytes_to_hex[2..]
78
+ end
79
+ end
80
+
81
+ class Address
82
+ SS58_PREFIX = 'SS58PRE'
83
+
84
+ TYPES = [
85
+ # Polkadot Live (SS58, AccountId)
86
+ 0, 1,
87
+ # Polkadot Canary (SS58, AccountId)
88
+ 2, 3,
89
+ # Kulupu (SS58, Reserved)
90
+ 16, 17,
91
+ # Darwinia Live
92
+ 18,
93
+ # Dothereum (SS58, AccountId)
94
+ 20, 21,
95
+ # Generic Substrate wildcard (SS58, AccountId)
96
+ 42, 43,
97
+
98
+ # Schnorr/Ristretto 25519 ("S/R 25519") key
99
+ 48,
100
+ # Edwards Ed25519 key
101
+ 49,
102
+ # ECDSA SECP256k1 key
103
+ 50,
104
+
105
+ # Reserved for future address format extensions.
106
+ *64..255
107
+ ]
108
+
109
+ class << self
110
+
111
+ def array_to_hex_string(arr)
112
+ body = arr.map { |i| i.to_s(16).rjust(2, '0') }.join
113
+ "0x#{body}"
114
+ end
115
+
116
+ def decode(address, addr_type = 42, ignore_checksum = true)
117
+ decoded = Base58.base58_to_binary(address, :bitcoin)
118
+ is_pubkey = decoded.size == 35
119
+
120
+ size = decoded.size - ( is_pubkey ? 2 : 1 )
121
+
122
+ prefix = decoded[0, 1].unpack("C*").first
123
+
124
+ raise "Invalid address type" unless TYPES.include?(addr_type)
125
+
126
+ hash_bytes = make_hash(decoded[0, size])
127
+ if is_pubkey
128
+ is_valid_checksum = decoded[-2].unpack("C*").first == hash_bytes[0] && decoded[-1].unpack("C*").first == hash_bytes[1]
129
+ else
130
+ is_valid_checksum = decoded[-1].unpack("C*").first == hash_bytes[0]
131
+ end
132
+
133
+ raise "Invalid decoded address checksum" unless is_valid_checksum && ignore_checksum
134
+
135
+ decoded[1...size].unpack("H*").first
136
+ end
137
+
138
+
139
+ def encode(pubkey, addr_type = 42)
140
+ pubkey = pubkey[2..-1] if pubkey =~ /^0x/i
141
+ key = [pubkey].pack("H*")
142
+
143
+ u8_array = key.bytes
144
+
145
+ u8_array.unshift(addr_type)
146
+
147
+ bytes = make_hash(u8_array.pack("C*"))
148
+
149
+ checksum = bytes[0, key.size == 32 ? 2 : 1]
150
+
151
+ u8_array.push(*checksum)
152
+
153
+ input = u8_array.pack("C*")
154
+
155
+ Base58.binary_to_base58(input, :bitcoin)
156
+ end
157
+
158
+ def make_hash(body)
159
+ Blake2b.bytes("#{SS58_PREFIX}#{body}", Blake2b::Key.none, 64)
160
+ end
161
+
162
+ end
163
+ end