abi_coder_rb 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.DS_Store +0 -0
- data/Gemfile.lock +3 -1
- data/README.md +60 -2
- data/flatten.rb +8 -0
- data/flattened_abi_coder.rb +669 -0
- data/lib/.DS_Store +0 -0
- data/lib/abi_coder_rb/decode/decode_array.rb +6 -6
- data/lib/abi_coder_rb/decode/decode_primitive_type.rb +27 -22
- data/lib/abi_coder_rb/decode/decode_tuple.rb +29 -0
- data/lib/abi_coder_rb/decode.rb +3 -33
- data/lib/abi_coder_rb/encode/encode_fixed_array.rb +15 -1
- data/lib/abi_coder_rb/encode/encode_primitive_type.rb +20 -8
- data/lib/abi_coder_rb/encode/encode_tuple.rb +32 -0
- data/lib/abi_coder_rb/encode.rb +13 -43
- data/lib/abi_coder_rb/parser.rb +8 -1
- data/lib/abi_coder_rb/types.rb +10 -3
- data/lib/abi_coder_rb/utils.rb +111 -0
- data/lib/abi_coder_rb/version.rb +1 -1
- data/lib/abi_coder_rb.rb +20 -12
- metadata +20 -3
@@ -1,26 +1,30 @@
|
|
1
1
|
module AbiCoderRb
|
2
2
|
def decode_primitive_type(type, data)
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
3
|
+
result =
|
4
|
+
case type
|
5
|
+
when Uint
|
6
|
+
decode_uint256(data[0, 32])
|
7
|
+
when Int
|
8
|
+
Utils.abi_to_int_signed(bin_to_hex(data[0, 32]), type.bits)
|
9
|
+
when Bool
|
10
|
+
data[31] == BYTE_ONE
|
11
|
+
when String
|
12
|
+
size = decode_uint256(data[0, 32])
|
13
|
+
data[32...(32 + size)].force_encoding("UTF-8")
|
14
|
+
when Bytes
|
15
|
+
size = decode_uint256(data[0, 32])
|
16
|
+
data[32...(32 + size)]
|
17
|
+
when FixedBytes
|
18
|
+
data[0, type.length]
|
19
|
+
when Address
|
20
|
+
bin_to_hex(data[12...32]).force_encoding("UTF-8")
|
21
|
+
else
|
22
|
+
raise DecodingError, "Unknown primitive type: #{type.class.name} #{type.format}"
|
23
|
+
end
|
24
|
+
|
25
|
+
result = after_decoding_action.call(type.format, result) if after_decoding_action
|
26
|
+
|
27
|
+
result
|
24
28
|
end
|
25
29
|
|
26
30
|
private
|
@@ -30,6 +34,7 @@ module AbiCoderRb
|
|
30
34
|
### todo/check - allow nil - why? why not?
|
31
35
|
## raise DeserializationError, "Invalid serialization (not minimal length)" if !@size && serial.size > 0 && serial[0] == BYTE_ZERO
|
32
36
|
# bin = bin || BYTE_ZERO
|
33
|
-
bin
|
37
|
+
bin_to_hex(bin).to_i(16)
|
38
|
+
# bin.bytes.reduce { |acc, byte| (acc << 8) + byte }
|
34
39
|
end
|
35
40
|
end
|
@@ -2,4 +2,33 @@ module AbiCoderRb
|
|
2
2
|
def decode_tuple(type, data)
|
3
3
|
decode_types(type.types, data)
|
4
4
|
end
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def decode_types(types, data)
|
9
|
+
start_positions = start_positions(types, data)
|
10
|
+
|
11
|
+
types.map.with_index do |type, index|
|
12
|
+
start_position = start_positions[index]
|
13
|
+
decode_type(type, data[start_position..])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def start_positions(types, data)
|
18
|
+
start_positions = ::Array.new(types.size)
|
19
|
+
offset = 0
|
20
|
+
|
21
|
+
types.each_with_index do |type, index|
|
22
|
+
if type.dynamic?
|
23
|
+
# 读取动态类型的偏移量
|
24
|
+
start_positions[index] = decode_uint256(data[offset, 32])
|
25
|
+
offset += 32
|
26
|
+
else
|
27
|
+
start_positions[index] = offset
|
28
|
+
offset += type.size
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
start_positions
|
33
|
+
end
|
5
34
|
end
|
data/lib/abi_coder_rb/decode.rb
CHANGED
@@ -4,18 +4,15 @@ require_relative "decode/decode_array"
|
|
4
4
|
require_relative "decode/decode_primitive_type"
|
5
5
|
|
6
6
|
module AbiCoderRb
|
7
|
-
def decode(
|
8
|
-
|
9
|
-
types = types.map { |type| type.is_a?(Type) ? type : Type.parse(type) }
|
7
|
+
def decode(type_str, data)
|
8
|
+
raise DecodingError, "Empty data" if data.nil? || data.empty?
|
10
9
|
|
11
|
-
|
10
|
+
decode_type(Type.parse(type_str), data)
|
12
11
|
end
|
13
12
|
|
14
13
|
private
|
15
14
|
|
16
15
|
def decode_type(type, data)
|
17
|
-
return nil if data.nil? || data.empty?
|
18
|
-
|
19
16
|
case type
|
20
17
|
when Tuple ## todo: support empty (unit) tuple - why? why not?
|
21
18
|
decode_tuple(type, data)
|
@@ -27,31 +24,4 @@ module AbiCoderRb
|
|
27
24
|
decode_primitive_type(type, data)
|
28
25
|
end
|
29
26
|
end
|
30
|
-
|
31
|
-
def decode_types(types, data)
|
32
|
-
start_positions = start_positions(types, data)
|
33
|
-
|
34
|
-
types.map.with_index do |type, index|
|
35
|
-
start_position = start_positions[index]
|
36
|
-
decode_type(type, data[start_position..])
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def start_positions(types, data)
|
41
|
-
start_positions = ::Array.new(types.size)
|
42
|
-
offset = 0
|
43
|
-
|
44
|
-
types.each_with_index do |type, index|
|
45
|
-
if type.dynamic?
|
46
|
-
# 读取动态类型的偏移量
|
47
|
-
start_positions[index] = decode_uint256(data[offset, 32])
|
48
|
-
offset += 32
|
49
|
-
else
|
50
|
-
start_positions[index] = offset
|
51
|
-
offset += type.size
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
start_positions
|
56
|
-
end
|
57
27
|
end
|
@@ -3,6 +3,20 @@ module AbiCoderRb
|
|
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
|
+
# 如果内部类型是静态的,就是一个一个元素编码后加起来。
|
8
|
+
# 如果内部类型是动态的,先用位置一个一个编码加起来,然后是元素本体
|
9
|
+
subtype = type.subtype
|
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
|
7
21
|
end
|
8
22
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module AbiCoderRb
|
2
2
|
def encode_primitive_type(type, arg)
|
3
|
+
arg = before_encoding_action.call(type.format, arg) if before_encoding_action
|
3
4
|
# 根据类型选择相应的编码方法
|
4
5
|
case type
|
5
6
|
when Uint
|
@@ -34,12 +35,11 @@ module AbiCoderRb
|
|
34
35
|
encode_uint(arg, 256)
|
35
36
|
end
|
36
37
|
|
37
|
-
def encode_int(arg,
|
38
|
+
def encode_int(arg, _bits)
|
38
39
|
## raise EncodingError or ArgumentError - why? why not?
|
39
40
|
raise ArgumentError, "arg is not integer: #{arg}" unless arg.is_a?(Integer)
|
40
|
-
raise ValueOutOfBounds, arg unless arg >= -2**(bits - 1) && arg < 2**(bits - 1)
|
41
41
|
|
42
|
-
|
42
|
+
hex_to_bin(Utils.int_to_abi_signed_256bit(arg))
|
43
43
|
end
|
44
44
|
|
45
45
|
def encode_bool(arg)
|
@@ -53,7 +53,7 @@ module AbiCoderRb
|
|
53
53
|
## raise EncodingError or ArgumentError - why? why not?
|
54
54
|
raise EncodingError, "Expecting string: #{arg}" unless arg.is_a?(::String)
|
55
55
|
|
56
|
-
arg = arg.b if arg.encoding !=
|
56
|
+
arg = arg.b if arg.encoding != "BINARY" ## was: name == 'UTF-8', wasm
|
57
57
|
|
58
58
|
raise ValueOutOfBounds, "Integer invalid or out of range: #{arg.size}" if arg.size > UINT_MAX
|
59
59
|
|
@@ -69,7 +69,7 @@ module AbiCoderRb
|
|
69
69
|
arg = arg.b if arg.encoding != Encoding::BINARY
|
70
70
|
|
71
71
|
if length # fixed length type
|
72
|
-
raise ValueOutOfBounds, "invalid bytes length #{length}" if arg.size > length
|
72
|
+
raise ValueOutOfBounds, "invalid bytes length #{arg.size}, should be #{length}" if arg.size > length
|
73
73
|
raise ValueOutOfBounds, "invalid bytes length #{length}" if length < 0 || length > 32
|
74
74
|
|
75
75
|
rpad(arg)
|
@@ -100,6 +100,18 @@ module AbiCoderRb
|
|
100
100
|
|
101
101
|
private
|
102
102
|
|
103
|
+
def int_to_eth_abi(value, bits)
|
104
|
+
# 计算补码,如果是负数
|
105
|
+
value = 2**bits + value if value < 0
|
106
|
+
|
107
|
+
# 将值转换为十六进制字符串
|
108
|
+
hex = (value % 2**bits).to_s(16)
|
109
|
+
hex = "0#{hex}" if hex.length.odd?
|
110
|
+
|
111
|
+
# 确保字符串长度为16位(8个字节)
|
112
|
+
hex.rjust(bits / 4, "0")
|
113
|
+
end
|
114
|
+
|
103
115
|
###########
|
104
116
|
# encoding helpers / utils
|
105
117
|
# with "hard-coded" fill symbol as BYTE_ZERO
|
@@ -124,8 +136,8 @@ module AbiCoderRb
|
|
124
136
|
raise ArgumentError, "Integer invalid or out of range: #{n}" unless n.is_a?(Integer) && n >= 0 && n <= UINT_MAX
|
125
137
|
|
126
138
|
hex = n.to_s(16)
|
127
|
-
hex = "0"
|
128
|
-
bin =
|
139
|
+
hex = "0#{hex}" if hex.length.odd? # wasm, no .odd?
|
140
|
+
bin = hex_to_bin(hex)
|
129
141
|
|
130
142
|
lpad(bin)
|
131
143
|
end
|
@@ -135,7 +147,7 @@ module AbiCoderRb
|
|
135
147
|
raise TypeError, "Value must be a string" unless hex.is_a?(::String)
|
136
148
|
raise TypeError, "Non-hexadecimal digit found" unless hex =~ /\A[0-9a-fA-F]*\z/
|
137
149
|
|
138
|
-
bin =
|
150
|
+
bin = hex_to_bin(hex)
|
139
151
|
|
140
152
|
lpad(bin)
|
141
153
|
end
|
@@ -2,4 +2,36 @@ module AbiCoderRb
|
|
2
2
|
def encode_tuple(tuple, args)
|
3
3
|
encode_types(tuple.types, args)
|
4
4
|
end
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def encode_types(types, args)
|
9
|
+
raise ArgumentError, "args must be an array" unless args.is_a?(::Array)
|
10
|
+
|
11
|
+
unless args.size == types.size
|
12
|
+
raise ArgumentError,
|
13
|
+
"Wrong number of args: found #{args.size}, expecting #{types.size}"
|
14
|
+
end
|
15
|
+
|
16
|
+
# 计算头部大小
|
17
|
+
head_size = types.map { |type| type.size || 32 }.sum
|
18
|
+
|
19
|
+
# 初始化头部和尾部
|
20
|
+
head = "".b
|
21
|
+
tail = "".b # 使用二进制字符串
|
22
|
+
|
23
|
+
# 遍历类型并编码
|
24
|
+
types.each_with_index do |type, i|
|
25
|
+
if type.dynamic?
|
26
|
+
# 动态类型: 更新头部和尾部
|
27
|
+
head += encode_uint256(head_size + tail.size)
|
28
|
+
tail += encode_type(type, args[i])
|
29
|
+
else
|
30
|
+
# 静态类型: 只更新头部
|
31
|
+
head += encode_type(type, args[i])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
head + tail
|
36
|
+
end
|
5
37
|
end
|
data/lib/abi_coder_rb/encode.rb
CHANGED
@@ -4,56 +4,26 @@ require_relative "encode/encode_array"
|
|
4
4
|
require_relative "encode/encode_primitive_type"
|
5
5
|
|
6
6
|
module AbiCoderRb
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def encode(types, args)
|
12
|
-
# 如果 types 是字符串,则转换为 ABI::Type 实例
|
13
|
-
types = types.map { |type| type.is_a?(Type) ? type : Type.parse(type) }
|
7
|
+
# returns byte array
|
8
|
+
def encode(type, value)
|
9
|
+
# TODO: more checks?
|
10
|
+
raise EncodingError, "Value can not be nil" if value.nil?
|
14
11
|
|
15
|
-
|
12
|
+
parsed = Type.parse(type)
|
13
|
+
encode_type(parsed, value)
|
16
14
|
end
|
17
15
|
|
18
16
|
private
|
19
17
|
|
20
|
-
def encode_type(type,
|
18
|
+
def encode_type(type, value)
|
21
19
|
if type.is_a?(Tuple)
|
22
|
-
encode_tuple(type,
|
23
|
-
elsif type.is_a?(Array)
|
24
|
-
|
20
|
+
encode_tuple(type, value)
|
21
|
+
elsif type.is_a?(Array)
|
22
|
+
encode_array(type, value)
|
23
|
+
elsif type.is_a?(FixedArray)
|
24
|
+
encode_fixed_array(type, value)
|
25
25
|
else
|
26
|
-
encode_primitive_type(type,
|
26
|
+
encode_primitive_type(type, value)
|
27
27
|
end
|
28
28
|
end
|
29
|
-
|
30
|
-
def encode_types(types, args)
|
31
|
-
raise ArgumentError, "args must be an array" unless args.is_a?(::Array)
|
32
|
-
|
33
|
-
unless args.size == types.size
|
34
|
-
raise ArgumentError,
|
35
|
-
"Wrong number of args: found #{args.size}, expecting #{types.size}"
|
36
|
-
end
|
37
|
-
|
38
|
-
# 计算头部大小
|
39
|
-
head_size = types.map { |type| type.size || 32 }.sum
|
40
|
-
|
41
|
-
# 初始化头部和尾部
|
42
|
-
head = "".b
|
43
|
-
tail = "".b # 使用二进制字符串
|
44
|
-
|
45
|
-
# 遍历类型并编码
|
46
|
-
types.each_with_index do |type, i|
|
47
|
-
if type.dynamic?
|
48
|
-
# 动态类型: 更新头部和尾部
|
49
|
-
head += encode_uint256(head_size + tail.size)
|
50
|
-
tail += encode_type(type, args[i])
|
51
|
-
else
|
52
|
-
# 静态类型: 只更新头部
|
53
|
-
head += encode_type(type, args[i])
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
head + tail
|
58
|
-
end
|
59
29
|
end
|
data/lib/abi_coder_rb/parser.rb
CHANGED
@@ -9,6 +9,8 @@ module AbiCoderRb
|
|
9
9
|
/x
|
10
10
|
|
11
11
|
def self.parse(type)
|
12
|
+
type = type.strip
|
13
|
+
|
12
14
|
if type =~ TUPLE_TYPE_RX
|
13
15
|
types = _parse_tuple_type(::Regexp.last_match(1))
|
14
16
|
dims = _parse_dims(::Regexp.last_match(2))
|
@@ -18,8 +20,13 @@ module AbiCoderRb
|
|
18
20
|
return _parse_array_type(Tuple.new(parsed_types), dims)
|
19
21
|
end
|
20
22
|
|
23
|
+
# uint256 => uint, 256, nil
|
24
|
+
# uint256[2] => uint, 256, [2]
|
25
|
+
# uint256[] => uint, 256, [-1]
|
26
|
+
# bytes => bytes, nil, []
|
21
27
|
base, sub, dims = _parse_base_type(type)
|
22
28
|
|
29
|
+
sub ||= 256 if type.start_with?("uint") || type.start_with?("int") # default to 256 if no sub given
|
23
30
|
_validate_base_type(base, sub)
|
24
31
|
|
25
32
|
subtype = case base
|
@@ -96,7 +103,7 @@ module AbiCoderRb
|
|
96
103
|
# NOTE: string can not have any suffix
|
97
104
|
raise ParseError, "String cannot have suffix" if sub
|
98
105
|
when "bytes"
|
99
|
-
raise ParseError, "Maximum 32 bytes for fixed-length bytes"
|
106
|
+
raise ParseError, "Maximum 32 bytes for fixed-length bytes" if sub && sub > 32
|
100
107
|
when "uint", "int"
|
101
108
|
raise ParseError, "Integer type must have numerical suffix" unless sub
|
102
109
|
raise ParseError, "Integer size out of bounds" unless sub >= 8 && sub <= 256
|
data/lib/abi_coder_rb/types.rb
CHANGED
@@ -210,12 +210,19 @@ module AbiCoderRb
|
|
210
210
|
|
211
211
|
def size
|
212
212
|
s = 0
|
213
|
+
has_dynamic = false
|
213
214
|
@types.each do |type|
|
214
215
|
ts = type.size
|
215
|
-
|
216
|
-
|
217
|
-
|
216
|
+
if ts.nil?
|
217
|
+
# can not return nil here? if wasm
|
218
|
+
has_dynamic = true
|
219
|
+
else
|
220
|
+
s += ts
|
221
|
+
end
|
218
222
|
end
|
223
|
+
|
224
|
+
return if has_dynamic
|
225
|
+
|
219
226
|
s
|
220
227
|
end
|
221
228
|
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module AbiCoderRb
|
2
|
+
module Utils
|
3
|
+
class << self
|
4
|
+
def hex_to_bin(hex)
|
5
|
+
hex = hex[2..] if %w[0x 0X].include?(hex[0, 2]) ## cut-of leading 0x or 0X if present
|
6
|
+
hex.scan(/../).map { |x| x.hex.chr }.join
|
7
|
+
end
|
8
|
+
|
9
|
+
def bin_to_hex(bin)
|
10
|
+
bin.each_byte.map { |byte| "%02x" % byte }.join
|
11
|
+
end
|
12
|
+
|
13
|
+
def hex?(str)
|
14
|
+
str.start_with?("0x") && str.length.even? && str[2..].match?(/\A\b[0-9a-fA-F]+\b\z/)
|
15
|
+
end
|
16
|
+
|
17
|
+
# example:
|
18
|
+
# lpad("hello", 'x', 10) => "xxxxxxhello"
|
19
|
+
def lpad(str, sym, len)
|
20
|
+
return str if str.size >= len
|
21
|
+
|
22
|
+
sym * (len - str.size) + str
|
23
|
+
end
|
24
|
+
|
25
|
+
def zpad(str, len)
|
26
|
+
lpad str, BYTE_ZERO, len
|
27
|
+
end
|
28
|
+
|
29
|
+
def ffpad(str, len)
|
30
|
+
lpad str, BYTE_FF, len
|
31
|
+
end
|
32
|
+
|
33
|
+
def uint_to_big_endian(num, size)
|
34
|
+
raise "Can only serialize integers" unless num.is_a?(Integer)
|
35
|
+
raise "Cannot serialize negative integers" if num.negative?
|
36
|
+
raise "Integer too large (does not fit in #{size} bytes)" if size && num >= 256**size
|
37
|
+
|
38
|
+
# Convert num into a binary string
|
39
|
+
s = if num.zero?
|
40
|
+
BYTE_EMPTY
|
41
|
+
else
|
42
|
+
hex = num.to_s(16)
|
43
|
+
hex = "0#{hex}" if hex.size.odd?
|
44
|
+
hex_to_bin hex
|
45
|
+
end
|
46
|
+
|
47
|
+
# Adjust the size of the binary string to match the specified `size` in bytes, if `size` is given.
|
48
|
+
s = size ? "#{BYTE_ZERO * [0, size - s.size].max}#{s}" : s
|
49
|
+
|
50
|
+
zpad s, size
|
51
|
+
end
|
52
|
+
|
53
|
+
def int_to_abi_signed_256bit(value)
|
54
|
+
# 确保值在256位有符号整数范围内
|
55
|
+
min = -2**255
|
56
|
+
max = 2**255 - 1
|
57
|
+
raise "Value out of range" if value < min || value > max
|
58
|
+
|
59
|
+
# 为负数计算补码
|
60
|
+
value = (1 << 256) + value if value < 0
|
61
|
+
|
62
|
+
# 转换为十六进制字符串
|
63
|
+
hex_str = value.to_s(16)
|
64
|
+
|
65
|
+
# 确保字符串长度为64字符(256位)
|
66
|
+
hex_str.rjust(64, "0")
|
67
|
+
end
|
68
|
+
|
69
|
+
def int_to_abi_signed(value)
|
70
|
+
# 确保值在32位有符号整数范围内
|
71
|
+
raise "Value out of range" if value < -2**31 || value > 2**31 - 1
|
72
|
+
|
73
|
+
# 转换为32位有符号整数的二进制表示,然后转换为十六进制
|
74
|
+
hex_str = [value].pack("l>").unpack1("H*")
|
75
|
+
|
76
|
+
# 如果是正数,补齐前导零以达到64位长度
|
77
|
+
# 如果是负数,pack方法会产生正确的补码形式,但需要确保长度为64位
|
78
|
+
if value >= 0
|
79
|
+
hex_str.rjust(64, "0")
|
80
|
+
else
|
81
|
+
hex_str.rjust(64, "f")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def abi_to_int_signed(hex_str, bits)
|
86
|
+
hex_str = "0x#{hex_str}" if hex_str[0, 2] != "0x" || hex_str[0, 2] != "0X"
|
87
|
+
|
88
|
+
# 计算预期的十六进制字符串长度
|
89
|
+
expected_length = bits / 4
|
90
|
+
extended_hex_str = if hex_str.length < expected_length
|
91
|
+
# 如果输入长度小于预期,根据首位字符扩展字符串
|
92
|
+
extend_char = hex_str[0] == "f" ? "f" : "0"
|
93
|
+
extend_char * (expected_length - hex_str.length) + hex_str
|
94
|
+
else
|
95
|
+
hex_str
|
96
|
+
end
|
97
|
+
|
98
|
+
# 将十六进制字符串转换为二进制字符串
|
99
|
+
binary_str = extended_hex_str.to_i(16).to_s(2).rjust(bits, extended_hex_str[0])
|
100
|
+
|
101
|
+
# 检查符号位并转换为整数
|
102
|
+
if binary_str[0] == "1" # 负数
|
103
|
+
# 取反加一以计算补码,然后转换为负数
|
104
|
+
-((binary_str.tr("01", "10").to_i(2) + 1) & ((1 << bits) - 1))
|
105
|
+
else # 正数
|
106
|
+
binary_str.to_i(2)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/lib/abi_coder_rb/version.rb
CHANGED
data/lib/abi_coder_rb.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require_relative "abi_coder_rb/version"
|
4
4
|
|
5
|
+
require_relative "abi_coder_rb/utils"
|
6
|
+
|
5
7
|
require_relative "abi_coder_rb/parser"
|
6
8
|
require_relative "abi_coder_rb/types"
|
7
9
|
require_relative "abi_coder_rb/decode"
|
@@ -13,17 +15,10 @@ module AbiCoderRb
|
|
13
15
|
class ValueError < StandardError; end
|
14
16
|
class ValueOutOfBounds < ValueError; end
|
15
17
|
|
16
|
-
|
17
|
-
### some (shared) constants (move to constants.rb or such - why? why not?)
|
18
|
-
|
19
|
-
## todo/check: use auto-freeze string literals magic comment - why? why not?
|
20
|
-
##
|
21
|
-
## todo/fix: move BYTE_EMPTY, BYTE_ZERO, BYTE_ONE to upstream to bytes gem
|
22
|
-
## and make "global" constants - why? why not?
|
23
|
-
|
24
|
-
## BYTE_EMPTY = "".b.freeze
|
18
|
+
BYTE_EMPTY = "".b.freeze
|
25
19
|
BYTE_ZERO = "\x00".b.freeze
|
26
20
|
BYTE_ONE = "\x01".b.freeze ## note: used for encoding bool for now
|
21
|
+
BYTE_FF = "\xff".b.freeze
|
27
22
|
|
28
23
|
UINT_MAX = 2**256 - 1 ## same as 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
29
24
|
UINT_MIN = 0
|
@@ -32,12 +27,25 @@ module AbiCoderRb
|
|
32
27
|
|
33
28
|
def hex_to_bin(hex) # convert hex(adecimal) string to binary string
|
34
29
|
hex = hex[2..] if %w[0x 0X].include?(hex[0, 2]) ## cut-of leading 0x or 0X if present
|
35
|
-
|
30
|
+
hex.scan(/../).map { |x| x.hex.chr }.join
|
36
31
|
end
|
37
32
|
alias hex hex_to_bin
|
38
33
|
|
39
34
|
def bin_to_hex(bin) # convert binary string to hex string
|
40
|
-
bin.
|
35
|
+
bin.each_byte.map { |byte| "%02x" % byte }.join
|
36
|
+
end
|
37
|
+
|
38
|
+
def hex?(str)
|
39
|
+
str.start_with?("0x") && str.length.even? && str[2..].match?(/\A\b[0-9a-fA-F]+\b\z/)
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_accessor :before_encoding_action, :after_decoding_action
|
43
|
+
|
44
|
+
def before_encoding(action)
|
45
|
+
self.before_encoding_action = action
|
46
|
+
end
|
47
|
+
|
48
|
+
def after_decoding(action)
|
49
|
+
self.after_decoding_action = action
|
41
50
|
end
|
42
|
-
alias bin bin_to_hex
|
43
51
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abi_coder_rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aki Wu
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-11-
|
12
|
-
dependencies:
|
11
|
+
date: 2023-11-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: keccak
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
13
27
|
description: An EVM ABI encoding and decoding tool
|
14
28
|
email:
|
15
29
|
- wuminzhe@gmail.com
|
@@ -26,6 +40,8 @@ files:
|
|
26
40
|
- LICENSE.txt
|
27
41
|
- README.md
|
28
42
|
- Rakefile
|
43
|
+
- flatten.rb
|
44
|
+
- flattened_abi_coder.rb
|
29
45
|
- lib/.DS_Store
|
30
46
|
- lib/abi_coder_rb.rb
|
31
47
|
- lib/abi_coder_rb/.DS_Store
|
@@ -41,6 +57,7 @@ files:
|
|
41
57
|
- lib/abi_coder_rb/encode/encode_tuple.rb
|
42
58
|
- lib/abi_coder_rb/parser.rb
|
43
59
|
- lib/abi_coder_rb/types.rb
|
60
|
+
- lib/abi_coder_rb/utils.rb
|
44
61
|
- lib/abi_coder_rb/version.rb
|
45
62
|
- sig/abi_coder_rb.rbs
|
46
63
|
homepage: https://github.com/wuminzhe/abi_coder_rb
|