web3ethereum 1.0.0

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.
@@ -0,0 +1,118 @@
1
+ # -*- encoding : ascii-8bit -*-
2
+
3
+ module Web3::Eth::Abi
4
+ class Type
5
+
6
+ class ParseError < StandardError;
7
+ end
8
+
9
+ class <<self
10
+ ##
11
+ # Crazy regexp to seperate out base type component (eg. uint), size (eg.
12
+ # 256, 128x128, nil), array component (eg. [], [45], nil)
13
+ #
14
+ def parse(type)
15
+ _, base, sub, dimension = /([a-z]*)([0-9]*x?[0-9]*)((\[[0-9]*\])*)/.match(type).to_a
16
+
17
+ dims = dimension.scan(/\[[0-9]*\]/)
18
+ raise ParseError, "Unknown characters found in array declaration" if dims.join != dimension
19
+
20
+ case base
21
+ when ''
22
+ return parse 'address'
23
+ when 'string'
24
+ raise ParseError, "String type must have no suffix or numerical suffix" unless sub.empty?
25
+ when 'bytes'
26
+ raise ParseError, "Maximum 32 bytes for fixed-length string or bytes" unless sub.empty? || sub.to_i <= 32
27
+ when 'uint', 'int'
28
+ raise ParseError, "Integer type must have numerical suffix" unless sub =~ /\A[0-9]+\z/
29
+
30
+ size = sub.to_i
31
+ raise ParseError, "Integer size out of bounds" unless size >= 8 && size <= 256
32
+ raise ParseError, "Integer size must be multiple of 8" unless size % 8 == 0
33
+ when 'fixed', 'ufixed'
34
+ raise ParseError, "Fixed type must have suffix of form <high>x<low>, e.g. 128x128" unless sub =~ /\A[0-9]+x[0-9]+\z/
35
+
36
+ high, low = sub.split('x').map(&:to_i)
37
+ total = high + low
38
+
39
+ raise ParseError, "Fixed size out of bounds (max 32 bytes)" unless total >= 8 && total <= 256
40
+ raise ParseError, "Fixed high/low sizes must be multiples of 8" unless high % 8 == 0 && low % 8 == 0
41
+ when 'hash'
42
+ raise ParseError, "Hash type must have numerical suffix" unless sub =~ /\A[0-9]+\z/
43
+ when 'address'
44
+ raise ParseError, "Address cannot have suffix" unless sub.empty?
45
+ when 'bool'
46
+ raise ParseError, "Bool cannot have suffix" unless sub.empty?
47
+ else
48
+ raise ParseError, "Unrecognized type base: #{base}"
49
+ end
50
+
51
+ new(base, sub, dims.map {|x| x[1...-1].to_i})
52
+ end
53
+
54
+ def size_type
55
+ @size_type ||= new('uint', 256, [])
56
+ end
57
+ end
58
+
59
+ attr :base, :sub, :dims
60
+
61
+ ##
62
+ # @param base [String] base name of type, e.g. uint for uint256[4]
63
+ # @param sub [String] subscript of type, e.g. 256 for uint256[4]
64
+ # @param dims [Array[Integer]] dimensions of array type, e.g. [1,2,0]
65
+ # for uint256[1][2][], [] for non-array type
66
+ #
67
+ def initialize(base, sub, dims)
68
+ @base = base
69
+ @sub = sub
70
+ @dims = dims
71
+ end
72
+
73
+ def ==(another_type)
74
+ base == another_type.base &&
75
+ sub == another_type.sub &&
76
+ dims == another_type.dims
77
+ end
78
+
79
+ ##
80
+ # Get the static size of a type, or nil if dynamic.
81
+ #
82
+ # @return [Integer, NilClass] size of static type, or nil for dynamic
83
+ # type
84
+ #
85
+ def size
86
+ @size ||= if dims.empty?
87
+ if %w(string bytes).include?(base) && sub.empty?
88
+ nil
89
+ else
90
+ 32
91
+ end
92
+ else
93
+ if dims.last == 0 # 0 for dynamic array []
94
+ nil
95
+ else
96
+ subtype.dynamic? ? nil : dims.last * subtype.size
97
+ end
98
+ end
99
+ end
100
+
101
+ def dynamic?
102
+ size.nil?
103
+ end
104
+
105
+ ##
106
+ # Type with one dimension lesser.
107
+ #
108
+ # @example
109
+ # Type.parse("uint256[2][]").subtype # => Type.new('uint', 256, [2])
110
+ #
111
+ # @return [Ethereum::ABI::Type]
112
+ #
113
+ def subtype
114
+ @subtype ||= self.class.new(base, sub, dims[0...-1])
115
+ end
116
+
117
+ end
118
+ end
@@ -0,0 +1,224 @@
1
+ # -*- encoding : ascii-8bit -*-
2
+
3
+ require 'digest'
4
+ require 'digest/sha3'
5
+ require 'openssl'
6
+ require 'rlp'
7
+
8
+ module Web3::Eth::Abi
9
+ module Utils
10
+
11
+ extend self
12
+
13
+ include Constant
14
+
15
+ ##
16
+ # Not the keccak in sha3, although it's underlying lib named SHA3
17
+ #
18
+ def keccak256(x)
19
+ Digest::SHA3.new(256).digest(x)
20
+ end
21
+
22
+ def keccak512(x)
23
+ Digest::SHA3.new(512).digest(x)
24
+ end
25
+
26
+ def keccak256_rlp(x)
27
+ keccak256 RLP.encode(x)
28
+ end
29
+
30
+ def sha256(x)
31
+ Digest::SHA256.digest x
32
+ end
33
+
34
+ def double_sha256(x)
35
+ sha256 sha256(x)
36
+ end
37
+
38
+ def ripemd160(x)
39
+ Digest::RMD160.digest x
40
+ end
41
+
42
+ def hash160(x)
43
+ ripemd160 sha256(x)
44
+ end
45
+
46
+ def hash160_hex(x)
47
+ encode_hex hash160(x)
48
+ end
49
+
50
+ def mod_exp(x, y, n)
51
+ x.to_bn.mod_exp(y, n).to_i
52
+ end
53
+
54
+ def mod_mul(x, y, n)
55
+ x.to_bn.mod_mul(y, n).to_i
56
+ end
57
+
58
+ def to_signed(i)
59
+ i > Constant::INT_MAX ? (i-Constant::TT256) : i
60
+ end
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
+
77
+ def ceil32(x)
78
+ x % 32 == 0 ? x : (x + 32 - x%32)
79
+ end
80
+
81
+ def encode_hex(b)
82
+ RLP::Utils.encode_hex b
83
+ end
84
+
85
+ def decode_hex(s)
86
+ RLP::Utils.decode_hex s
87
+ end
88
+
89
+ def big_endian_to_int(s)
90
+ RLP::Sedes.big_endian_int.deserialize s.sub(/\A(\x00)+/, '')
91
+ end
92
+
93
+ def int_to_big_endian(n)
94
+ RLP::Sedes.big_endian_int.serialize n
95
+ end
96
+
97
+ def lpad(x, symbol, l)
98
+ return x if x.size >= l
99
+ symbol * (l - x.size) + x
100
+ end
101
+
102
+ def rpad(x, symbol, l)
103
+ return x if x.size >= l
104
+ x + symbol * (l - x.size)
105
+ end
106
+
107
+ def zpad(x, l)
108
+ lpad x, BYTE_ZERO, l
109
+ end
110
+
111
+ def zunpad(x)
112
+ x.sub /\A\x00+/, ''
113
+ end
114
+
115
+ def zpad_int(n, l=32)
116
+ zpad encode_int(n), l
117
+ end
118
+
119
+ def zpad_hex(s, l=32)
120
+ zpad decode_hex(s), l
121
+ end
122
+
123
+ def int_to_addr(x)
124
+ zpad_int x, 20
125
+ end
126
+
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
+
137
+ def bytearray_to_int(arr)
138
+ o = 0
139
+ arr.each {|x| o = (o << 8) + x }
140
+ o
141
+ end
142
+
143
+ def int_array_to_bytes(arr)
144
+ arr.pack('C*')
145
+ end
146
+
147
+ def bytes_to_int_array(bytes)
148
+ bytes.unpack('C*')
149
+ end
150
+
151
+ def coerce_to_int(x)
152
+ if x.is_a?(Numeric)
153
+ x
154
+ elsif x.size == 40
155
+ big_endian_to_int decode_hex(x)
156
+ else
157
+ big_endian_to_int x
158
+ end
159
+ end
160
+
161
+ def coerce_to_bytes(x)
162
+ if x.is_a?(Numeric)
163
+ int_to_big_endian x
164
+ elsif x.size == 40
165
+ decode_hex(x)
166
+ else
167
+ x
168
+ end
169
+ end
170
+
171
+ def coerce_addr_to_hex(x)
172
+ if x.is_a?(Numeric)
173
+ encode_hex zpad(int_to_big_endian(x), 20)
174
+ elsif x.size == 40 || x.size == 0
175
+ x
176
+ else
177
+ encode_hex zpad(x, 20)[-20..-1]
178
+ end
179
+ end
180
+
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
+
195
+
196
+ def parse_int_or_hex(s)
197
+ if s.is_a?(Numeric)
198
+ s
199
+ elsif s[0,2] == '0x'
200
+ big_endian_to_int decode_hex(normalize_hex_without_prefix(s))
201
+ else
202
+ s.to_i
203
+ end
204
+ end
205
+
206
+ def normalize_hex_without_prefix(s)
207
+ if s[0,2] == '0x'
208
+ (s.size % 2 == 1 ? '0' : '') + s[2..-1]
209
+ else
210
+ s
211
+ end
212
+ end
213
+
214
+ def function_signature method_name, arg_types
215
+ "#{method_name}(#{arg_types.join(',')})"
216
+ end
217
+
218
+ def signature_hash signature, length=64
219
+ encode_hex(keccak256(signature))[0...length]
220
+ end
221
+
222
+
223
+ end
224
+ end
@@ -0,0 +1,33 @@
1
+ module Web3
2
+ module Eth
3
+
4
+ class Block
5
+
6
+ include Web3::Eth::Utility
7
+
8
+ attr_reader :raw_data
9
+
10
+ def initialize block_data
11
+ @raw_data = block_data
12
+
13
+ block_data.each do |k, v|
14
+ self.instance_variable_set("@#{k}", v)
15
+ self.class.send(:define_method, k, proc {self.instance_variable_get("@#{k}")})
16
+ end
17
+
18
+ @transactions = @transactions.collect {|t| Web3::Eth::Transaction.new t }
19
+
20
+ end
21
+
22
+ def timestamp_time
23
+ Time.at from_hex timestamp
24
+ end
25
+
26
+ def block_number
27
+ from_hex number
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,87 @@
1
+ module Web3
2
+ module Eth
3
+
4
+ class CallTrace
5
+
6
+ include Web3::Eth::Utility
7
+
8
+ attr_reader :raw_data
9
+
10
+ def initialize trace_data
11
+ @raw_data = trace_data
12
+
13
+ trace_data.each do |k, v|
14
+ self.instance_variable_set("@#{k}", v)
15
+ self.class.send(:define_method, k, proc {self.instance_variable_get("@#{k}")})
16
+ end
17
+
18
+ end
19
+
20
+ def value_wei
21
+ from_hex action['value']
22
+ end
23
+
24
+ def value_eth
25
+ wei_to_ether from_hex action['value']
26
+ end
27
+
28
+ def from
29
+ action['from']
30
+ end
31
+
32
+ def to
33
+ action['to']
34
+ end
35
+
36
+ def input
37
+ action['input'] || action['init']
38
+ end
39
+
40
+ def output
41
+ result && result['output']
42
+ end
43
+
44
+ def gas_used
45
+ result && from_hex(result['gasUsed'])
46
+ end
47
+
48
+ def method_hash
49
+ if input && input.length>=10
50
+ input[2...10]
51
+ else
52
+ nil
53
+ end
54
+ end
55
+
56
+ def creates
57
+ action && result && action['init'] && result['address']
58
+ end
59
+
60
+ # suffix # 0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29
61
+ # look http://solidity.readthedocs.io/en/latest/metadata.html for details
62
+ def call_input_data
63
+ if creates && input
64
+ input[/a165627a7a72305820\w{64}0029(\w*)/,1]
65
+ elsif input && input.length>10
66
+ input[10..input.length]
67
+ else
68
+ []
69
+ end
70
+ end
71
+
72
+
73
+ def suicide?
74
+ type=='suicide'
75
+ end
76
+
77
+ def balance_ether
78
+ wei_to_ether action['balance'].to_i(16)
79
+ end
80
+
81
+ def success?
82
+ !raw_data['error']
83
+ end
84
+
85
+ end
86
+ end
87
+ end