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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae222b87f68b45367128a4cd07c5792208ed75ef4838dcf64e414fd60366ddff
4
- data.tar.gz: 344f59862c11ffbbf6127a350cc5066093da24433914bad779f9b75e3e9e97e1
3
+ metadata.gz: 2446e20c68206c39fddd2cc887136d0188a74283c82240f95d9fd3d7fce19d15
4
+ data.tar.gz: '0158a5505f945dc0655a1c80cf8722ff4d15610bf2e027fea15cd21de917aa1c'
5
5
  SHA512:
6
- metadata.gz: 92c783fb486a02c1df160acaf87c773ca9d2ef7e6637acdc441c69edf92c135f216d22708af285a0ebc02c3711c68f61b7d64cbbece681425c7fb82edee5ea16
7
- data.tar.gz: a5ac737f20cb1b66128e57ab27786b40d36e646a7836baa2b374339ca56825c4c486cf08e615fadbe81ddb6cd96224c80025040d586e6648c69c72a6e92b0d1f
6
+ metadata.gz: 26d7209d606865c01c539a3e5611e25477ce8ba3f2f1e9e54eb0c879ac510ca047979c066905a430fceab5f23f18b8c680b594341834a900d03e983d2241be03
7
+ data.tar.gz: cac0312067c262e52808ff92b7b36e9a85e87660e306f1e13205a19eb1107bb1a9fb423b2fd6641949c0e4e130b3bb20adb114c1d0fa83f00b5e81923173b2b3
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- abi_coder_rb (0.2.7)
4
+ abi_coder_rb (0.2.8)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -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
- head += encode_uint256(args.size)
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
- head += encode_uint256(32 * args.size + tail.size)
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
- 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
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
- lpad_int(arg)
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, _bits)
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
- hex_to_bin(int_to_abi_signed_256bit(arg))
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
- lpad(arg ? BYTE_ONE : BYTE_ZERO) ## was lpad_int( arg ? 1 : 0 )
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
- size = lpad_int(arg.size)
61
- value = rpad(arg, ceil32(arg.size))
62
- size + value
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 = nil)
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
- size = lpad_int(arg.size)
80
- value = rpad(arg, ceil32(arg.size))
81
- size + value
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.size == 20
89
- ## note: make sure encoding is always binary!!!
90
- arg = arg.b if arg.encoding != Encoding::BINARY
91
- lpad(arg)
92
- elsif arg.size == 40
93
- lpad_hex(arg)
94
- elsif arg.size == 42 && arg[0, 2] == "0x" ## todo/fix: allow 0X too - why? why not?
95
- lpad_hex(arg[2..-1])
96
- else
97
- raise EncodingError, "Could not parse address: #{arg}"
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
- encode_types(tuple.types, args)
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
 
@@ -5,25 +5,38 @@ require_relative "encode/encode_primitive_type"
5
5
 
6
6
  module AbiCoderRb
7
7
  # returns byte array
8
- def encode(type, value)
9
- # TODO: more checks?
10
- raise EncodingError, "Value can not be nil" if value.nil?
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
- parsed = Type.parse(type)
13
- encode_type(parsed, value)
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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbiCoderRb
4
- VERSION = "0.2.7"
4
+ VERSION = "0.2.8"
5
5
  end
data/tea.yaml ADDED
@@ -0,0 +1,6 @@
1
+ # https://tea.xyz/what-is-this-file
2
+ ---
3
+ version: 1.0.0
4
+ codeOwners:
5
+ - '0x08D5966A5226C74f59407bC3aB3a63a68488Da1D'
6
+ quorum: 1
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.7
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-02-26 00:00:00.000000000 Z
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