scale.rb 0.2.14 → 0.2.19

Sign up to get free protection for your applications and to get access to all the features.
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