eth 0.5.14 → 0.5.16
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 -4
- data/.github/workflows/docs.yml +1 -1
- data/.github/workflows/spec.yml +31 -13
- data/CHANGELOG.md +53 -0
- data/CODE_OF_CONDUCT.md +3 -5
- data/Gemfile +3 -3
- data/README.md +8 -6
- data/SECURITY.md +2 -2
- data/eth.gemspec +10 -1
- data/lib/eth/abi/decoder.rb +94 -39
- data/lib/eth/abi/encoder.rb +85 -58
- data/lib/eth/abi/function.rb +124 -0
- data/lib/eth/abi/type.rb +69 -5
- data/lib/eth/abi.rb +2 -0
- data/lib/eth/bls.rb +68 -0
- data/lib/eth/chain.rb +3 -0
- data/lib/eth/client/http.rb +5 -8
- data/lib/eth/client/ws.rb +323 -0
- data/lib/eth/client.rb +44 -40
- data/lib/eth/contract/error.rb +62 -0
- data/lib/eth/contract/function.rb +21 -0
- data/lib/eth/contract/function_output.rb +11 -3
- data/lib/eth/contract.rb +55 -4
- data/lib/eth/eip712.rb +48 -13
- data/lib/eth/key.rb +1 -1
- data/lib/eth/tx/eip1559.rb +32 -7
- data/lib/eth/tx/eip2930.rb +31 -6
- data/lib/eth/tx/eip4844.rb +401 -0
- data/lib/eth/tx/eip7702.rb +34 -9
- data/lib/eth/tx/legacy.rb +30 -6
- data/lib/eth/tx.rb +45 -4
- data/lib/eth/util.rb +19 -7
- data/lib/eth/version.rb +1 -1
- data/lib/eth.rb +1 -0
- metadata +53 -15
data/lib/eth/tx/legacy.rb
CHANGED
|
@@ -68,7 +68,7 @@ module Eth
|
|
|
68
68
|
# @option params [Integer] :gas_price the gas price.
|
|
69
69
|
# @option params [Integer] :gas_limit the gas limit.
|
|
70
70
|
# @option params [Eth::Address] :from the sender address.
|
|
71
|
-
# @option params [Eth::Address] :to the
|
|
71
|
+
# @option params [Eth::Address] :to the receiver address.
|
|
72
72
|
# @option params [Integer] :value the transaction value.
|
|
73
73
|
# @option params [String] :data the transaction data payload.
|
|
74
74
|
# @param chain_id [Integer] the EIP-155 Chain ID.
|
|
@@ -128,18 +128,18 @@ module Eth
|
|
|
128
128
|
raise ParameterError, "Transaction missing fields!" if tx.size < 9
|
|
129
129
|
|
|
130
130
|
# populate the 9 fields
|
|
131
|
-
nonce = Util.
|
|
132
|
-
gas_price = Util.
|
|
133
|
-
gas_limit = Util.
|
|
131
|
+
nonce = Util.deserialize_rlp_int tx[0]
|
|
132
|
+
gas_price = Util.deserialize_rlp_int tx[1]
|
|
133
|
+
gas_limit = Util.deserialize_rlp_int tx[2]
|
|
134
134
|
to = Util.bin_to_hex tx[3]
|
|
135
|
-
value = Util.
|
|
135
|
+
value = Util.deserialize_rlp_int tx[4]
|
|
136
136
|
data = tx[5]
|
|
137
137
|
v = Util.bin_to_hex tx[6]
|
|
138
138
|
r = Util.bin_to_hex tx[7]
|
|
139
139
|
s = Util.bin_to_hex tx[8]
|
|
140
140
|
|
|
141
141
|
# try to recover the chain id from v
|
|
142
|
-
chain_id = Chain.to_chain_id Util.
|
|
142
|
+
chain_id = Chain.to_chain_id Util.deserialize_rlp_int tx[6]
|
|
143
143
|
|
|
144
144
|
# populate class attributes
|
|
145
145
|
@signer_nonce = nonce.to_i
|
|
@@ -223,6 +223,30 @@ module Eth
|
|
|
223
223
|
return hash
|
|
224
224
|
end
|
|
225
225
|
|
|
226
|
+
# Signs the transaction with a provided signature blob.
|
|
227
|
+
#
|
|
228
|
+
# @param signature [String] the concatenated `r`, `s`, and `v` values.
|
|
229
|
+
# @return [String] a transaction hash.
|
|
230
|
+
# @raise [Signature::SignatureError] if transaction is already signed.
|
|
231
|
+
# @raise [Signature::SignatureError] if sender address does not match signer.
|
|
232
|
+
def sign_with(signature)
|
|
233
|
+
if Tx.signed? self
|
|
234
|
+
raise Signature::SignatureError, "Transaction is already signed!"
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# ensure the sender address matches the signature
|
|
238
|
+
unless @sender.nil? or sender.empty?
|
|
239
|
+
public_key = Signature.recover(unsigned_hash, signature, @chain_id)
|
|
240
|
+
signer_address = Tx.sanitize_address Util.public_key_to_address(public_key).to_s
|
|
241
|
+
from_address = Tx.sanitize_address @sender
|
|
242
|
+
raise Signature::SignatureError, "Signer does not match sender" unless signer_address == from_address
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
r, s, v = Signature.dissect signature
|
|
246
|
+
send :_set_signature, v, r, s
|
|
247
|
+
return hash
|
|
248
|
+
end
|
|
249
|
+
|
|
226
250
|
# Encodes a raw transaction object.
|
|
227
251
|
#
|
|
228
252
|
# @return [String] a raw, RLP-encoded legacy transaction.
|
data/lib/eth/tx.rb
CHANGED
|
@@ -17,6 +17,7 @@ require "konstructor"
|
|
|
17
17
|
require "eth/chain"
|
|
18
18
|
require "eth/tx/eip1559"
|
|
19
19
|
require "eth/tx/eip2930"
|
|
20
|
+
require "eth/tx/eip4844"
|
|
20
21
|
require "eth/tx/eip7702"
|
|
21
22
|
require "eth/tx/legacy"
|
|
22
23
|
require "eth/unit"
|
|
@@ -87,6 +88,8 @@ module Eth
|
|
|
87
88
|
|
|
88
89
|
# Creates a new transaction of any type for given parameters and chain ID.
|
|
89
90
|
# Required parameters are (optional in brackets):
|
|
91
|
+
# - EIP-4844: chain_id, nonce, priority_fee, max_gas_fee, gas_limit, max_fee_per_blob_gas, blob_versioned_hashes(, from, to,
|
|
92
|
+
# value, data, access_list)
|
|
90
93
|
# - EIP-1559: chain_id, nonce, priority_fee, max_gas_fee, gas_limit(, from, to,
|
|
91
94
|
# value, data, access_list)
|
|
92
95
|
# - EIP-2930: chain_id, nonce, gas_price, gas_limit, access_list(, from, to,
|
|
@@ -99,9 +102,10 @@ module Eth
|
|
|
99
102
|
# @param chain_id [Integer] the EIP-155 Chain ID (legacy transactions only).
|
|
100
103
|
def new(params, chain_id = Chain::ETHEREUM)
|
|
101
104
|
|
|
102
|
-
# if we deal with blobs, attempt EIP-4844
|
|
105
|
+
# if we deal with blobs, attempt EIP-4844
|
|
103
106
|
unless params[:max_fee_per_blob_gas].nil?
|
|
104
|
-
|
|
107
|
+
params[:chain_id] = chain_id if params[:chain_id].nil?
|
|
108
|
+
return Tx::Eip4844.new params
|
|
105
109
|
end
|
|
106
110
|
|
|
107
111
|
# if we deal with authorizations, attempt EIP-7702
|
|
@@ -148,7 +152,7 @@ module Eth
|
|
|
148
152
|
when TYPE_4844
|
|
149
153
|
|
|
150
154
|
# EIP-4844 transaction (type 3)
|
|
151
|
-
|
|
155
|
+
return Tx::Eip4844.decode hex
|
|
152
156
|
when TYPE_7702
|
|
153
157
|
|
|
154
158
|
# EIP-7702 transaction (type 4)
|
|
@@ -182,7 +186,7 @@ module Eth
|
|
|
182
186
|
when TYPE_4844
|
|
183
187
|
|
|
184
188
|
# EIP-4844 transaction (type 3)
|
|
185
|
-
|
|
189
|
+
return Tx::Eip4844.unsigned_copy tx
|
|
186
190
|
when TYPE_7702
|
|
187
191
|
|
|
188
192
|
# EIP-7702 transaction (type 4)
|
|
@@ -278,6 +282,27 @@ module Eth
|
|
|
278
282
|
return fields
|
|
279
283
|
end
|
|
280
284
|
|
|
285
|
+
# Validates that the type-3 transaction blob fields are present
|
|
286
|
+
#
|
|
287
|
+
# @param fields [Hash] the transaction fields.
|
|
288
|
+
# @return [Hash] the validated transaction fields.
|
|
289
|
+
# @raise [ParameterError] if max blob fee or blob hashes are invalid or exceed limits.
|
|
290
|
+
def validate_eip4844_params(fields)
|
|
291
|
+
if fields[:max_fee_per_blob_gas].nil? or fields[:max_fee_per_blob_gas] < 0
|
|
292
|
+
raise ParameterError, "Invalid max blob fee #{fields[:max_fee_per_blob_gas]}!"
|
|
293
|
+
end
|
|
294
|
+
if fields[:blob_versioned_hashes].nil? or !fields[:blob_versioned_hashes].is_a? Array or fields[:blob_versioned_hashes].empty?
|
|
295
|
+
raise ParameterError, "Invalid blob versioned hashes #{fields[:blob_versioned_hashes]}!"
|
|
296
|
+
end
|
|
297
|
+
if fields[:blob_versioned_hashes].length > Eip4844::MAX_BLOBS_PER_BLOCK
|
|
298
|
+
raise ParameterError, "Too many blob versioned hashes #{fields[:blob_versioned_hashes].length}!"
|
|
299
|
+
end
|
|
300
|
+
if fields[:to].nil? or fields[:to].empty?
|
|
301
|
+
raise ParameterError, "Invalid destination address #{fields[:to]}!"
|
|
302
|
+
end
|
|
303
|
+
return fields
|
|
304
|
+
end
|
|
305
|
+
|
|
281
306
|
# Validates that the type-4 transaction field authorization list is present
|
|
282
307
|
#
|
|
283
308
|
# @param fields [Hash] the transaction fields.
|
|
@@ -372,6 +397,22 @@ module Eth
|
|
|
372
397
|
return list
|
|
373
398
|
end
|
|
374
399
|
|
|
400
|
+
# Populates the blob versioned hashes field with a serializable empty
|
|
401
|
+
# array in case it is undefined; also ensures the hashes are binary
|
|
402
|
+
# not hex.
|
|
403
|
+
#
|
|
404
|
+
# @param list [Array] the blob versioned hashes.
|
|
405
|
+
# @return [Array] the sanitized blob versioned hashes.
|
|
406
|
+
def sanitize_hashes(list)
|
|
407
|
+
list = [] if list.nil?
|
|
408
|
+
list.each_with_index do |value, index|
|
|
409
|
+
if Util.hex? value
|
|
410
|
+
list[index] = Util.hex_to_bin value
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
return list
|
|
414
|
+
end
|
|
415
|
+
|
|
375
416
|
# Allows to check wether a transaction is signed already.
|
|
376
417
|
#
|
|
377
418
|
# @return [Bool] true if transaction is already signed.
|
data/lib/eth/util.rb
CHANGED
|
@@ -72,8 +72,7 @@ module Eth
|
|
|
72
72
|
# @param hex [String] a hex-string to be prefixed.
|
|
73
73
|
# @return [String] a prefixed hex-string.
|
|
74
74
|
def prefix_hex(hex)
|
|
75
|
-
|
|
76
|
-
return "0x#{hex}"
|
|
75
|
+
"0x#{remove_hex_prefix hex}"
|
|
77
76
|
end
|
|
78
77
|
|
|
79
78
|
# Removes the `0x` prefix of a hexa-decimal string.
|
|
@@ -93,12 +92,12 @@ module Eth
|
|
|
93
92
|
prefix_hex bin_to_hex bin
|
|
94
93
|
end
|
|
95
94
|
|
|
96
|
-
# Checks if a string is
|
|
95
|
+
# Checks if a string is hexadecimal.
|
|
97
96
|
#
|
|
98
97
|
# @param str [String] a string to be checked.
|
|
99
|
-
# @return [
|
|
98
|
+
# @return [MatchData, nil] a match if true; `nil` if not.
|
|
100
99
|
def hex?(str)
|
|
101
|
-
return
|
|
100
|
+
return unless str.is_a? String
|
|
102
101
|
str = remove_hex_prefix str
|
|
103
102
|
str.match /\A[0-9a-fA-F]*\z/
|
|
104
103
|
end
|
|
@@ -108,7 +107,7 @@ module Eth
|
|
|
108
107
|
# @param hex [String] a string to be checked.
|
|
109
108
|
# @return [String] a match if true; `nil` if not.
|
|
110
109
|
def prefixed?(hex)
|
|
111
|
-
hex.match /\A0x/
|
|
110
|
+
hex.match /\A0x/i
|
|
112
111
|
end
|
|
113
112
|
|
|
114
113
|
# Serializes an unsigned integer to big endian.
|
|
@@ -129,7 +128,11 @@ module Eth
|
|
|
129
128
|
# @param num [Integer] integer to be converted.
|
|
130
129
|
# @return [String] packed, big-endian integer string.
|
|
131
130
|
def int_to_big_endian(num)
|
|
132
|
-
hex =
|
|
131
|
+
hex = if hex? num
|
|
132
|
+
remove_hex_prefix num
|
|
133
|
+
else
|
|
134
|
+
num.to_s(16)
|
|
135
|
+
end
|
|
133
136
|
hex = "0#{hex}" if hex.size.odd?
|
|
134
137
|
hex_to_bin hex
|
|
135
138
|
end
|
|
@@ -142,6 +145,15 @@ module Eth
|
|
|
142
145
|
Rlp::Sedes.big_endian_int.deserialize str.sub(/\A(\x00)+/, "")
|
|
143
146
|
end
|
|
144
147
|
|
|
148
|
+
# Deserializes an RLP integer, enforcing minimal encoding.
|
|
149
|
+
#
|
|
150
|
+
# @param str [String] serialized big endian integer string.
|
|
151
|
+
# @return [Integer] a deserialized unsigned integer.
|
|
152
|
+
# @raise [Rlp::DeserializationError] if encoding is not minimal.
|
|
153
|
+
def deserialize_rlp_int(str)
|
|
154
|
+
Rlp::Sedes.big_endian_int.deserialize str
|
|
155
|
+
end
|
|
156
|
+
|
|
145
157
|
# Converts a big endian to an interger.
|
|
146
158
|
#
|
|
147
159
|
# @param str [String] big endian to be converted.
|
data/lib/eth/version.rb
CHANGED
data/lib/eth.rb
CHANGED
metadata
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: eth
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.16
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Steve Ellis
|
|
8
8
|
- Afri Schoedon
|
|
9
|
-
autorequire:
|
|
10
9
|
bindir: exe
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: bigdecimal
|
|
@@ -85,22 +84,30 @@ dependencies:
|
|
|
85
84
|
name: openssl
|
|
86
85
|
requirement: !ruby/object:Gem::Requirement
|
|
87
86
|
requirements:
|
|
88
|
-
- - "
|
|
89
|
-
- !ruby/object:Gem::Version
|
|
90
|
-
version: '2.2'
|
|
91
|
-
- - "<"
|
|
87
|
+
- - "~>"
|
|
92
88
|
- !ruby/object:Gem::Version
|
|
93
|
-
version: '
|
|
89
|
+
version: '3.3'
|
|
94
90
|
type: :runtime
|
|
95
91
|
prerelease: false
|
|
96
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
97
93
|
requirements:
|
|
98
|
-
- - "
|
|
94
|
+
- - "~>"
|
|
99
95
|
- !ruby/object:Gem::Version
|
|
100
|
-
version: '
|
|
101
|
-
|
|
96
|
+
version: '3.3'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: base64
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0.1'
|
|
104
|
+
type: :runtime
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
102
109
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: '
|
|
110
|
+
version: '0.1'
|
|
104
111
|
- !ruby/object:Gem::Dependency
|
|
105
112
|
name: scrypt
|
|
106
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -115,6 +122,34 @@ dependencies:
|
|
|
115
122
|
- - "~>"
|
|
116
123
|
- !ruby/object:Gem::Version
|
|
117
124
|
version: '3.0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: bls12-381
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0.3'
|
|
132
|
+
type: :runtime
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - "~>"
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0.3'
|
|
139
|
+
- !ruby/object:Gem::Dependency
|
|
140
|
+
name: httpx
|
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - "~>"
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '1.6'
|
|
146
|
+
type: :runtime
|
|
147
|
+
prerelease: false
|
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
+
requirements:
|
|
150
|
+
- - "~>"
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '1.6'
|
|
118
153
|
description: Library to handle Ethereum accounts, messages, and transactions.
|
|
119
154
|
email:
|
|
120
155
|
- email@steveell.is
|
|
@@ -151,16 +186,20 @@ files:
|
|
|
151
186
|
- lib/eth/abi/decoder.rb
|
|
152
187
|
- lib/eth/abi/encoder.rb
|
|
153
188
|
- lib/eth/abi/event.rb
|
|
189
|
+
- lib/eth/abi/function.rb
|
|
154
190
|
- lib/eth/abi/packed/encoder.rb
|
|
155
191
|
- lib/eth/abi/type.rb
|
|
156
192
|
- lib/eth/address.rb
|
|
157
193
|
- lib/eth/api.rb
|
|
194
|
+
- lib/eth/bls.rb
|
|
158
195
|
- lib/eth/chain.rb
|
|
159
196
|
- lib/eth/client.rb
|
|
160
197
|
- lib/eth/client/http.rb
|
|
161
198
|
- lib/eth/client/ipc.rb
|
|
199
|
+
- lib/eth/client/ws.rb
|
|
162
200
|
- lib/eth/constant.rb
|
|
163
201
|
- lib/eth/contract.rb
|
|
202
|
+
- lib/eth/contract/error.rb
|
|
164
203
|
- lib/eth/contract/event.rb
|
|
165
204
|
- lib/eth/contract/function.rb
|
|
166
205
|
- lib/eth/contract/function_input.rb
|
|
@@ -185,6 +224,7 @@ files:
|
|
|
185
224
|
- lib/eth/tx.rb
|
|
186
225
|
- lib/eth/tx/eip1559.rb
|
|
187
226
|
- lib/eth/tx/eip2930.rb
|
|
227
|
+
- lib/eth/tx/eip4844.rb
|
|
188
228
|
- lib/eth/tx/eip7702.rb
|
|
189
229
|
- lib/eth/tx/legacy.rb
|
|
190
230
|
- lib/eth/unit.rb
|
|
@@ -199,7 +239,6 @@ metadata:
|
|
|
199
239
|
documentation_uri: https://q9f.github.io/eth.rb/
|
|
200
240
|
github_repo: https://github.com/q9f/eth.rb
|
|
201
241
|
source_code_uri: https://github.com/q9f/eth.rb
|
|
202
|
-
post_install_message:
|
|
203
242
|
rdoc_options: []
|
|
204
243
|
require_paths:
|
|
205
244
|
- lib
|
|
@@ -218,8 +257,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
218
257
|
- !ruby/object:Gem::Version
|
|
219
258
|
version: '0'
|
|
220
259
|
requirements: []
|
|
221
|
-
rubygems_version: 3.
|
|
222
|
-
signing_key:
|
|
260
|
+
rubygems_version: 3.6.9
|
|
223
261
|
specification_version: 4
|
|
224
262
|
summary: Ruby Ethereum library.
|
|
225
263
|
test_files: []
|