abi_coder_rb 0.2.7 → 0.2.8
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/Gemfile.lock +1 -1
- data/lib/abi_coder_rb/encode/encode_array.rb +13 -4
- data/lib/abi_coder_rb/encode/encode_fixed_array.rb +2 -13
- data/lib/abi_coder_rb/encode/encode_primitive_type.rb +58 -35
- data/lib/abi_coder_rb/encode/encode_tuple.rb +10 -8
- data/lib/abi_coder_rb/encode.rb +23 -10
- data/lib/abi_coder_rb/utils.rb +15 -4
- data/lib/abi_coder_rb/version.rb +1 -1
- data/tea.yaml +6 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2446e20c68206c39fddd2cc887136d0188a74283c82240f95d9fd3d7fce19d15
|
4
|
+
data.tar.gz: '0158a5505f945dc0655a1c80cf8722ff4d15610bf2e027fea15cd21de917aa1c'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 26d7209d606865c01c539a3e5611e25477ce8ba3f2f1e9e54eb0c879ac510ca047979c066905a430fceab5f23f18b8c680b594341834a900d03e983d2241be03
|
7
|
+
data.tar.gz: cac0312067c262e52808ff92b7b36e9a85e87660e306f1e13205a19eb1107bb1a9fb423b2fd6641949c0e4e130b3bb20adb114c1d0fa83f00b5e81923173b2b3
|
data/Gemfile.lock
CHANGED
@@ -1,16 +1,25 @@
|
|
1
1
|
module AbiCoderRb
|
2
|
-
def encode_array(type, args)
|
2
|
+
def encode_array(type, args, packed = false)
|
3
3
|
raise ArgumentError, "arg must be an array" unless args.is_a?(::Array)
|
4
4
|
|
5
|
+
_encode_array(type: type, args: args, packed: packed)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def _encode_array(type:, args:, packed: false)
|
5
11
|
head = "".b
|
6
|
-
tail = "".b
|
12
|
+
tail = "".b
|
7
13
|
|
8
|
-
|
14
|
+
# 数组长度
|
15
|
+
head += encode_uint256(args.size) if type.is_a?(Array) && !packed
|
9
16
|
|
10
17
|
subtype = type.subtype
|
11
18
|
args.each do |arg|
|
12
19
|
if subtype.dynamic?
|
13
|
-
|
20
|
+
raise "#{type.class} with dynamic inner type is not supported in packed mode" if packed
|
21
|
+
|
22
|
+
head += encode_uint256(32 * args.size + tail.size) # 当前数据的位置指针
|
14
23
|
tail += encode_type(subtype, arg)
|
15
24
|
else
|
16
25
|
head += encode_type(subtype, arg)
|
@@ -1,22 +1,11 @@
|
|
1
1
|
module AbiCoderRb
|
2
|
-
def encode_fixed_array(type, args)
|
2
|
+
def encode_fixed_array(type, args, packed = false)
|
3
3
|
raise ArgumentError, "arg must be an array" unless args.is_a?(::Array)
|
4
4
|
raise ArgumentError, "Wrong array size: found #{args.size}, expecting #{type.dim}" unless args.size == type.dim
|
5
5
|
|
6
6
|
# fixed_array,是没有元素数量的编码de
|
7
7
|
# 如果内部类型是静态的,就是一个一个元素编码后加起来。
|
8
8
|
# 如果内部类型是动态的,先用位置一个一个编码加起来,然后是元素本体
|
9
|
-
|
10
|
-
if subtype.dynamic?
|
11
|
-
head = "".b
|
12
|
-
tail = "".b
|
13
|
-
args.each do |arg|
|
14
|
-
head += encode_uint256(32 * args.size + tail.size)
|
15
|
-
tail += encode_type(subtype, arg)
|
16
|
-
end
|
17
|
-
head + tail
|
18
|
-
else
|
19
|
-
args.map { |arg| encode_type(type.subtype, arg) }.join
|
20
|
-
end
|
9
|
+
_encode_array(type: type, args: args, packed: packed)
|
21
10
|
end
|
22
11
|
end
|
@@ -1,55 +1,67 @@
|
|
1
1
|
module AbiCoderRb
|
2
|
-
def encode_primitive_type(type, arg)
|
2
|
+
def encode_primitive_type(type, arg, packed = false)
|
3
3
|
arg = before_encoding_action.call(type.format, arg) if before_encoding_action
|
4
4
|
# 根据类型选择相应的编码方法
|
5
5
|
case type
|
6
6
|
when Uint
|
7
7
|
# NOTE: for now size in bits always required
|
8
|
-
encode_uint(arg, type.bits)
|
8
|
+
encode_uint(arg, type.bits, packed)
|
9
9
|
when Int
|
10
10
|
# NOTE: for now size in bits always required
|
11
|
-
encode_int(arg, type.bits)
|
11
|
+
encode_int(arg, type.bits, packed)
|
12
12
|
when Bool
|
13
|
-
encode_bool(arg)
|
13
|
+
encode_bool(arg, packed)
|
14
14
|
when String
|
15
|
-
encode_string(arg)
|
15
|
+
encode_string(arg, packed)
|
16
16
|
when FixedBytes
|
17
|
-
encode_bytes(arg, type.length)
|
17
|
+
encode_bytes(arg, length: type.length, packed: packed)
|
18
18
|
when Bytes
|
19
|
-
encode_bytes(arg)
|
19
|
+
encode_bytes(arg, packed: packed)
|
20
20
|
when Address
|
21
|
-
encode_address(arg)
|
21
|
+
encode_address(arg, packed)
|
22
22
|
else
|
23
23
|
raise EncodingError, "Unknown type: #{type}"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def encode_uint(arg, bits)
|
27
|
+
def encode_uint(arg, bits, packed = false)
|
28
28
|
raise ArgumentError, "arg is not integer: #{arg}" unless arg.is_a?(Integer)
|
29
29
|
raise ValueOutOfBounds, arg unless arg >= 0 && arg < 2**bits
|
30
30
|
|
31
|
-
|
31
|
+
if packed
|
32
|
+
lpad_int(arg, bits / 8)
|
33
|
+
else
|
34
|
+
lpad_int(arg)
|
35
|
+
end
|
32
36
|
end
|
33
37
|
|
34
38
|
def encode_uint256(arg)
|
35
39
|
encode_uint(arg, 256)
|
36
40
|
end
|
37
41
|
|
38
|
-
def encode_int(arg,
|
42
|
+
def encode_int(arg, bits, packed = false)
|
39
43
|
## raise EncodingError or ArgumentError - why? why not?
|
40
44
|
raise ArgumentError, "arg is not integer: #{arg}" unless arg.is_a?(Integer)
|
41
45
|
|
42
|
-
|
46
|
+
if packed
|
47
|
+
hex_to_bin(int_to_abi_signed(arg, bits))
|
48
|
+
else
|
49
|
+
hex_to_bin(int_to_abi_signed_256bit(arg))
|
50
|
+
end
|
43
51
|
end
|
44
52
|
|
45
|
-
def encode_bool(arg)
|
53
|
+
def encode_bool(arg, packed = false)
|
46
54
|
## raise EncodingError or ArgumentError - why? why not?
|
47
55
|
raise ArgumentError, "arg is not bool: #{arg}" unless arg.is_a?(TrueClass) || arg.is_a?(FalseClass)
|
48
56
|
|
49
|
-
|
57
|
+
if packed
|
58
|
+
arg ? BYTE_ONE : BYTE_ZERO
|
59
|
+
else
|
60
|
+
lpad(arg ? BYTE_ONE : BYTE_ZERO) ## was lpad_int( arg ? 1 : 0 )
|
61
|
+
end
|
50
62
|
end
|
51
63
|
|
52
|
-
def encode_string(arg)
|
64
|
+
def encode_string(arg, packed = false)
|
53
65
|
## raise EncodingError or ArgumentError - why? why not?
|
54
66
|
raise EncodingError, "Expecting string: #{arg}" unless arg.is_a?(::String)
|
55
67
|
|
@@ -57,12 +69,16 @@ module AbiCoderRb
|
|
57
69
|
|
58
70
|
raise ValueOutOfBounds, "Integer invalid or out of range: #{arg.size}" if arg.size > UINT_MAX
|
59
71
|
|
60
|
-
|
61
|
-
|
62
|
-
|
72
|
+
if packed
|
73
|
+
arg
|
74
|
+
else
|
75
|
+
size = lpad_int(arg.size)
|
76
|
+
value = rpad(arg, ceil32(arg.size))
|
77
|
+
size + value
|
78
|
+
end
|
63
79
|
end
|
64
80
|
|
65
|
-
def encode_bytes(arg, length
|
81
|
+
def encode_bytes(arg, length: nil, packed: false)
|
66
82
|
## raise EncodingError or ArgumentError - why? why not?
|
67
83
|
raise EncodingError, "Expecting string: #{arg}" unless arg.is_a?(::String)
|
68
84
|
|
@@ -72,29 +88,36 @@ module AbiCoderRb
|
|
72
88
|
raise ValueOutOfBounds, "invalid bytes length #{arg.size}, should be #{length}" if arg.size > length
|
73
89
|
raise ValueOutOfBounds, "invalid bytes length #{length}" if length < 0 || length > 32
|
74
90
|
|
75
|
-
rpad(arg)
|
91
|
+
packed ? arg : rpad(arg)
|
76
92
|
else # variable length type (if length is nil)
|
77
93
|
raise ValueOutOfBounds, "Integer invalid or out of range: #{arg.size}" if arg.size > UINT_MAX
|
78
94
|
|
79
|
-
|
80
|
-
|
81
|
-
|
95
|
+
if packed
|
96
|
+
arg
|
97
|
+
else
|
98
|
+
size = lpad_int(arg.size)
|
99
|
+
value = rpad(arg, ceil32(arg.size))
|
100
|
+
size + value
|
101
|
+
end
|
82
102
|
end
|
83
103
|
end
|
84
104
|
|
85
|
-
def encode_address(arg)
|
105
|
+
def encode_address(arg, packed = false)
|
86
106
|
if arg.is_a?(Integer)
|
87
|
-
lpad_int(arg)
|
88
|
-
elsif arg.
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
107
|
+
packed ? lpad_int(arg, 20) : lpad_int(arg)
|
108
|
+
elsif arg.is_a?(::String)
|
109
|
+
if arg.size == 20
|
110
|
+
## note: make sure encoding is always binary!!!
|
111
|
+
arg = arg.b if arg.encoding != Encoding::BINARY
|
112
|
+
packed ? arg : lpad(arg)
|
113
|
+
elsif arg.size == 40
|
114
|
+
packed ? hex_to_bin(arg) : lpad_hex(arg)
|
115
|
+
elsif arg.size == 42 && arg[0, 2] == "0x" ## todo/fix: allow 0X too - why? why not?
|
116
|
+
arg = arg[2..-1] ## cut-off leading 0x
|
117
|
+
packed ? hex_to_bin(arg) : lpad_hex(arg)
|
118
|
+
else
|
119
|
+
raise EncodingError, "Could not parse address: #{arg}"
|
120
|
+
end
|
98
121
|
end
|
99
122
|
end
|
100
123
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
module AbiCoderRb
|
2
|
-
def encode_tuple(tuple, args)
|
3
|
-
|
2
|
+
def encode_tuple(tuple, args, packed = false)
|
3
|
+
raise "#{tuple.class} with multi inner types is not supported in packed mode" if packed && tuple.types.size > 1
|
4
|
+
|
5
|
+
encode_types(tuple.types, args, packed)
|
4
6
|
end
|
5
7
|
|
6
8
|
private
|
7
9
|
|
8
|
-
def encode_types(types, args)
|
10
|
+
def encode_types(types, args, packed = false)
|
9
11
|
raise ArgumentError, "args must be an array" unless args.is_a?(::Array)
|
10
12
|
|
11
13
|
unless args.size == types.size
|
@@ -17,18 +19,18 @@ module AbiCoderRb
|
|
17
19
|
head_size = types.map { |type| type.size || 32 }.sum
|
18
20
|
|
19
21
|
# 初始化头部和尾部
|
20
|
-
head = "".b
|
22
|
+
head = "".b # 如果是动态类型,头部是指针;如果是静态类型,头部是数据
|
21
23
|
tail = "".b # 使用二进制字符串
|
22
24
|
|
23
25
|
# 遍历类型并编码
|
24
26
|
types.each_with_index do |type, i|
|
25
|
-
if type.dynamic?
|
27
|
+
if !type.dynamic? || packed
|
28
|
+
# 只更新头部,也就是数据
|
29
|
+
head += encode_type(type, args[i], packed)
|
30
|
+
else
|
26
31
|
# 动态类型: 更新头部和尾部
|
27
32
|
head += encode_uint256(head_size + tail.size)
|
28
33
|
tail += encode_type(type, args[i])
|
29
|
-
else
|
30
|
-
# 静态类型: 只更新头部
|
31
|
-
head += encode_type(type, args[i])
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
data/lib/abi_coder_rb/encode.rb
CHANGED
@@ -5,25 +5,38 @@ require_relative "encode/encode_primitive_type"
|
|
5
5
|
|
6
6
|
module AbiCoderRb
|
7
7
|
# returns byte array
|
8
|
-
def encode(
|
9
|
-
|
10
|
-
|
8
|
+
def encode(typestr_or_typestrs, value_or_values, packed = false)
|
9
|
+
if typestr_or_typestrs.is_a?(::Array)
|
10
|
+
raise EncodingError, "values should be an array" unless value_or_values.is_a?(::Array)
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
typestrs = typestr_or_typestrs
|
13
|
+
values = value_or_values
|
14
|
+
typestrs.map.with_index do |typestr, i|
|
15
|
+
value = values[i]
|
16
|
+
encode(typestr, value, packed)
|
17
|
+
end.join
|
18
|
+
else
|
19
|
+
typestr = typestr_or_typestrs
|
20
|
+
value = value_or_values
|
21
|
+
# TODO: more checks?
|
22
|
+
raise EncodingError, "Value can not be nil" if value.nil?
|
23
|
+
|
24
|
+
parsed = Type.parse(typestr)
|
25
|
+
encode_type(parsed, value, packed)
|
26
|
+
end
|
14
27
|
end
|
15
28
|
|
16
29
|
private
|
17
30
|
|
18
|
-
def encode_type(type, value)
|
31
|
+
def encode_type(type, value, packed = false)
|
19
32
|
if type.is_a?(Tuple)
|
20
|
-
encode_tuple(type, value)
|
33
|
+
encode_tuple(type, value, packed)
|
21
34
|
elsif type.is_a?(Array)
|
22
|
-
encode_array(type, value)
|
35
|
+
encode_array(type, value, packed)
|
23
36
|
elsif type.is_a?(FixedArray)
|
24
|
-
encode_fixed_array(type, value)
|
37
|
+
encode_fixed_array(type, value, packed)
|
25
38
|
else
|
26
|
-
encode_primitive_type(type, value)
|
39
|
+
encode_primitive_type(type, value, packed)
|
27
40
|
end
|
28
41
|
end
|
29
42
|
end
|
data/lib/abi_coder_rb/utils.rb
CHANGED
@@ -27,15 +27,14 @@ module AbiCoderRb
|
|
27
27
|
## rename to lpad32 or such - why? why not?
|
28
28
|
# example:
|
29
29
|
# lpad("hello", 'x', 10) => "xxxxxxhello"
|
30
|
-
def lpad(bin) ## note: same as builtin String#rjust !!!
|
31
|
-
l = 32 # NOTE: default l word is 32 bytes
|
30
|
+
def lpad(bin, l = 32) ## note: same as builtin String#rjust !!!
|
32
31
|
return bin if bin.size >= l
|
33
32
|
|
34
33
|
BYTE_ZERO * (l - bin.size) + bin
|
35
34
|
end
|
36
35
|
|
37
36
|
## rename to lpad32_int or such - why? why not?
|
38
|
-
def lpad_int(n)
|
37
|
+
def lpad_int(n, l = 32)
|
39
38
|
unless n.is_a?(Integer) && n >= 0 && n <= UINT_MAX
|
40
39
|
raise ArgumentError,
|
41
40
|
"Integer invalid or out of range: #{n}"
|
@@ -45,7 +44,7 @@ module AbiCoderRb
|
|
45
44
|
hex = "0#{hex}" if hex.length.odd? # wasm, no .odd?
|
46
45
|
bin = hex_to_bin(hex)
|
47
46
|
|
48
|
-
lpad(bin)
|
47
|
+
lpad(bin, l)
|
49
48
|
end
|
50
49
|
|
51
50
|
## rename to lpad32_hex or such - why? why not?
|
@@ -62,6 +61,18 @@ module AbiCoderRb
|
|
62
61
|
x % 32 == 0 ? x : (x + 32 - x % 32)
|
63
62
|
end
|
64
63
|
|
64
|
+
def int_to_abi_signed(value, bits)
|
65
|
+
min = -2**(bits - 1)
|
66
|
+
max = 2**(bits - 1) - 1
|
67
|
+
raise "Value out of range" if value < min || value > max
|
68
|
+
|
69
|
+
value = (1 << bits) + value if value < 0
|
70
|
+
|
71
|
+
hex_str = value.to_s(16)
|
72
|
+
|
73
|
+
hex_str.rjust(bits / 4, "0")
|
74
|
+
end
|
75
|
+
|
65
76
|
def int_to_abi_signed_256bit(value)
|
66
77
|
# 确保值在256位有符号整数范围内
|
67
78
|
min = -2**255
|
data/lib/abi_coder_rb/version.rb
CHANGED
data/tea.yaml
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abi_coder_rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aki Wu
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- lib/abi_coder_rb/version.rb
|
75
75
|
- lib/periphery/event_decoder.rb
|
76
76
|
- sig/abi_coder_rb.rbs
|
77
|
+
- tea.yaml
|
77
78
|
homepage: https://github.com/wuminzhe/abi_coder_rb
|
78
79
|
licenses:
|
79
80
|
- MIT
|