ethlite 0.1.0 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 782c6115c725eaefb922c2486832197ddeb44473d21d74e9b8f27de9986aef63
4
- data.tar.gz: 30db801b21cc0fb703ba78908470b5e6ea9b2741768b03caf7a01bd7a772734a
3
+ metadata.gz: 5dea4d9654501b9b1fa7a86477a0b509e7722975fdf29ce3c95e060750d917f7
4
+ data.tar.gz: 25b082b2803cb0404b39cab23b62740c716680f22d3f61825e364f9dfd387640
5
5
  SHA512:
6
- metadata.gz: 3babcd1abc28ba676df94e7afe53cf3ea7880a4b69e112c85ab12b6f6d226b63424e5cebe7678e91b0c34f2ed4da6bbcf3e88eb401d9e3ac7375ef38592f4bbf
7
- data.tar.gz: 34c38f561121d5ad42070b2fbadc6899cc94b1e8ecf4a6f695f71a1a5166f98211fbe572a7a0b2d9d111407ef1b4fcf7058d2f58aca81d5e1e4662b834cd7f77
6
+ metadata.gz: 6c28f0334a44bdbb3c2b4d2f375b94ff9ee643a49aa66953eac3bcd471a78398f2c89f8f8b150f64a1d64d19c2a47590f793b4c88ab7c41c045330a44a85a06b
7
+ data.tar.gz: 45ff4d1b251eb7273f8fa1034b92bb2a95164796268e2d0a69d26f3567e7b806163ab7d851ef8d314d75bb61845d0117ae56fd7af089098ff43e3940dc1c7b2d
data/Manifest.txt CHANGED
@@ -2,5 +2,15 @@ CHANGELOG.md
2
2
  Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
+ lib/digest/keccak256.rb
6
+ lib/digest/sha3.rb
5
7
  lib/ethlite.rb
8
+ lib/ethlite/abi/abi_coder.rb
9
+ lib/ethlite/abi/constant.rb
10
+ lib/ethlite/abi/exceptions.rb
11
+ lib/ethlite/abi/type.rb
12
+ lib/ethlite/abi/utils.rb
13
+ lib/ethlite/contract.rb
14
+ lib/ethlite/rpc.rb
15
+ lib/ethlite/utility.rb
6
16
  lib/ethlite/version.rb
data/Rakefile CHANGED
@@ -20,6 +20,8 @@ Hoe.spec 'ethlite' do
20
20
 
21
21
  self.extra_deps = [
22
22
  ['cocos'],
23
+ ## ['keccak'], -- try using bundled ruby version for now
24
+ ['rlp'],
23
25
  ]
24
26
 
25
27
  self.licenses = ['Public Domain']
@@ -0,0 +1,111 @@
1
+ ###
2
+ # use a "vendor" bundled keccak 256 in all ruby (no c-extensions required)
3
+ #
4
+ # see https://github.com/evtaylor/keccak256
5
+
6
+
7
+
8
+ ## require 'digest'
9
+
10
+
11
+ module Digest
12
+ class Keccak256 < Digest::Class
13
+ PILN = [10, 7, 11, 17, 18, 3, 5, 16,
14
+ 8, 21, 24, 4, 15, 23, 19, 13,
15
+ 12, 2, 20, 14, 22, 9, 6, 1]
16
+
17
+ ROTC = [ 1, 3, 6, 10, 15, 21, 28, 36,
18
+ 45, 55, 2, 14, 27, 41, 56, 8,
19
+ 25, 43, 62, 18, 39, 61, 20, 44]
20
+
21
+ RNDC = [0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
22
+ 0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
23
+ 0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
24
+ 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
25
+ 0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
26
+ 0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
27
+ 0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
28
+ 0x8000000000008080, 0x0000000080000001, 0x8000000080008008]
29
+
30
+ def initialize
31
+ @size = 256 / 8
32
+ @buffer = ''
33
+ end
34
+
35
+ def << s
36
+ @buffer << s
37
+ self
38
+ end
39
+ alias update <<
40
+
41
+ def reset
42
+ @buffer.clear
43
+ self
44
+ end
45
+
46
+ def finish
47
+ s = Array.new 25, 0
48
+ width = 200 - @size * 2
49
+ padding = "\x01"
50
+
51
+ buffer = @buffer
52
+ buffer << padding << "\0" * (width - buffer.size % width)
53
+ buffer[-1] = (buffer[-1].ord | 0x80).chr
54
+
55
+ 0.step buffer.size - 1, width do |j|
56
+ quads = buffer[j, width].unpack 'Q*'
57
+ (width / 8).times do |i|
58
+ s[i] ^= quads[i]
59
+ end
60
+
61
+ keccak s
62
+ end
63
+
64
+ s.pack('Q*')[0, @size]
65
+ end
66
+
67
+ private
68
+ def keccak s
69
+ 24.times.each_with_object [] do |round, a|
70
+ # Theta
71
+ 5.times do |i|
72
+ a[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]
73
+ end
74
+
75
+ 5.times do |i|
76
+ t = a[(i + 4) % 5] ^ rotate(a[(i + 1) % 5], 1)
77
+ 0.step 24, 5 do |j|
78
+ s[j + i] ^= t
79
+ end
80
+ end
81
+
82
+ # Rho Pi
83
+ t = s[1]
84
+ 24.times do |i|
85
+ j = PILN[i]
86
+ a[0] = s[j]
87
+ s[j] = rotate t, ROTC[i]
88
+ t = a[0]
89
+ end
90
+
91
+ # Chi
92
+ 0.step 24, 5 do |j|
93
+ 5.times do |i|
94
+ a[i] = s[j + i]
95
+ end
96
+
97
+ 5.times do |i|
98
+ s[j + i] ^= ~a[(i + 1) % 5] & a[(i + 2) % 5]
99
+ end
100
+ end
101
+
102
+ # Iota
103
+ s[0] ^= RNDC[round]
104
+ end
105
+ end
106
+
107
+ def rotate x, y
108
+ (x << y | x >> 64 - y) & (1 << 64) - 1
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,108 @@
1
+ ###
2
+ # use a "vendor" bundled sha3 in all ruby (no c-extensions required)
3
+ #
4
+ # see https://github.com/havenwood/sha3-pure-ruby/blob/master/lib/sha3-pure-ruby.rb
5
+
6
+
7
+ ## require 'digest'
8
+
9
+ module Digest
10
+ class SHA3 < Digest::Class
11
+ PILN = [10, 7, 11, 17, 18, 3, 5, 16,
12
+ 8, 21, 24, 4, 15, 23, 19, 13,
13
+ 12, 2, 20, 14, 22, 9, 6, 1]
14
+
15
+ ROTC = [ 1, 3, 6, 10, 15, 21, 28, 36,
16
+ 45, 55, 2, 14, 27, 41, 56, 8,
17
+ 25, 43, 62, 18, 39, 61, 20, 44]
18
+
19
+ RNDC = [0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
20
+ 0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
21
+ 0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
22
+ 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
23
+ 0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
24
+ 0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
25
+ 0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
26
+ 0x8000000000008080, 0x0000000080000001, 0x8000000080008008]
27
+
28
+ def initialize hash_size = 512
29
+ @size = hash_size / 8
30
+ @buffer = ''
31
+ end
32
+
33
+ def << s
34
+ @buffer << s
35
+ self
36
+ end
37
+ alias update <<
38
+
39
+ def reset
40
+ @buffer.clear
41
+ self
42
+ end
43
+
44
+ def finish
45
+ s = Array.new 25, 0
46
+ width = 200 - @size * 2
47
+
48
+ buffer = @buffer
49
+ buffer << "\x06" << "\0" * (width - buffer.size % width)
50
+ buffer[-1] = (buffer[-1].ord | 0x80).chr
51
+
52
+ 0.step buffer.size - 1, width do |j|
53
+ quads = buffer[j, width].unpack 'Q*'
54
+ (width / 8).times do |i|
55
+ s[i] ^= quads[i]
56
+ end
57
+
58
+ keccak s
59
+ end
60
+
61
+ s.pack('Q*')[0, @size]
62
+ end
63
+
64
+ private
65
+ def keccak s
66
+ 24.times.each_with_object [] do |round, a|
67
+ # Theta
68
+ 5.times do |i|
69
+ a[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]
70
+ end
71
+
72
+ 5.times do |i|
73
+ t = a[(i + 4) % 5] ^ rotate(a[(i + 1) % 5], 1)
74
+ 0.step 24, 5 do |j|
75
+ s[j + i] ^= t
76
+ end
77
+ end
78
+
79
+ # Rho Pi
80
+ t = s[1]
81
+ 24.times do |i|
82
+ j = PILN[i]
83
+ a[0] = s[j]
84
+ s[j] = rotate t, ROTC[i]
85
+ t = a[0]
86
+ end
87
+
88
+ # Chi
89
+ 0.step 24, 5 do |j|
90
+ 5.times do |i|
91
+ a[i] = s[j + i]
92
+ end
93
+
94
+ 5.times do |i|
95
+ s[j + i] ^= ~a[(i + 1) % 5] & a[(i + 2) % 5]
96
+ end
97
+ end
98
+
99
+ # Iota
100
+ s[0] ^= RNDC[round]
101
+ end
102
+ end
103
+
104
+ def rotate x, y
105
+ (x << y | x >> 64 - y) & (1 << 64) - 1
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,423 @@
1
+
2
+
3
+ module Ethlite
4
+ module Abi
5
+
6
+ ##
7
+ # Contract ABI encoding and decoding.
8
+ #
9
+ # @see https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
10
+ #
11
+ module AbiCoder
12
+
13
+ extend self
14
+
15
+ include Constant
16
+
17
+ class EncodingError < StandardError; end
18
+ class DecodingError < StandardError; end
19
+ class ValueOutOfBounds < ValueError; end
20
+
21
+ ##
22
+ # Encodes multiple arguments using the head/tail mechanism.
23
+ #
24
+ def encode_abi(types, args)
25
+ parsed_types = types.map {|t| Type.parse(t) }
26
+
27
+ head_size = (0...args.size)
28
+ .map {|i| parsed_types[i].size || 32 }
29
+ .reduce(0, &:+)
30
+
31
+ head, tail = '', ''
32
+ args.each_with_index do |arg, i|
33
+ if parsed_types[i].dynamic?
34
+ head += encode_type(Type.size_type, head_size + tail.size)
35
+ tail += encode_type(parsed_types[i], arg)
36
+ else
37
+ head += encode_type(parsed_types[i], arg)
38
+ end
39
+ end
40
+
41
+ "#{head}#{tail}"
42
+ end
43
+ alias :encode :encode_abi
44
+
45
+ ##
46
+ # Encodes a single value (static or dynamic).
47
+ #
48
+ # @param type [Ethereum::ABI::Type] value type
49
+ # @param arg [Object] value
50
+ #
51
+ # @return [String] encoded bytes
52
+ #
53
+ def encode_type(type, arg)
54
+ if %w(string bytes).include?(type.base) && type.sub.empty?
55
+ encode_primitive_type type, arg
56
+ elsif type.dynamic?
57
+ raise ArgumentError, "arg must be an array" unless arg.instance_of?(Array)
58
+
59
+ head, tail = '', ''
60
+ if type.dims.last == 0
61
+ head += encode_type(Type.size_type, arg.size)
62
+ else
63
+ raise ArgumentError, "Wrong array size: found #{arg.size}, expecting #{type.dims.last}" unless arg.size == type.dims.last
64
+ end
65
+
66
+ sub_type = type.subtype
67
+ sub_size = type.subtype.size
68
+ arg.size.times do |i|
69
+ if sub_size.nil?
70
+ head += encode_type(Type.size_type, 32*arg.size + tail.size)
71
+ tail += encode_type(sub_type, arg[i])
72
+ else
73
+ head += encode_type(sub_type, arg[i])
74
+ end
75
+ end
76
+
77
+ "#{head}#{tail}"
78
+ else # static type
79
+ if type.dims.empty?
80
+ encode_primitive_type type, arg
81
+ else
82
+ arg.map {|x| encode_type(type.subtype, x) }.join
83
+ end
84
+ end
85
+ end
86
+
87
+ def encode_primitive_type(type, arg)
88
+ case type.base
89
+ when 'uint'
90
+ begin
91
+ real_size = type.sub.to_i
92
+ i = get_uint arg
93
+
94
+ raise ValueOutOfBounds, arg unless i >= 0 && i < 2**real_size
95
+ Utils.zpad_int i
96
+ rescue EncodingError
97
+ raise ValueOutOfBounds, arg
98
+ end
99
+ when 'bool'
100
+ raise ArgumentError, "arg is not bool: #{arg}" unless arg.instance_of?(TrueClass) || arg.instance_of?(FalseClass)
101
+ Utils.zpad_int(arg ? 1 : 0)
102
+ when 'int'
103
+ begin
104
+ real_size = type.sub.to_i
105
+ i = get_int arg
106
+
107
+ raise ValueOutOfBounds, arg unless i >= -2**(real_size-1) && i < 2**(real_size-1)
108
+ Utils.zpad_int(i % 2**type.sub.to_i)
109
+ rescue EncodingError
110
+ raise ValueOutOfBounds, arg
111
+ end
112
+ when 'ufixed'
113
+ high, low = type.sub.split('x').map(&:to_i)
114
+
115
+ raise ValueOutOfBounds, arg unless arg >= 0 && arg < 2**high
116
+ Utils.zpad_int((arg * 2**low).to_i)
117
+ when 'fixed'
118
+ high, low = type.sub.split('x').map(&:to_i)
119
+
120
+ raise ValueOutOfBounds, arg unless arg >= -2**(high - 1) && arg < 2**(high - 1)
121
+
122
+ i = (arg * 2**low).to_i
123
+ Utils.zpad_int(i % 2**(high+low))
124
+ when 'string'
125
+ if arg.encoding.name == 'UTF-8'
126
+ arg = arg.b
127
+ else
128
+ begin
129
+ arg.unpack('U*')
130
+ rescue ArgumentError
131
+ raise ValueError, "string must be UTF-8 encoded"
132
+ end
133
+ end
134
+
135
+ if type.sub.empty? # variable length type
136
+ raise ValueOutOfBounds, "Integer invalid or out of range: #{arg.size}" if arg.size >= TT256
137
+ size = Utils.zpad_int arg.size
138
+ value = Utils.rpad arg, BYTE_ZERO, Utils.ceil32(arg.size)
139
+ "#{size}#{value}"
140
+ else # fixed length type
141
+ sub = type.sub.to_i
142
+ raise ValueOutOfBounds, "invalid string length #{sub}" if arg.size > sub
143
+ raise ValueOutOfBounds, "invalid string length #{sub}" if sub < 0 || sub > 32
144
+ Utils.rpad(arg, BYTE_ZERO, 32)
145
+ end
146
+ when 'bytes'
147
+ raise EncodingError, "Expecting string: #{arg}" unless arg.instance_of?(String)
148
+ arg = arg.b
149
+
150
+ if type.sub.empty? # variable length type
151
+ raise ValueOutOfBounds, "Integer invalid or out of range: #{arg.size}" if arg.size >= TT256
152
+ size = Utils.zpad_int arg.size
153
+ value = Utils.rpad arg, BYTE_ZERO, Utils.ceil32(arg.size)
154
+ "#{size}#{value}"
155
+ else # fixed length type
156
+ sub = type.sub.to_i
157
+ raise ValueOutOfBounds, "invalid bytes length #{sub}" if arg.size > sub
158
+ raise ValueOutOfBounds, "invalid bytes length #{sub}" if sub < 0 || sub > 32
159
+ Utils.rpad(arg, BYTE_ZERO, 32)
160
+ end
161
+ when 'hash'
162
+ size = type.sub.to_i
163
+ raise EncodingError, "too long: #{arg}" unless size > 0 && size <= 32
164
+
165
+ if arg.is_a?(Integer)
166
+ Utils.zpad_int(arg)
167
+ elsif arg.size == size
168
+ Utils.zpad arg, 32
169
+ elsif arg.size == size * 2
170
+ Utils.zpad_hex arg
171
+ else
172
+ raise EncodingError, "Could not parse hash: #{arg}"
173
+ end
174
+ when 'address'
175
+ if arg.is_a?(Integer)
176
+ Utils.zpad_int arg
177
+ elsif arg.size == 20
178
+ Utils.zpad arg, 32
179
+ elsif arg.size == 40
180
+ Utils.zpad_hex arg
181
+ elsif arg.size == 42 && arg[0,2] == '0x'
182
+ Utils.zpad_hex arg[2..-1]
183
+ else
184
+ raise EncodingError, "Could not parse address: #{arg}"
185
+ end
186
+ else
187
+ raise EncodingError, "Unhandled type: #{type.base} #{type.sub}"
188
+ end
189
+ end
190
+
191
+
192
+ def min_data_size types
193
+ types.size*32
194
+ end
195
+
196
+ ##
197
+ # Decodes multiple arguments using the head/tail mechanism.
198
+ #
199
+ def decode_abi types, data, raise_errors = false
200
+ parsed_types = types.map {|t| Type.parse(t) }
201
+
202
+ outputs = [nil] * types.size
203
+ start_positions = [nil] * types.size + [data.size]
204
+
205
+ # TODO: refactor, a reverse iteration will be better
206
+ pos = 0
207
+ parsed_types.each_with_index do |t, i|
208
+ # If a type is static, grab the data directly, otherwise record its
209
+ # start position
210
+ if t.dynamic?
211
+
212
+ if raise_errors && pos>data.size-1
213
+ raise DecodingError, "Position out of bounds #{pos}>#{data.size-1}"
214
+ end
215
+
216
+ start_positions[i] = Utils.big_endian_to_int(data[pos, 32])
217
+
218
+ if raise_errors && start_positions[i]>data.size-1
219
+ raise DecodingError, "Start position out of bounds #{start_positions[i]}>#{data.size-1}"
220
+ end
221
+
222
+ j = i - 1
223
+ while j >= 0 && start_positions[j].nil?
224
+ start_positions[j] = start_positions[i]
225
+ j -= 1
226
+ end
227
+
228
+ pos += 32
229
+ else
230
+ outputs[i] = zero_padding data, pos, t.size, start_positions
231
+ pos += t.size
232
+ end
233
+ end
234
+
235
+ # We add a start position equal to the length of the entire data for
236
+ # convenience.
237
+ j = types.size - 1
238
+ while j >= 0 && start_positions[j].nil?
239
+ start_positions[j] = start_positions[types.size]
240
+ j -= 1
241
+ end
242
+
243
+ if raise_errors && pos > data.size
244
+ raise DecodingError, "Not enough data for head"
245
+ end
246
+
247
+
248
+ parsed_types.each_with_index do |t, i|
249
+ if t.dynamic?
250
+ offset, next_offset = start_positions[i, 2]
251
+ if offset<=data.size && next_offset<=data.size
252
+ outputs[i] = data[offset...next_offset]
253
+ end
254
+ end
255
+ end
256
+
257
+ if raise_errors && outputs.include?(nil)
258
+ raise DecodingError, "Not all data can be parsed"
259
+ end
260
+
261
+ parsed_types.zip(outputs).map {|(type, out)| decode_type(type, out) }
262
+ end
263
+ alias :decode :decode_abi
264
+
265
+ def zero_padding data, pos, count, start_positions
266
+ if pos >= data.size
267
+ start_positions[start_positions.size-1] += count
268
+ "\x00"*count
269
+ elsif pos + count > data.size
270
+ start_positions[start_positions.size-1] += ( count - (data.size-pos))
271
+ data[pos,data.size-pos] + "\x00"*( count - (data.size-pos))
272
+ else
273
+ data[pos, count]
274
+ end
275
+ end
276
+
277
+ def decode_typed_data type_name, data
278
+ decode_primitive_type Type.parse(type_name), data
279
+ end
280
+
281
+ def decode_type(type, arg)
282
+ return nil if arg.nil? || arg.empty?
283
+ if type.kind_of?(Tuple) && type.dims.empty?
284
+ arg ? decode_abi(type.types, arg) : []
285
+ elsif %w(string bytes).include?(type.base) && type.sub.empty?
286
+ l = Utils.big_endian_to_int arg[0,32]
287
+ data = arg[32..-1]
288
+ data[0, l]
289
+ elsif !type.dims.empty? && (l = type.dims.last)>0 # static-sized arrays
290
+ subtype = type.subtype
291
+ if subtype.dynamic?
292
+ start_positions = (0...l).map {|i| Utils.big_endian_to_int(arg[32*i, 32]) }
293
+ start_positions.push arg.size
294
+
295
+ outputs = (0...l).map {|i| arg[start_positions[i]...start_positions[i+1]] }
296
+
297
+ outputs.map {|out| decode_type(subtype, out) }
298
+ else
299
+ (0...l).map {|i| decode_type(subtype, arg[subtype.size*i, subtype.size]) }
300
+ end
301
+
302
+ elsif type.dynamic?
303
+ l = Utils.big_endian_to_int arg[0,32]
304
+ raise DecodingError, "Too long length: #{l}" if l>100000
305
+ subtype = type.subtype
306
+
307
+ if subtype.dynamic?
308
+ raise DecodingError, "Not enough data for head" unless arg.size >= 32 + 32*l
309
+
310
+ start_positions = (1..l).map {|i| 32+Utils.big_endian_to_int(arg[32*i, 32]) }
311
+ start_positions.push arg.size
312
+
313
+ outputs = (0...l).map {|i| arg[start_positions[i]...start_positions[i+1]] }
314
+
315
+ outputs.map {|out| decode_type(subtype, out) }
316
+ else
317
+ (0...l).map {|i| decode_type(subtype, arg[32 + subtype.size*i, subtype.size]) }
318
+ end
319
+
320
+ else
321
+ decode_primitive_type type, arg
322
+ end
323
+ end
324
+
325
+ def decode_primitive_type(type, data)
326
+ case type.base
327
+ when 'address'
328
+ Utils.encode_hex data[12..-1]
329
+ when 'string', 'bytes'
330
+ if type.sub.empty? # dynamic
331
+ if data.length==32
332
+ data[0..32]
333
+ else
334
+ size = Utils.big_endian_to_int data[0,32]
335
+ data[32..-1][0,size]
336
+ end
337
+ else # fixed
338
+ data[0, type.sub.to_i]
339
+ end
340
+ when 'hash'
341
+ data[(32 - type.sub.to_i), type.sub.to_i]
342
+ when 'uint'
343
+ Utils.big_endian_to_int data
344
+ when 'int'
345
+ u = Utils.big_endian_to_int data
346
+ u >= 2**(type.sub.to_i-1) ? (u - 2**type.sub.to_i) : u
347
+ when 'ufixed'
348
+ high, low = type.sub.split('x').map(&:to_i)
349
+ Utils.big_endian_to_int(data) * 1.0 / 2**low
350
+ when 'fixed'
351
+ high, low = type.sub.split('x').map(&:to_i)
352
+ u = Utils.big_endian_to_int data
353
+ i = u >= 2**(high+low-1) ? (u - 2**(high+low)) : u
354
+ i * 1.0 / 2**low
355
+ when 'bool'
356
+ data[-1] == BYTE_ONE
357
+ else
358
+ raise DecodingError, "Unknown primitive type: #{type.base}"
359
+ end
360
+ end
361
+
362
+ private
363
+
364
+ def get_uint(n)
365
+ case n
366
+ when Integer
367
+ raise EncodingError, "Number out of range: #{n}" if n > UINT_MAX || n < UINT_MIN
368
+ n
369
+ when String
370
+ i = if n.size == 40
371
+ Utils.decode_hex(n)
372
+ elsif n.size <= 32
373
+ n
374
+ else
375
+ raise EncodingError, "String too long: #{n}"
376
+ end
377
+ i = Utils.big_endian_to_int i
378
+
379
+ raise EncodingError, "Number out of range: #{i}" if i > UINT_MAX || i < UINT_MIN
380
+ i
381
+ when true
382
+ 1
383
+ when false, nil
384
+ 0
385
+ else
386
+ raise EncodingError, "Cannot decode uint: #{n}"
387
+ end
388
+ end
389
+
390
+ def get_int(n)
391
+ case n
392
+ when Integer
393
+ raise EncodingError, "Number out of range: #{n}" if n > INT_MAX || n < INT_MIN
394
+ n
395
+ when String
396
+ i = if n.size == 40
397
+ Utils.decode_hex(n)
398
+ elsif n.size <= 32
399
+ n
400
+ else
401
+ raise EncodingError, "String too long: #{n}"
402
+ end
403
+ i = Utils.big_endian_to_int i
404
+
405
+ i = i > INT_MAX ? (i-TT256) : i
406
+ raise EncodingError, "Number out of range: #{i}" if i > INT_MAX || i < INT_MIN
407
+ i
408
+ when true
409
+ 1
410
+ when false, nil
411
+ 0
412
+ else
413
+ raise EncodingError, "Cannot decode int: #{n}"
414
+ end
415
+ end
416
+
417
+ end
418
+
419
+ end # module Abi
420
+ end # module Ethlite
421
+
422
+
423
+
@@ -0,0 +1,32 @@
1
+
2
+ module Ethlite
3
+ module Abi
4
+ module Constant
5
+
6
+ BYTE_EMPTY = "".freeze
7
+ BYTE_ZERO = "\x00".freeze
8
+ BYTE_ONE = "\x01".freeze
9
+
10
+ TT32 = 2**32
11
+ TT40 = 2**40
12
+ TT160 = 2**160
13
+ TT256 = 2**256
14
+ TT64M1 = 2**64 - 1
15
+
16
+ UINT_MAX = 2**256 - 1
17
+ UINT_MIN = 0
18
+ INT_MAX = 2**255 - 1
19
+ INT_MIN = -2**255
20
+
21
+ HASH_ZERO = ("\x00"*32).freeze
22
+
23
+ PUBKEY_ZERO = ("\x00"*32).freeze
24
+ PRIVKEY_ZERO = ("\x00"*32).freeze
25
+ PRIVKEY_ZERO_HEX = ('0'*64).freeze
26
+
27
+ CONTRACT_CODE_SIZE_LIMIT = 0x6000
28
+
29
+ end
30
+
31
+ end # module Abi
32
+ end # module Ethlite