ethlite 0.2.2 → 0.2.4

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: bdacaafee691ecb72746721479d637e03b211c4afbcde0c4c938edc50695ccf8
4
- data.tar.gz: 607cb3eda84667009ac105e998afb56a4af0dfa23dcc0a47264623e8e3409c21
3
+ metadata.gz: a6a9601ad8c91c592541ffc721dbe9bbb8572683ef88c995a1bb810f7da79e33
4
+ data.tar.gz: 4ddf8c5a91c9a370e580bc9519f4d7c9832f863f31e4dfb8fa2b0505c2c6d6e0
5
5
  SHA512:
6
- metadata.gz: 459910398810dfa9ff9dab030feb0a185a03afa5d440656cc37ef4479dd54f49e0cd16b9c7e018b72d3a9507c109deb01e234f408e5b13131f14d044701868be
7
- data.tar.gz: 6783748547fa38964c62f695df60d4d5f8533fceb650c212e4ae0d6f20619cd9f42dea747f1a0c3bc28512b336998cde5c80fce78e4c3445a6e3723e05a5c54d
6
+ metadata.gz: 12d4cd45f40f8ecf3835f058e2ac5d4e9a9b361e3cd91fd5bca193e982c7fd726ff3ffab08ed7bedb543c3800e76808364c51f2992d4971816629ac170f700f6
7
+ data.tar.gz: 236164ce176d5b50187e7402729a895130354f929df269e3b9d7b04472300b1661b9992a5579ba53064cbe0b7aee95e21aeeaae65225519ca55707caad771533
data/Manifest.txt CHANGED
@@ -2,15 +2,13 @@ CHANGELOG.md
2
2
  Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
- lib/digest/keccak256.rb
5
+ lib/digest/keccak.rb
6
6
  lib/digest/sha3.rb
7
7
  lib/ethlite.rb
8
8
  lib/ethlite/abi/abi_coder.rb
9
- lib/ethlite/abi/constant.rb
10
- lib/ethlite/abi/exceptions.rb
11
9
  lib/ethlite/abi/type.rb
12
10
  lib/ethlite/abi/utils.rb
11
+ lib/ethlite/constant.rb
13
12
  lib/ethlite/contract.rb
14
- lib/ethlite/rpc.rb
15
- lib/ethlite/utility.rb
16
13
  lib/ethlite/version.rb
14
+ lib/jsonrpc/jsonrpc.rb
data/Rakefile CHANGED
@@ -21,7 +21,7 @@ Hoe.spec 'ethlite' do
21
21
  self.extra_deps = [
22
22
  ['cocos'],
23
23
  ## ['keccak'], -- try using bundled ruby version for now
24
- ['rlp'],
24
+ ['rlp-lite'],
25
25
  ]
26
26
 
27
27
  self.licenses = ['Public Domain']
@@ -8,8 +8,15 @@
8
8
  ## require 'digest'
9
9
 
10
10
 
11
+
12
+ ##
13
+ # note: use KeccakLite (or KeccakZero? KeccakSHA3?) instead of Keccak
14
+ # to allow usage of native w/ c-extension Keccak and "lite" version
15
+
16
+
17
+
11
18
  module Digest
12
- class Keccak256 < Digest::Class
19
+ class KeccakLite < Digest::Class
13
20
  PILN = [10, 7, 11, 17, 18, 3, 5, 16,
14
21
  8, 21, 24, 4, 15, 23, 19, 13,
15
22
  12, 2, 20, 14, 22, 9, 6, 1]
@@ -27,16 +34,18 @@ module Digest
27
34
  0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
28
35
  0x8000000000008080, 0x0000000080000001, 0x8000000080008008]
29
36
 
30
- def initialize
31
- @size = 256 / 8
37
+ ## note: changed initialize to use param hash_size = 512
38
+ ## do NOT hard-code only 256 bit
39
+ def initialize( hash_size = 512 )
40
+ @size = hash_size / 8
32
41
  @buffer = ''
33
42
  end
34
43
 
35
- def << s
44
+ def <<( s )
36
45
  @buffer << s
37
46
  self
38
47
  end
39
- alias update <<
48
+ alias_method :update, :<<
40
49
 
41
50
  def reset
42
51
  @buffer.clear
@@ -44,37 +53,40 @@ module Digest
44
53
  end
45
54
 
46
55
  def finish
47
- s = Array.new 25, 0
56
+ s = Array.new( 25, 0 )
48
57
  width = 200 - @size * 2
58
+
59
+ ### note: padding changed in final FIPS PUB 202 standard
60
+ ## from "\x01" to "\x06"
49
61
  padding = "\x01"
50
62
 
51
63
  buffer = @buffer
52
64
  buffer << padding << "\0" * (width - buffer.size % width)
53
65
  buffer[-1] = (buffer[-1].ord | 0x80).chr
54
66
 
55
- 0.step buffer.size - 1, width do |j|
56
- quads = buffer[j, width].unpack 'Q*'
67
+ 0.step( buffer.size - 1, width ) do |j|
68
+ quads = buffer[j, width].unpack( 'Q*' )
57
69
  (width / 8).times do |i|
58
70
  s[i] ^= quads[i]
59
71
  end
60
72
 
61
- keccak s
73
+ _keccak( s )
62
74
  end
63
75
 
64
76
  s.pack('Q*')[0, @size]
65
77
  end
66
78
 
67
79
  private
68
- def keccak s
69
- 24.times.each_with_object [] do |round, a|
80
+ def _keccak( s )
81
+ 24.times.each_with_object( [] ) do |round, a|
70
82
  # Theta
71
83
  5.times do |i|
72
84
  a[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]
73
85
  end
74
86
 
75
87
  5.times do |i|
76
- t = a[(i + 4) % 5] ^ rotate(a[(i + 1) % 5], 1)
77
- 0.step 24, 5 do |j|
88
+ t = a[(i + 4) % 5] ^ _rotate(a[(i + 1) % 5], 1)
89
+ 0.step( 24, 5 ) do |j|
78
90
  s[j + i] ^= t
79
91
  end
80
92
  end
@@ -84,12 +96,12 @@ module Digest
84
96
  24.times do |i|
85
97
  j = PILN[i]
86
98
  a[0] = s[j]
87
- s[j] = rotate t, ROTC[i]
99
+ s[j] = _rotate( t, ROTC[i] )
88
100
  t = a[0]
89
101
  end
90
102
 
91
103
  # Chi
92
- 0.step 24, 5 do |j|
104
+ 0.step( 24, 5 ) do |j|
93
105
  5.times do |i|
94
106
  a[i] = s[j + i]
95
107
  end
@@ -104,8 +116,10 @@ module Digest
104
116
  end
105
117
  end
106
118
 
107
- def rotate x, y
119
+ def _rotate( x, y )
108
120
  (x << y | x >> 64 - y) & (1 << 64) - 1
109
121
  end
110
- end
111
- end
122
+
123
+
124
+ end # class KeccakLite
125
+ end # module Digest
data/lib/digest/sha3.rb CHANGED
@@ -6,8 +6,13 @@
6
6
 
7
7
  ## require 'digest'
8
8
 
9
+ ##
10
+ # note: use SHA3Lite (or SHA3Zero? ZeroSHA3?) instead of SHA3
11
+ # to allow usage of native w/ c-extension SHA3 and "lite" version
12
+
13
+
9
14
  module Digest
10
- class SHA3 < Digest::Class
15
+ class SHA3Lite < Digest::Class
11
16
  PILN = [10, 7, 11, 17, 18, 3, 5, 16,
12
17
  8, 21, 24, 4, 15, 23, 19, 13,
13
18
  12, 2, 20, 14, 22, 9, 6, 1]
@@ -25,16 +30,16 @@ module Digest
25
30
  0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
26
31
  0x8000000000008080, 0x0000000080000001, 0x8000000080008008]
27
32
 
28
- def initialize hash_size = 512
29
- @size = hash_size / 8
30
- @buffer = ''
33
+ def initialize( hash_size = 512 )
34
+ @size = hash_size / 8
35
+ @buffer = '' ## todo/check: make sure buffer is with encoding BINARY - why? why not?
31
36
  end
32
37
 
33
- def << s
38
+ def <<( s )
34
39
  @buffer << s
35
40
  self
36
41
  end
37
- alias update <<
42
+ alias_method :update, :<<
38
43
 
39
44
  def reset
40
45
  @buffer.clear
@@ -42,36 +47,40 @@ module Digest
42
47
  end
43
48
 
44
49
  def finish
45
- s = Array.new 25, 0
50
+ s = Array.new( 25, 0 )
46
51
  width = 200 - @size * 2
47
52
 
53
+ ### note: padding changed in final FIPS PUB 202 standard
54
+ ## from "\x01" to "\x06"
55
+ padding = "\x06"
56
+
48
57
  buffer = @buffer
49
- buffer << "\x06" << "\0" * (width - buffer.size % width)
58
+ buffer << padding << "\0" * (width - buffer.size % width)
50
59
  buffer[-1] = (buffer[-1].ord | 0x80).chr
51
60
 
52
- 0.step buffer.size - 1, width do |j|
53
- quads = buffer[j, width].unpack 'Q*'
61
+ 0.step( buffer.size - 1, width ) do |j|
62
+ quads = buffer[j, width].unpack( 'Q*' )
54
63
  (width / 8).times do |i|
55
64
  s[i] ^= quads[i]
56
65
  end
57
66
 
58
- keccak s
67
+ _keccak( s )
59
68
  end
60
69
 
61
70
  s.pack('Q*')[0, @size]
62
71
  end
63
72
 
64
- private
65
- def keccak s
66
- 24.times.each_with_object [] do |round, a|
73
+ private
74
+ def _keccak( s )
75
+ 24.times.each_with_object( [] ) do |round, a|
67
76
  # Theta
68
77
  5.times do |i|
69
78
  a[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]
70
79
  end
71
80
 
72
81
  5.times do |i|
73
- t = a[(i + 4) % 5] ^ rotate(a[(i + 1) % 5], 1)
74
- 0.step 24, 5 do |j|
82
+ t = a[(i + 4) % 5] ^ _rotate(a[(i + 1) % 5], 1)
83
+ 0.step( 24, 5 ) do |j|
75
84
  s[j + i] ^= t
76
85
  end
77
86
  end
@@ -81,12 +90,12 @@ module Digest
81
90
  24.times do |i|
82
91
  j = PILN[i]
83
92
  a[0] = s[j]
84
- s[j] = rotate t, ROTC[i]
93
+ s[j] = _rotate( t, ROTC[i] )
85
94
  t = a[0]
86
95
  end
87
96
 
88
97
  # Chi
89
- 0.step 24, 5 do |j|
98
+ 0.step( 24, 5 ) do |j|
90
99
  5.times do |i|
91
100
  a[i] = s[j + i]
92
101
  end
@@ -101,8 +110,9 @@ module Digest
101
110
  end
102
111
  end
103
112
 
104
- def rotate x, y
113
+ def _rotate( x, y )
105
114
  (x << y | x >> 64 - y) & (1 << 64) - 1
106
115
  end
107
- end
108
- end
116
+
117
+ end # class SHA3Lite
118
+ end # module Digest
@@ -14,8 +14,11 @@ module Ethlite
14
14
 
15
15
  include Constant
16
16
 
17
+
17
18
  class EncodingError < StandardError; end
18
19
  class DecodingError < StandardError; end
20
+ class ValueError < StandardError; end
21
+
19
22
  class ValueOutOfBounds < ValueError; end
20
23
 
21
24
  ##
@@ -2,17 +2,16 @@ module Ethlite
2
2
  module Abi
3
3
  class Type
4
4
 
5
- class ParseError < StandardError;
6
- end
5
+ class ParseError < StandardError; end
6
+
7
7
 
8
- class <<self
9
8
  ##
10
9
  # Crazy regexp to seperate out base type component (eg. uint), size (eg.
11
10
  # 256, 128x128, nil), array component (eg. [], [45], nil)
12
11
  #
13
- def parse(type)
12
+ def self.parse( type )
14
13
 
15
- return parse('uint256') if type=='trcToken'
14
+ return parse('uint256') if type=='trcToken'
16
15
 
17
16
  if type =~ /^\((.*)\)((\[[0-9]*\])*)/
18
17
  return Tuple.parse $1, $2.scan(/\[[0-9]*\]/)
@@ -56,10 +55,10 @@ module Ethlite
56
55
  new(base, sub, dims.map {|x| x[1...-1].to_i})
57
56
  end
58
57
 
59
- def size_type
58
+ def self.size_type
60
59
  @size_type ||= new('uint', 256, [])
61
60
  end
62
- end
61
+
63
62
 
64
63
  attr :base, :sub, :dims
65
64
 
@@ -69,7 +68,7 @@ module Ethlite
69
68
  # @param dims [Array[Integer]] dimensions of array type, e.g. [1,2,0]
70
69
  # for uint256[1][2][], [] for non-array type
71
70
  #
72
- def initialize(base, sub, dims)
71
+ def initialize( base, sub, dims )
73
72
  @base = base
74
73
  @sub = sub
75
74
  @dims = dims
@@ -123,7 +122,7 @@ module Ethlite
123
122
 
124
123
  class Tuple < Type
125
124
 
126
- def self.parse types, dims
125
+ def self.parse( types, dims )
127
126
 
128
127
  depth = 0
129
128
  collected = []
@@ -156,7 +155,8 @@ module Ethlite
156
155
  end
157
156
 
158
157
  attr_reader :types, :parsed_types
159
- def initialize types, dims
158
+
159
+ def initialize( types, dims )
160
160
  super('tuple', '', dims)
161
161
  @types = types
162
162
  @parsed_types = types.map{|t| Type.parse t}
@@ -188,14 +188,11 @@ module Ethlite
188
188
  subtype.dynamic? ? nil : dims.last * subtype.size
189
189
  end
190
190
  end
191
-
192
-
193
191
  end
194
192
 
195
193
  def subtype
196
194
  @subtype ||= Tuple.new(types, dims[0...-1])
197
195
  end
198
-
199
196
  end
200
197
 
201
198
 
@@ -12,16 +12,16 @@ module Abi
12
12
  def keccak256(x)
13
13
  # Digest::SHA3.new(256).digest(x)
14
14
  ## Digest::Keccak.digest(x, 256)
15
- Digest::Keccak256.digest( x )
15
+ Digest::KeccakLite.new(256).digest( x )
16
16
  end
17
17
 
18
- =begin
19
- ## check where required / in use - what for?
18
+ ## todo/check where required / in use - what for?
20
19
  def keccak512(x)
21
20
  # Digest::SHA3.new(512).digest(x)
22
- Digest::Keccak.digest(x, 512)
21
+ # Digest::Keccak.digest(x, 512)
22
+ Digest::KeccakLite.new(512).digest( x )
23
23
  end
24
- =end
24
+
25
25
 
26
26
  def keccak256_rlp(x)
27
27
  keccak256 RLP.encode(x)
@@ -56,44 +56,50 @@ module Abi
56
56
  end
57
57
 
58
58
  def to_signed(i)
59
- i > Constant::INT_MAX ? (i-Constant::TT256) : i
59
+ i > INT_MAX ? (i-TT256) : i
60
60
  end
61
61
 
62
- def base58_check_to_bytes(s)
63
- leadingzbytes = s.match(/\A1*/)[0]
64
- data = Constant::BYTE_ZERO * leadingzbytes.size + BaseConvert.convert(s, 58, 256)
65
-
66
- raise ChecksumError, "double sha256 checksum doesn't match" unless double_sha256(data[0...-4])[0,4] == data[-4..-1]
67
- data[1...-4]
68
- end
69
-
70
- def bytes_to_base58_check(bytes, magicbyte=0)
71
- bs = "#{magicbyte.chr}#{bytes}"
72
- leadingzbytes = bs.match(/\A#{Constant::BYTE_ZERO}*/)[0]
73
- checksum = double_sha256(bs)[0,4]
74
- '1'*leadingzbytes.size + BaseConvert.convert("#{bs}#{checksum}", 256, 58)
75
- end
76
62
 
77
63
  def ceil32(x)
78
64
  x % 32 == 0 ? x : (x + 32 - x%32)
79
65
  end
80
66
 
81
67
  def encode_hex(b)
82
- RLP::Utils.encode_hex b
68
+ raise TypeError, "Value must be an instance of String" unless b.instance_of?(String)
69
+ b.unpack("H*").first
83
70
  end
84
71
 
85
- def decode_hex(s)
86
- RLP::Utils.decode_hex s
72
+ def decode_hex(str)
73
+ raise TypeError, "Value must be an instance of string" unless sstr.instance_of?(String)
74
+ raise TypeError, 'Non-hexadecimal digit found' unless str =~ /\A[0-9a-fA-F]*\z/
75
+ [str].pack("H*")
76
+ end
77
+
78
+
79
+
80
+
81
+ def int_to_big_endian(n)
82
+ RLP::Sedes.big_endian_int.serialize n
87
83
  end
88
84
 
89
85
  def big_endian_to_int(s)
90
86
  RLP::Sedes.big_endian_int.deserialize s.sub(/\A(\x00)+/, '')
91
87
  end
92
88
 
93
- def int_to_big_endian(n)
94
- RLP::Sedes.big_endian_int.serialize n
89
+
90
+ def encode_int(n)
91
+ raise ArgumentError, "Integer invalid or out of range: #{n}" unless n.is_a?(Integer) && n >= 0 && n <= UINT_MAX
92
+ int_to_big_endian n
95
93
  end
96
94
 
95
+ def decode_int(v)
96
+ raise ArgumentError, "No leading zero bytes allowed for integers" if v.size > 0 && (v[0] == BYTE_ZERO || v[0] == 0)
97
+ big_endian_to_int v
98
+ end
99
+
100
+
101
+
102
+
97
103
  def lpad(x, symbol, l)
98
104
  return x if x.size >= l
99
105
  symbol * (l - x.size) + x
@@ -124,15 +130,6 @@ module Abi
124
130
  zpad_int x, 20
125
131
  end
126
132
 
127
- def encode_int(n)
128
- raise ArgumentError, "Integer invalid or out of range: #{n}" unless n.is_a?(Integer) && n >= 0 && n <= UINT_MAX
129
- int_to_big_endian n
130
- end
131
-
132
- def decode_int(v)
133
- raise ArgumentError, "No leading zero bytes allowed for integers" if v.size > 0 && (v[0] == Constant::BYTE_ZERO || v[0] == 0)
134
- big_endian_to_int v
135
- end
136
133
 
137
134
  def bytearray_to_int(arr)
138
135
  o = 0
@@ -148,6 +145,7 @@ module Abi
148
145
  bytes.unpack('C*')
149
146
  end
150
147
 
148
+
151
149
  def coerce_to_int(x)
152
150
  if x.is_a?(Numeric)
153
151
  x
@@ -178,19 +176,6 @@ module Abi
178
176
  end
179
177
  end
180
178
 
181
- def normalize_address(x, allow_blank: false)
182
- address = Address.new(x)
183
- raise ValueError, "address is blank" if !allow_blank && address.blank?
184
- address.to_bytes
185
- end
186
-
187
- def mk_contract_address(sender, nonce)
188
- keccak256_rlp([normalize_address(sender), nonce])[12..-1]
189
- end
190
-
191
- def mk_metropolis_contract_address(sender, initcode)
192
- keccak256(normalize_address(sender) + initcode)[12..-1]
193
- end
194
179
 
195
180
 
196
181
  def parse_int_or_hex(s)
@@ -203,6 +188,24 @@ module Abi
203
188
  end
204
189
  end
205
190
 
191
+
192
+ =begin
193
+ ## add? moved over from the old module Utility
194
+ def hex( num )
195
+ '0x' + num.to_s(16)
196
+ end
197
+
198
+ def from_hex( h )
199
+ h.nil? ? 0 : (h.kind_of?(String) ? h.to_i(16) : h)
200
+ end
201
+ =end
202
+
203
+
204
+ def remove_0x_head( s )
205
+ return s if !s || s.length<2
206
+ s[0,2] == '0x' ? s[2..-1] : s
207
+ end
208
+
206
209
  def normalize_hex_without_prefix(s)
207
210
  if s[0,2] == '0x'
208
211
  (s.size % 2 == 1 ? '0' : '') + s[2..-1]
@@ -211,6 +214,7 @@ module Abi
211
214
  end
212
215
  end
213
216
 
217
+
214
218
  def function_signature method_name, arg_types
215
219
  "#{method_name}(#{arg_types.join(',')})"
216
220
  end
@@ -218,8 +222,6 @@ module Abi
218
222
  def signature_hash signature, length=64
219
223
  encode_hex(keccak256(signature))[0...length]
220
224
  end
221
-
222
-
223
225
  end
224
226
 
225
227
  end # module Abi
@@ -0,0 +1,38 @@
1
+
2
+ module Ethlite
3
+ module Constant
4
+
5
+
6
+ ## todo/check - use encoding -ascii-8bit for source file or ? - why? why not?
7
+ ## use #b/.b to ensure binary encoding? - why? why not?
8
+
9
+ ## todo/check: use auto-freeze string literals magic comment - why? why not?
10
+ BYTE_EMPTY = "".b.freeze
11
+ BYTE_ZERO = "\x00".b.freeze
12
+ BYTE_ONE = "\x01".b.freeze
13
+
14
+
15
+ TT32 = 2**32
16
+ TT40 = 2**40
17
+ TT160 = 2**160
18
+ TT256 = 2**256
19
+ TT64M1 = 2**64 - 1
20
+
21
+ UINT_MAX = 2**256 - 1
22
+ UINT_MIN = 0
23
+ INT_MAX = 2**255 - 1
24
+ INT_MIN = -2**255
25
+
26
+ HASH_ZERO = ("\x00"*32).b.freeze
27
+
28
+
29
+ PUBKEY_ZERO = ("\x00"*32).b.freeze
30
+ PRIVKEY_ZERO = ("\x00"*32).b.freeze
31
+
32
+ PRIVKEY_ZERO_HEX = ('0'*64).freeze
33
+
34
+ CONTRACT_CODE_SIZE_LIMIT = 0x6000
35
+
36
+
37
+ end # module Constant
38
+ end # module Ethlite
@@ -1,38 +1,54 @@
1
1
  module Ethlite
2
2
  class ContractMethod
3
- include Utility
4
3
 
5
- attr_reader :abi,
6
- :signature,
4
+ def self.parse_abi( abi )
5
+ ## convenience helper - auto-convert to json if string passed in
6
+ abi = JSON.parse( abi ) if abi.is_a?( String )
7
+
8
+ name = abi['name']
9
+ constant = !!abi['constant'] || abi['stateMutability']=='view'
10
+ input_types = abi['inputs'] ? abi['inputs'].map{|a| _parse_component_type( a ) } : []
11
+ output_types = abi['outputs'] ? abi['outputs'].map{|a| _parse_component_type( a ) } : []
12
+ type = abi['type'] || 'function'
13
+
14
+ new( name, inputs: input_types,
15
+ outputs: output_types,
16
+ constant: constant,
17
+ type: type )
18
+ end
19
+
20
+ def self._parse_component_type( argument )
21
+ if argument['type'] =~ /^tuple((\[[0-9]*\])*)/
22
+ argument['components'] ? "(#{argument['components'].collect{ |c| _parse_component_type( c ) }.join(',')})#{$1}"
23
+ : "()#{$1}"
24
+ else
25
+ argument['type']
26
+ end
27
+ end
28
+
29
+
30
+
31
+
32
+ attr_reader :signature,
7
33
  :name,
8
34
  :signature_hash,
9
35
  :input_types,
10
36
  :output_types,
11
37
  :constant
12
38
 
13
- def initialize( abi )
14
- ## convenience helper - auto-convert to json if string passed in
15
- abi = JSON.parse( abi ) if abi.is_a?( String )
39
+ def initialize( name, inputs:,
40
+ outputs: [],
41
+ constant: true,
42
+ type: 'function' )
43
+ @name = name
44
+ @constant = constant
45
+ @input_types = inputs
46
+ @output_types = outputs
16
47
 
17
- @abi = abi
18
- @name = abi['name']
19
- @constant = !!abi['constant'] || abi['stateMutability']=='view'
20
- @input_types = abi['inputs'] ? abi['inputs'].map{|a| parse_component_type a } : []
21
- @output_types = abi['outputs'] ? abi['outputs'].map{|a| parse_component_type a } : nil
22
48
  @signature = Abi::Utils.function_signature( @name, @input_types )
23
- @signature_hash = Abi::Utils.signature_hash( @signature, abi['type']=='event' ? 64 : 8)
49
+ @signature_hash = Abi::Utils.signature_hash( @signature, type=='event' ? 64 : 8)
24
50
  end
25
51
 
26
- def parse_component_type( argument )
27
- if argument['type'] =~ /^tuple((\[[0-9]*\])*)/
28
- argument['components'] ? "(#{argument['components'].collect{|c| parse_component_type( c ) }.join(',')})#{$1}"
29
- : "()#{$1}"
30
- else
31
- argument['type']
32
- end
33
- end
34
-
35
-
36
52
  def do_call( rpc, contract_address, args )
37
53
  data = '0x' + @signature_hash + Abi::Utils.encode_hex(
38
54
  Abi::AbiCoder.encode_abi(@input_types, args) )
@@ -47,7 +63,7 @@
47
63
  puts "response:"
48
64
  pp response
49
65
 
50
- string_data = [remove_0x_head(response)].pack('H*')
66
+ string_data = [Abi::Utils.remove_0x_head(response)].pack('H*')
51
67
  return nil if string_data.empty?
52
68
 
53
69
  result = Abi::AbiCoder.decode_abi( @output_types, string_data )
@@ -3,7 +3,7 @@
3
3
  module Ethlite
4
4
  MAJOR = 0
5
5
  MINOR = 2
6
- PATCH = 2
6
+ PATCH = 4
7
7
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
8
 
9
9
  def self.version
data/lib/ethlite.rb CHANGED
@@ -10,28 +10,27 @@ require 'openssl'
10
10
  require 'digest'
11
11
 
12
12
  ## 3rd party gems
13
- require 'rlp' ## gem rlp - see https://rubygems.org/gems/rlp
13
+ require 'rlp-lite'
14
14
 
15
15
  ## bundled require 'digest/keccak' ## gem keccak - see https://rubygems.org/gems/keccak
16
- require 'digest/keccak256'
16
+ require_relative 'digest/keccak'
17
+ require_relative 'digest/sha3'
17
18
 
19
+ require_relative 'jsonrpc/jsonrpc'
18
20
 
19
21
 
20
22
 
21
23
  ## our own code
22
24
  require_relative 'ethlite/version' # note: let version always go first
23
25
 
26
+ require_relative 'ethlite/constant'
27
+
24
28
 
25
29
  require_relative 'ethlite/abi/type'
26
- require_relative 'ethlite/abi/constant'
27
- require_relative 'ethlite/abi/exceptions'
28
30
  require_relative 'ethlite/abi/utils'
29
31
  require_relative 'ethlite/abi/abi_coder'
30
32
 
31
33
 
32
- require_relative 'ethlite/rpc'
33
-
34
- require_relative 'ethlite/utility'
35
34
  require_relative 'ethlite/contract'
36
35
 
37
36
 
@@ -39,8 +38,14 @@ require_relative 'ethlite/contract'
39
38
 
40
39
  module Ethlite
41
40
  class Configuration
42
- def rpc() @rpc || Rpc.new( ENV['INFURA_URI'] ); end
43
- def rpc=(value) @rpc = value; end
41
+ def rpc() @rpc || JsonRpc.new( ENV['INFURA_URI'] ); end
42
+ def rpc=(value)
43
+ @rpc = if value.is_a?( String )
44
+ JsonRpc.new( value ) ## auto-wrap in (built-in/simple) jsonrpc client/serverproxy
45
+ else
46
+ value
47
+ end
48
+ end
44
49
  end # class Configuration
45
50
 
46
51
 
@@ -0,0 +1,48 @@
1
+
2
+ ###
3
+ # simple JsonRpc client
4
+ #
5
+ # see https://www.jsonrpc.org/specification
6
+ # https://en.wikipedia.org/wiki/JSON-RPC
7
+
8
+
9
+
10
+ class JsonRpc
11
+ def initialize( uri )
12
+ @uri = uri ## assume uri always as string for now
13
+ @request_id = 1
14
+ end
15
+
16
+
17
+ def request( method, params=[] )
18
+
19
+ data = { jsonrpc: '2.0',
20
+ method: method,
21
+ params: params,
22
+ id: @request_id }
23
+
24
+ @request_id += 1
25
+
26
+ puts "json POST payload:"
27
+ puts data.to_json
28
+
29
+ response = Webclient.post( @uri, json: data )
30
+
31
+
32
+ if response.status.nok?
33
+ raise "Error code #{response.status.code} on request #{@uri} #{data}"
34
+ end
35
+
36
+
37
+ body = JSON.parse( response.body, max_nesting: 1500 )
38
+
39
+ if body['result']
40
+ body['result']
41
+ elsif body['error']
42
+ raise "Error #{@uri} #{body['error']} on request #{@uri} #{data}"
43
+ else
44
+ raise "No response on request #{@uri} #{data}"
45
+ end
46
+ end # method request
47
+ end # class JsonRpc
48
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ethlite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-14 00:00:00.000000000 Z
11
+ date: 2022-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cocos
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rlp
28
+ name: rlp-lite
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -86,18 +86,16 @@ files:
86
86
  - Manifest.txt
87
87
  - README.md
88
88
  - Rakefile
89
- - lib/digest/keccak256.rb
89
+ - lib/digest/keccak.rb
90
90
  - lib/digest/sha3.rb
91
91
  - lib/ethlite.rb
92
92
  - lib/ethlite/abi/abi_coder.rb
93
- - lib/ethlite/abi/constant.rb
94
- - lib/ethlite/abi/exceptions.rb
95
93
  - lib/ethlite/abi/type.rb
96
94
  - lib/ethlite/abi/utils.rb
95
+ - lib/ethlite/constant.rb
97
96
  - lib/ethlite/contract.rb
98
- - lib/ethlite/rpc.rb
99
- - lib/ethlite/utility.rb
100
97
  - lib/ethlite/version.rb
98
+ - lib/jsonrpc/jsonrpc.rb
101
99
  homepage: https://github.com/pixelartexchange/artbase
102
100
  licenses:
103
101
  - Public Domain
@@ -1,32 +0,0 @@
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
@@ -1,29 +0,0 @@
1
-
2
- module Ethlite
3
- module Abi
4
-
5
- class DeprecatedError < StandardError; end
6
- class ChecksumError < StandardError; end
7
- class FormatError < StandardError; end
8
- class ValidationError < StandardError; end
9
- class ValueError < StandardError; end
10
- class AssertError < StandardError; end
11
-
12
- class UnknownParentError < StandardError; end
13
- class InvalidBlock < ValidationError; end
14
- class InvalidUncles < ValidationError; end
15
-
16
- class InvalidTransaction < ValidationError; end
17
- class UnsignedTransactionError < InvalidTransaction; end
18
- class InvalidNonce < InvalidTransaction; end
19
- class InsufficientStartGas < InvalidTransaction; end
20
- class InsufficientBalance < InvalidTransaction; end
21
- class BlockGasLimitReached < InvalidTransaction; end
22
-
23
- class InvalidSPVProof < ValidationError; end
24
-
25
- class ContractCreationFailed < StandardError; end
26
- class TransactionFailed < StandardError; end
27
-
28
- end # module Abi
29
- end # module Ethlite
data/lib/ethlite/rpc.rb DELETED
@@ -1,48 +0,0 @@
1
- module Ethlite
2
-
3
- class Rpc
4
- def initialize( uri )
5
- @client_id = Random.rand( 10000000 )
6
-
7
- @uri = URI.parse( uri )
8
- end
9
-
10
- def request( method, params=[] )
11
- opts = {}
12
- if @uri.instance_of?( URI::HTTPS )
13
- opts[:use_ssl] = true
14
- opts[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
15
- end
16
-
17
- Net::HTTP.start( @uri.host, @uri.port, **opts ) do |http|
18
- headers = {"Content-Type" => "application/json"}
19
- request = Net::HTTP::Post.new( @uri.request_uri, headers )
20
-
21
- json = { jsonrpc: '2.0',
22
- method: method,
23
- params: params,
24
- id: @client_id }.to_json
25
-
26
- puts "json POST payload:"
27
- puts json
28
-
29
- request.body = json
30
- response = http.request( request )
31
-
32
- raise "Error code #{response.code} on request #{@uri.to_s} #{request.body}" unless response.kind_of?( Net::HTTPOK )
33
-
34
- body = JSON.parse(response.body, max_nesting: 1500)
35
-
36
- if body['result']
37
- body['result']
38
- elsif body['error']
39
- raise "Error #{@uri.to_s} #{body['error']} on request #{@uri.to_s} #{request.body}"
40
- else
41
- raise "No response on request #{@uri.to_s} #{request.body}"
42
- end
43
- end
44
- end
45
- end # class Rpc
46
-
47
- end # module Ethlite
48
-
@@ -1,23 +0,0 @@
1
- module Ethlite
2
-
3
- module Utility
4
-
5
- def hex( num )
6
- '0x' + num.to_s(16)
7
- end
8
-
9
- def from_hex( h )
10
- h.nil? ? 0 : (h.kind_of?(String) ? h.to_i(16) : h)
11
- end
12
-
13
- def remove_0x_head( s )
14
- return s if !s || s.length<2
15
- s[0,2] == '0x' ? s[2..-1] : s
16
- end
17
-
18
-
19
- def wei_to_ether( wei )
20
- 1.0 * wei / 10**18
21
- end
22
- end
23
- end # module Ethlite