eth 0.5.0 → 0.5.3
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/.github/workflows/codeql.yml +4 -0
- data/.github/workflows/spec.yml +14 -3
- data/.yardopts +1 -0
- data/AUTHORS.txt +14 -1
- data/CHANGELOG.md +63 -13
- data/README.md +121 -18
- data/bin/console +2 -1
- data/bin/setup +3 -4
- data/codecov.yml +6 -0
- data/eth.gemspec +5 -7
- data/lib/eth/abi/event.rb +137 -0
- data/lib/eth/abi/type.rb +8 -7
- data/lib/eth/abi.rb +29 -11
- data/lib/eth/address.rb +12 -5
- data/lib/eth/api.rb +223 -0
- data/lib/eth/chain.rb +31 -28
- data/lib/eth/client/http.rb +63 -0
- data/lib/eth/client/ipc.rb +50 -0
- data/lib/eth/client.rb +468 -0
- data/lib/eth/constant.rb +71 -0
- data/lib/eth/contract/event.rb +41 -0
- data/lib/eth/contract/function.rb +56 -0
- data/lib/eth/contract/function_input.rb +36 -0
- data/lib/eth/contract/function_output.rb +32 -0
- data/lib/eth/contract/initializer.rb +46 -0
- data/lib/eth/contract.rb +120 -0
- data/lib/eth/eip712.rb +2 -2
- data/lib/eth/key/decrypter.rb +16 -13
- data/lib/eth/key/encrypter.rb +27 -25
- data/lib/eth/key.rb +21 -16
- data/lib/eth/rlp/decoder.rb +114 -0
- data/lib/eth/rlp/encoder.rb +78 -0
- data/lib/eth/rlp/sedes/big_endian_int.rb +66 -0
- data/lib/eth/rlp/sedes/binary.rb +97 -0
- data/lib/eth/rlp/sedes/list.rb +84 -0
- data/lib/eth/rlp/sedes.rb +74 -0
- data/lib/eth/rlp.rb +63 -0
- data/lib/eth/signature.rb +11 -8
- data/lib/eth/solidity.rb +75 -0
- data/lib/eth/tx/eip1559.rb +22 -14
- data/lib/eth/tx/eip2930.rb +23 -15
- data/lib/eth/tx/legacy.rb +14 -10
- data/lib/eth/tx.rb +28 -34
- data/lib/eth/unit.rb +1 -1
- data/lib/eth/util.rb +68 -11
- data/lib/eth/version.rb +3 -3
- data/lib/eth.rb +15 -2
- metadata +31 -23
- data/lib/eth/abi/constant.rb +0 -63
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright (c) 2016-2022 The Ruby-Eth Contributors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# -*- encoding : ascii-8bit -*-
|
16
|
+
|
17
|
+
# Provides the {Eth} module.
|
18
|
+
module Eth
|
19
|
+
# Provide classes for contract function input.
|
20
|
+
class Contract::FunctionInput
|
21
|
+
attr_accessor :type, :name
|
22
|
+
|
23
|
+
# Constructor of the {Eth::Contract::FunctionInput} class.
|
24
|
+
#
|
25
|
+
# @param data [Hash] contract abi data.
|
26
|
+
def initialize(data)
|
27
|
+
@type = Eth::Abi::Type.parse(data["type"])
|
28
|
+
@name = data["name"]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns types like uint256
|
32
|
+
def type
|
33
|
+
@type.base_type + @type.sub_type
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright (c) 2016-2022 The Ruby-Eth Contributors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# -*- encoding : ascii-8bit -*-
|
16
|
+
|
17
|
+
# Provides the {Eth} module.
|
18
|
+
module Eth
|
19
|
+
# Provide classes for contract function output.
|
20
|
+
class Contract::FunctionOutput
|
21
|
+
attr_accessor :type, :name
|
22
|
+
|
23
|
+
def initialize(data)
|
24
|
+
@type = Eth::Abi::Type.parse(data["type"])
|
25
|
+
@name = data["name"]
|
26
|
+
end
|
27
|
+
|
28
|
+
def type
|
29
|
+
@type.base_type + @type.sub_type
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Copyright (c) 2016-2022 The Ruby-Eth Contributors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# -*- encoding : ascii-8bit -*-
|
16
|
+
|
17
|
+
# Provides the {Eth} module.
|
18
|
+
module Eth
|
19
|
+
# Provide classes for contract initializer.
|
20
|
+
class Contract::Initializer
|
21
|
+
attr_accessor :contracts, :file
|
22
|
+
|
23
|
+
# Constructor of the {Eth::Contract::Initializer} class.
|
24
|
+
#
|
25
|
+
# @param file [String] file path to solidity code.
|
26
|
+
def initialize(file)
|
27
|
+
sol_output = Eth::Solidity.new.compile(file)
|
28
|
+
contracts = sol_output.keys
|
29
|
+
|
30
|
+
@contracts = []
|
31
|
+
contracts.each do |contract|
|
32
|
+
abi = sol_output[contract]["abi"]
|
33
|
+
name = contract
|
34
|
+
code = sol_output[contract]["bin"]
|
35
|
+
@contracts << Contract.new(name, code, abi)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Build and return all contracts.
|
40
|
+
def build_all
|
41
|
+
@contracts.each do |contract|
|
42
|
+
contract.build
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/eth/contract.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# Copyright (c) 2016-2022 The Ruby-Eth Contributors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# -*- encoding : ascii-8bit -*-
|
16
|
+
|
17
|
+
# Provides the {Eth} module.
|
18
|
+
module Eth
|
19
|
+
|
20
|
+
# Provides classes to access smart contracts
|
21
|
+
class Contract
|
22
|
+
attr_reader :address
|
23
|
+
attr_accessor :key
|
24
|
+
attr_accessor :gas_limit, :gas_price, :max_fee_per_gas, :max_priority_fee_per_gas, :nonce
|
25
|
+
attr_accessor :bin, :name, :abi, :class_object
|
26
|
+
attr_accessor :events, :functions, :constructor_inputs
|
27
|
+
|
28
|
+
# Constructor of the {Eth::Contract} class.
|
29
|
+
#
|
30
|
+
# @param name [String] contract name.
|
31
|
+
# @param bin [String] contract bin string.
|
32
|
+
# @param abi [String] contract abi string.
|
33
|
+
def initialize(name, bin, abi)
|
34
|
+
@name = name
|
35
|
+
@bin = bin
|
36
|
+
@abi = abi
|
37
|
+
@constructor_inputs, @functions, @events = parse_abi(abi)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Creates a contract wrapper.
|
41
|
+
#
|
42
|
+
# @param file [String] solidity file path.
|
43
|
+
# @param bin [String] contract bin string.
|
44
|
+
# @param abi [String] contract abi string.
|
45
|
+
# @param address [String] contract address.
|
46
|
+
# @param name [String] name of contract.
|
47
|
+
# @param contract_index [Number] specify contract.
|
48
|
+
# @return [Eth::Contract::Object] Returns the class of the smart contract.
|
49
|
+
# @raise [JSON::ParserError] if the json format is wrong.
|
50
|
+
# @raise [ArgumentError] if argument is incorrect.
|
51
|
+
def self.create(file: nil, bin: nil, abi: nil, address: nil, name: nil, contract_index: nil)
|
52
|
+
if File.exist?(file.to_s)
|
53
|
+
contracts = Eth::Contract::Initializer.new(file).build_all
|
54
|
+
raise "No contracts compiled" if contracts.empty?
|
55
|
+
if contract_index
|
56
|
+
contract = contracts[contract_index].class_object.new
|
57
|
+
else
|
58
|
+
contract = contracts.first.class_object.new
|
59
|
+
end
|
60
|
+
elsif ![name, bin, abi].include? nil
|
61
|
+
begin
|
62
|
+
abi = abi.is_a?(Array) ? abi : JSON.parse(abi)
|
63
|
+
rescue JSON::ParserError => e
|
64
|
+
raise e
|
65
|
+
end
|
66
|
+
contract = Eth::Contract.new(name, bin, abi)
|
67
|
+
contract.build
|
68
|
+
contract = contract.class_object.new
|
69
|
+
else
|
70
|
+
raise ArgumentError, "The argument is incorrect."
|
71
|
+
end
|
72
|
+
contract.address = address
|
73
|
+
contract
|
74
|
+
end
|
75
|
+
|
76
|
+
# Set the address of the smart contract
|
77
|
+
def address=(addr)
|
78
|
+
@address = addr.nil? ? nil : Eth::Address.new(addr).address
|
79
|
+
@events.each do |event|
|
80
|
+
event.set_address(@address)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Create classes for smart contracts
|
85
|
+
def build
|
86
|
+
class_name = @name
|
87
|
+
parent = self
|
88
|
+
class_methods = Class.new do
|
89
|
+
extend Forwardable
|
90
|
+
def_delegators :parent, :key, :key=
|
91
|
+
def_delegators :parent, :name, :abi, :bin
|
92
|
+
def_delegators :parent, :gas_limit, :gas_price, :gas_limit=, :gas_price=, :nonce, :nonce=
|
93
|
+
def_delegators :parent, :max_fee_per_gas, :max_fee_per_gas=, :max_priority_fee_per_gas, :max_priority_fee_per_gas=
|
94
|
+
def_delegators :parent, :events
|
95
|
+
def_delegators :parent, :address, :address=
|
96
|
+
def_delegator :parent, :functions
|
97
|
+
define_method :parent do
|
98
|
+
parent
|
99
|
+
end
|
100
|
+
end
|
101
|
+
Eth::Contract.send(:remove_const, class_name) if Eth::Contract.const_defined?(class_name, false)
|
102
|
+
Eth::Contract.const_set(class_name, class_methods)
|
103
|
+
@class_object = class_methods
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def parse_abi(abi)
|
109
|
+
constructor = abi.detect { |x| x["type"] == "constructor" }
|
110
|
+
if !constructor.nil?
|
111
|
+
constructor_inputs = constructor["inputs"].map { |input| Eth::Contract::FunctionInput.new(input) }
|
112
|
+
else
|
113
|
+
constructor_inputs = []
|
114
|
+
end
|
115
|
+
functions = abi.select { |x| x["type"] == "function" }.map { |fun| Eth::Contract::Function.new(fun) }
|
116
|
+
events = abi.select { |x| x["type"] == "event" }.map { |evt| Eth::Contract::Event.new(evt) }
|
117
|
+
[constructor_inputs, functions, events]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
data/lib/eth/eip712.rb
CHANGED
@@ -12,11 +12,11 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
# Provides the
|
15
|
+
# Provides the {Eth} module.
|
16
16
|
module Eth
|
17
17
|
|
18
18
|
# Defines handy tools for encoding typed structured data as per EIP-712.
|
19
|
-
#
|
19
|
+
# Ref: https://eips.ethereum.org/EIPS/eip-712
|
20
20
|
module Eip712
|
21
21
|
extend self
|
22
22
|
|
data/lib/eth/key/decrypter.rb
CHANGED
@@ -12,37 +12,40 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
# Provides the
|
15
|
+
# Provides the {Eth} module.
|
16
16
|
module Eth
|
17
17
|
|
18
|
-
# The Eth::Key::Decrypter class to handle PBKDF2-SHA-256 decryption.
|
18
|
+
# The {Eth::Key::Decrypter} class to handle PBKDF2-SHA-256 decryption.
|
19
19
|
class Key::Decrypter
|
20
20
|
|
21
21
|
# Provides a specific decrypter error if decryption fails.
|
22
22
|
class DecrypterError < StandardError; end
|
23
23
|
|
24
|
-
# Class method
|
24
|
+
# Class method {Eth::Key::Decrypter.perform} to perform an keystore
|
25
|
+
# decryption.
|
25
26
|
#
|
26
|
-
# @param data [JSON] encryption data including cypherkey
|
27
|
-
# @param password [String] password to decrypt the key
|
28
|
-
# @return [Eth::Key] decrypted key-pair
|
27
|
+
# @param data [JSON] encryption data including cypherkey.
|
28
|
+
# @param password [String] password to decrypt the key.
|
29
|
+
# @return [Eth::Key] decrypted key-pair.
|
29
30
|
def self.perform(data, password)
|
30
31
|
new(data, password).perform
|
31
32
|
end
|
32
33
|
|
33
|
-
# Constructor of the
|
34
|
-
#
|
34
|
+
# Constructor of the {Eth::Key::Decrypter} class for secret key
|
35
|
+
# decryption. Should not be used; use {Eth::Key::Decrypter.perform}
|
36
|
+
# instead.
|
35
37
|
#
|
36
|
-
# @param data [JSON] encryption data including cypherkey
|
37
|
-
# @param password [String] password to decrypt the key
|
38
|
+
# @param data [JSON] encryption data including cypherkey.
|
39
|
+
# @param password [String] password to decrypt the key.
|
38
40
|
def initialize(data, password)
|
39
|
-
|
41
|
+
data = JSON.parse(data) if data.is_a? String
|
42
|
+
@data = data
|
40
43
|
@password = password
|
41
44
|
end
|
42
45
|
|
43
|
-
# Method to decrypt key using password
|
46
|
+
# Method to decrypt key using password.
|
44
47
|
#
|
45
|
-
# @return [
|
48
|
+
# @return [Eth::Key] decrypted key.
|
46
49
|
def perform
|
47
50
|
derive_key password
|
48
51
|
check_macs
|
data/lib/eth/key/encrypter.rb
CHANGED
@@ -12,45 +12,47 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
# Provides the
|
15
|
+
# Provides the {Eth} module.
|
16
16
|
module Eth
|
17
17
|
|
18
|
-
# The Eth::Key::Encrypter class to handle PBKDF2-SHA-256 encryption.
|
18
|
+
# The {Eth::Key::Encrypter} class to handle PBKDF2-SHA-256 encryption.
|
19
19
|
class Key::Encrypter
|
20
20
|
|
21
21
|
# Provides a specific encrypter error if decryption fails.
|
22
22
|
class EncrypterError < StandardError; end
|
23
23
|
|
24
|
-
# Class method
|
24
|
+
# Class method {Eth::Key::Encrypter.perform} to performa an key-store
|
25
25
|
# encryption.
|
26
26
|
#
|
27
|
-
# @param key [Eth::Key] representing a secret key-pair used for encryption
|
28
|
-
# @param options [Hash] the options to encrypt with
|
29
|
-
# @option options [String] :kdf key derivation function defaults to pbkdf2
|
30
|
-
# @option options [String] :id uuid given to the secret key
|
31
|
-
# @option options [String] :iterations number of iterations for the hash function
|
32
|
-
# @option options [String] :salt passed to PBKDF
|
33
|
-
# @option options [String] :iv 128-bit initialisation vector for the cipher
|
34
|
-
# @option options [Integer] :parallelization parallelization factor for scrypt, defaults to 8
|
35
|
-
# @option options [Integer] :block_size for scrypt, defaults to 1
|
36
|
-
# @return [JSON] formatted with encrypted key (cyphertext) and [other identifying data](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition#pbkdf2-sha-256)
|
27
|
+
# @param key [Eth::Key] representing a secret key-pair used for encryption.
|
28
|
+
# @param options [Hash] the options to encrypt with.
|
29
|
+
# @option options [String] :kdf key derivation function defaults to pbkdf2.
|
30
|
+
# @option options [String] :id uuid given to the secret key.
|
31
|
+
# @option options [String] :iterations number of iterations for the hash function.
|
32
|
+
# @option options [String] :salt passed to PBKDF.
|
33
|
+
# @option options [String] :iv 128-bit initialisation vector for the cipher.
|
34
|
+
# @option options [Integer] :parallelization parallelization factor for scrypt, defaults to 8.
|
35
|
+
# @option options [Integer] :block_size for scrypt, defaults to 1.
|
36
|
+
# @return [JSON] formatted with encrypted key (cyphertext) and [other identifying data](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition#pbkdf2-sha-256).
|
37
37
|
def self.perform(key, password, options = {})
|
38
38
|
new(key, options).perform(password)
|
39
39
|
end
|
40
40
|
|
41
|
-
# Constructor of the
|
42
|
-
# encryption.
|
41
|
+
# Constructor of the {Eth::Key::Encrypter} class for secret key
|
42
|
+
# encryption. Should not be used; use {Eth::Key::Encrypter.perform}
|
43
|
+
# instead.
|
43
44
|
#
|
44
|
-
# @param key [Eth::Key] representing a secret key-pair used for encryption
|
45
|
-
# @param options [Hash] the options to encrypt with
|
46
|
-
# @option options [String] :kdf key derivation function defaults to pbkdf2
|
47
|
-
# @option options [String] :id uuid given to the secret key
|
48
|
-
# @option options [String] :iterations number of iterations for the hash function
|
49
|
-
# @option options [String] :salt passed to PBKDF
|
50
|
-
# @option options [String] :iv 128-bit initialisation vector for the cipher
|
51
|
-
# @option options [Integer] :parallelization parallelization factor for scrypt, defaults to 8
|
52
|
-
# @option options [Integer] :block_size for scrypt, defaults to 1
|
45
|
+
# @param key [Eth::Key] representing a secret key-pair used for encryption.
|
46
|
+
# @param options [Hash] the options to encrypt with.
|
47
|
+
# @option options [String] :kdf key derivation function defaults to pbkdf2.
|
48
|
+
# @option options [String] :id uuid given to the secret key.
|
49
|
+
# @option options [String] :iterations number of iterations for the hash function.
|
50
|
+
# @option options [String] :salt passed to PBKDF.
|
51
|
+
# @option options [String] :iv 128-bit initialisation vector for the cipher.
|
52
|
+
# @option options [Integer] :parallelization parallelization factor for scrypt, defaults to 8.
|
53
|
+
# @option options [Integer] :block_size for scrypt, defaults to 1.
|
53
54
|
def initialize(key, options = {})
|
55
|
+
key = Key.new(priv: key) if key.is_a? String
|
54
56
|
@key = key
|
55
57
|
@options = options
|
56
58
|
|
@@ -64,7 +66,7 @@ module Eth
|
|
64
66
|
# Encrypt the key with a given password.
|
65
67
|
#
|
66
68
|
# @param password [String] a secret key used for encryption
|
67
|
-
# @return [String] a
|
69
|
+
# @return [String] a JSON-formatted keystore string.
|
68
70
|
def perform(password)
|
69
71
|
derive_key password
|
70
72
|
encrypt
|
data/lib/eth/key.rb
CHANGED
@@ -18,28 +18,28 @@ require "rbsecp256k1"
|
|
18
18
|
require "scrypt"
|
19
19
|
require "securerandom"
|
20
20
|
|
21
|
-
# Provides the
|
21
|
+
# Provides the {Eth} module.
|
22
22
|
module Eth
|
23
23
|
|
24
|
-
# The
|
24
|
+
# The {Eth::Key} class to handle Secp256k1 private/public key-pairs.
|
25
25
|
class Key
|
26
26
|
|
27
|
-
# The Eth::Key::Decrypter class to handle PBKDF2-SHA-256 decryption.
|
27
|
+
# The {Eth::Key::Decrypter} class to handle PBKDF2-SHA-256 decryption.
|
28
28
|
autoload :Decrypter, "eth/key/decrypter"
|
29
29
|
|
30
|
-
# The Eth::Key::Encrypter class to handle PBKDF2-SHA-256 encryption.
|
30
|
+
# The {Eth::Key::Encrypter} class to handle PBKDF2-SHA-256 encryption.
|
31
31
|
autoload :Encrypter, "eth/key/encrypter"
|
32
32
|
|
33
|
-
# The `Secp256k1::PrivateKey` of the
|
33
|
+
# The `Secp256k1::PrivateKey` of the {Eth::Key} pair.
|
34
34
|
attr_reader :private_key
|
35
35
|
|
36
|
-
# The `Secp256k1::PublicKey` of the
|
36
|
+
# The `Secp256k1::PublicKey` of the {Eth::Key} pair.
|
37
37
|
attr_reader :public_key
|
38
38
|
|
39
|
-
# Constructor of the
|
39
|
+
# Constructor of the {Eth::Key} class. Creates a new random key-pair
|
40
40
|
# if no `priv` key is provided.
|
41
41
|
#
|
42
|
-
# @param priv [String] binary string of private key data
|
42
|
+
# @param priv [String] binary string of private key data.
|
43
43
|
def initialize(priv: nil)
|
44
44
|
|
45
45
|
# Creates a new, randomized libsecp256k1 context.
|
@@ -63,9 +63,10 @@ module Eth
|
|
63
63
|
end
|
64
64
|
|
65
65
|
# Signs arbitrary data without validation. Should not be used unless really
|
66
|
-
# desired. See also: personal_sign, sign_typed_data
|
66
|
+
# desired. See also: {Key.personal_sign}, {Key.sign_typed_data}, and
|
67
|
+
# {Signature.recover}.
|
67
68
|
#
|
68
|
-
# @param blob [
|
69
|
+
# @param blob [Object] that arbitrary data to be signed.
|
69
70
|
# @param chain_id [Integer] the chain id the signature should be generated on.
|
70
71
|
# @return [String] a hexa-decimal signature.
|
71
72
|
def sign(blob, chain_id = nil)
|
@@ -81,9 +82,11 @@ module Eth
|
|
81
82
|
Util.bin_to_hex signature.pack "c*"
|
82
83
|
end
|
83
84
|
|
84
|
-
# Prefixes a message with
|
85
|
+
# Prefixes a message with `\x19Ethereum Signed Message:` and signs
|
85
86
|
# it in the common way used by many web3 wallets. Complies with
|
86
|
-
# EIP-191 prefix 0x19 and version byte 0x45 (E).
|
87
|
+
# EIP-191 prefix `0x19` and version byte `0x45` (`E`). See also
|
88
|
+
# {Signature.personal_recover}.
|
89
|
+
# Ref: https://eips.ethereum.org/EIPS/eip-191
|
87
90
|
#
|
88
91
|
# @param message [String] the message string to be prefixed and signed.
|
89
92
|
# @param chain_id [Integer] the chain id the signature should be generated on.
|
@@ -95,8 +98,10 @@ module Eth
|
|
95
98
|
end
|
96
99
|
|
97
100
|
# Prefixes, hashes, and signes a typed data structure in the common
|
98
|
-
# way used by many web3 wallets. Complies with EIP-191 prefix 0x19
|
99
|
-
# and EIP-712 version byte 0x01
|
101
|
+
# way used by many web3 wallets. Complies with EIP-191 prefix `0x19`
|
102
|
+
# and EIP-712 version byte `0x01`. Supports `V3`, `V4`. See also
|
103
|
+
# {Signature.recover_typed_data}.
|
104
|
+
# Ref: https://eips.ethereum.org/EIPS/eip-712
|
100
105
|
#
|
101
106
|
# @param typed_data [Array] all the data in the typed data structure to be signed.
|
102
107
|
# @param chain_id [Integer] the chain id the signature should be generated on.
|
@@ -114,7 +119,7 @@ module Eth
|
|
114
119
|
end
|
115
120
|
|
116
121
|
# Exports the private key bytes in a wrapper function to maintain
|
117
|
-
# backward-compatibility with older versions of
|
122
|
+
# backward-compatibility with older versions of {Eth::Key}.
|
118
123
|
#
|
119
124
|
# @return [String] private key as packed byte-string.
|
120
125
|
def private_bytes
|
@@ -138,7 +143,7 @@ module Eth
|
|
138
143
|
end
|
139
144
|
|
140
145
|
# Exports the uncompressed public key bytes in a wrapper function to
|
141
|
-
# maintain backward-compatibility with older versions of
|
146
|
+
# maintain backward-compatibility with older versions of {Eth::Key}.
|
142
147
|
#
|
143
148
|
# @return [String] uncompressed public key as packed byte-string.
|
144
149
|
def public_bytes
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# Copyright (c) 2016-2022 The Ruby-Eth Contributors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# -*- encoding : ascii-8bit -*-
|
16
|
+
|
17
|
+
# Provides the {Eth} module.
|
18
|
+
module Eth
|
19
|
+
|
20
|
+
# Provides an recursive-length prefix (RLP) encoder and decoder.
|
21
|
+
module Rlp
|
22
|
+
|
23
|
+
# Provides an RLP-decoder.
|
24
|
+
module Decoder
|
25
|
+
extend self
|
26
|
+
|
27
|
+
# Decodes an RLP-encoded object.
|
28
|
+
#
|
29
|
+
# @param rlp [String] an RLP-encoded object.
|
30
|
+
# @return [Object] the decoded and maybe deserialized object.
|
31
|
+
# @raise [Eth::Rlp::DecodingError] if the input string does not end after
|
32
|
+
# the root item.
|
33
|
+
def perform(rlp)
|
34
|
+
rlp = Util.hex_to_bin rlp if Util.is_hex? rlp
|
35
|
+
rlp = Util.str_to_bytes rlp
|
36
|
+
begin
|
37
|
+
item, next_start = consume_item rlp, 0
|
38
|
+
rescue Exception => e
|
39
|
+
raise DecodingError, "Cannot decode rlp string: #{e}"
|
40
|
+
end
|
41
|
+
raise DecodingError, "RLP string ends with #{rlp.size - next_start} superfluous bytes" if next_start != rlp.size
|
42
|
+
return item
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# Consume an RLP-encoded item from the given start.
|
48
|
+
def consume_item(rlp, start)
|
49
|
+
t, l, s = consume_length_prefix rlp, start
|
50
|
+
consume_payload rlp, s, t, l
|
51
|
+
end
|
52
|
+
|
53
|
+
# Consume an RLP length prefix at the given position.
|
54
|
+
def consume_length_prefix(rlp, start)
|
55
|
+
b0 = rlp[start].ord
|
56
|
+
if b0 < Constant::PRIMITIVE_PREFIX_OFFSET
|
57
|
+
|
58
|
+
# single byte
|
59
|
+
[:str, 1, start]
|
60
|
+
elsif b0 < Constant::PRIMITIVE_PREFIX_OFFSET + Constant::SHORT_LENGTH_LIMIT
|
61
|
+
raise DecodingError, "Encoded as short string although single byte was possible" if (b0 - Constant::PRIMITIVE_PREFIX_OFFSET == 1) && rlp[start + 1].ord < Constant::PRIMITIVE_PREFIX_OFFSET
|
62
|
+
|
63
|
+
# short string
|
64
|
+
[:str, b0 - Constant::PRIMITIVE_PREFIX_OFFSET, start + 1]
|
65
|
+
elsif b0 < Constant::LIST_PREFIX_OFFSET
|
66
|
+
enforce_no_zero_bytes rlp, start
|
67
|
+
|
68
|
+
# long string
|
69
|
+
ll = b0 - Constant::PRIMITIVE_PREFIX_OFFSET - Constant::SHORT_LENGTH_LIMIT + 1
|
70
|
+
l = Util.big_endian_to_int rlp[(start + 1)...(start + 1 + ll)]
|
71
|
+
raise DecodingError, "Long string prefix used for short string" if l < Constant::SHORT_LENGTH_LIMIT
|
72
|
+
[:str, l, start + 1 + ll]
|
73
|
+
elsif b0 < Constant::LIST_PREFIX_OFFSET + Constant::SHORT_LENGTH_LIMIT
|
74
|
+
|
75
|
+
# short list
|
76
|
+
[:list, b0 - Constant::LIST_PREFIX_OFFSET, start + 1]
|
77
|
+
else
|
78
|
+
enforce_no_zero_bytes rlp, start
|
79
|
+
|
80
|
+
# long list
|
81
|
+
ll = b0 - Constant::LIST_PREFIX_OFFSET - Constant::SHORT_LENGTH_LIMIT + 1
|
82
|
+
l = Util.big_endian_to_int rlp[(start + 1)...(start + 1 + ll)]
|
83
|
+
raise DecodingError, "Long list prefix used for short list" if l < Constant::SHORT_LENGTH_LIMIT
|
84
|
+
[:list, l, start + 1 + ll]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Enforce RLP slices to not start with empty bytes.
|
89
|
+
def enforce_no_zero_bytes(rlp, start)
|
90
|
+
raise DecodingError, "Length starts with zero bytes" if rlp.slice(start + 1) == Constant::BYTE_ZERO
|
91
|
+
end
|
92
|
+
|
93
|
+
# Consume an RLP payload at the given position of given type and size.
|
94
|
+
def consume_payload(rlp, start, type, length)
|
95
|
+
case type
|
96
|
+
when :str
|
97
|
+
[rlp[start...(start + length)], start + length]
|
98
|
+
when :list
|
99
|
+
items = []
|
100
|
+
next_item_start = start
|
101
|
+
payload_end = next_item_start + length
|
102
|
+
while next_item_start < payload_end
|
103
|
+
item, next_item_start = consume_item rlp, next_item_start
|
104
|
+
items.push item
|
105
|
+
end
|
106
|
+
raise DecodingError, "List length prefix announced a too small length" if next_item_start > payload_end
|
107
|
+
[items, next_item_start]
|
108
|
+
else
|
109
|
+
raise TypeError, "Type must be either :str or :list"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Copyright (c) 2016-2022 The Ruby-Eth Contributors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# -*- encoding : ascii-8bit -*-
|
16
|
+
|
17
|
+
# Provides the {Eth} module.
|
18
|
+
module Eth
|
19
|
+
|
20
|
+
# Provides an recursive-length prefix (RLP) encoder and decoder.
|
21
|
+
module Rlp
|
22
|
+
|
23
|
+
# Provides an RLP-encoder.
|
24
|
+
module Encoder
|
25
|
+
extend self
|
26
|
+
|
27
|
+
# Encodes a Ruby object in RLP format.
|
28
|
+
#
|
29
|
+
# @param obj [Object] a Ruby object.
|
30
|
+
# @return [String] the RLP encoded item.
|
31
|
+
# @raise [Eth::Rlp::EncodingError] in the rather unlikely case that the item
|
32
|
+
# is too big to encode (will not happen).
|
33
|
+
# @raise [Eth::Rlp::SerializationError] if the serialization fails.
|
34
|
+
def perform(obj)
|
35
|
+
item = Sedes.infer(obj).serialize(obj)
|
36
|
+
result = encode_raw item
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# Encodes the raw item.
|
42
|
+
def encode_raw(item)
|
43
|
+
return item if item.instance_of? Rlp::Data
|
44
|
+
return encode_primitive item if Util.is_primitive? item
|
45
|
+
return encode_list item if Util.is_list? item
|
46
|
+
raise EncodingError "Cannot encode object of type #{item.class.name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
# Encodes a single primitive.
|
50
|
+
def encode_primitive(item)
|
51
|
+
return Util.str_to_bytes item if item.size == 1 && item.ord < Constant::PRIMITIVE_PREFIX_OFFSET
|
52
|
+
payload = Util.str_to_bytes item
|
53
|
+
prefix = length_prefix payload.size, Constant::PRIMITIVE_PREFIX_OFFSET
|
54
|
+
"#{prefix}#{payload}"
|
55
|
+
end
|
56
|
+
|
57
|
+
# Encodes a single list.
|
58
|
+
def encode_list(list)
|
59
|
+
payload = list.map { |item| encode_raw item }.join
|
60
|
+
prefix = length_prefix payload.size, Constant::LIST_PREFIX_OFFSET
|
61
|
+
"#{prefix}#{payload}"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Determines a length prefix.
|
65
|
+
def length_prefix(length, offset)
|
66
|
+
if length < Constant::SHORT_LENGTH_LIMIT
|
67
|
+
(offset + length).chr
|
68
|
+
elsif length < Constant::LONG_LENGTH_LIMIT
|
69
|
+
length_string = Util.int_to_big_endian length
|
70
|
+
length_len = (offset + Constant::SHORT_LENGTH_LIMIT - 1 + length_string.size).chr
|
71
|
+
"#{length_len}#{length_string}"
|
72
|
+
else
|
73
|
+
raise EncodingError, "Length greater than 256**8: #{length}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|