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