ethlite 0.1.0 → 0.2.1

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: 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