web3-hpb 0.0.2
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 +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +26 -0
- data/README.md +87 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/web3/hpb.rb +12 -0
- data/lib/web3/hpb/abi/abi_coder.rb +389 -0
- data/lib/web3/hpb/abi/constant.rb +30 -0
- data/lib/web3/hpb/abi/exceptions.rb +28 -0
- data/lib/web3/hpb/abi/type.rb +90 -0
- data/lib/web3/hpb/abi/utils.rb +224 -0
- data/lib/web3/hpb/block.rb +32 -0
- data/lib/web3/hpb/call_trace.rb +87 -0
- data/lib/web3/hpb/contract.rb +172 -0
- data/lib/web3/hpb/hpb_module.rb +47 -0
- data/lib/web3/hpb/log.rb +30 -0
- data/lib/web3/hpb/rpc.rb +64 -0
- data/lib/web3/hpb/trace_module.rb +26 -0
- data/lib/web3/hpb/transaction.rb +73 -0
- data/lib/web3/hpb/transaction_receipt.rb +41 -0
- data/lib/web3/hpb/utility.rb +24 -0
- data/lib/web3/hpb/version.rb +5 -0
- data/web3-hpb-0.1.0.gem +0 -0
- data/web3-hpb.gemspec +30 -0
- metadata +141 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding : ascii-8bit -*-
|
2
|
+
|
3
|
+
module Web3::Hpb::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
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding : ascii-8bit -*-
|
2
|
+
|
3
|
+
module Web3::Hpb::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
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# -*- encoding : ascii-8bit -*-
|
2
|
+
|
3
|
+
module Web3::Hpb::Abi
|
4
|
+
class Type
|
5
|
+
|
6
|
+
class ParseError < StandardError;
|
7
|
+
end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def parse(type)
|
12
|
+
_, base, sub, dimension = /([a-z]*)([0-9]*x?[0-9]*)((\[[0-9]*\])*)/.match(type).to_a
|
13
|
+
|
14
|
+
dims = dimension.scan(/\[[0-9]*\]/)
|
15
|
+
raise ParseError, "Unknown characters found in array declaration" if dims.join != dimension
|
16
|
+
|
17
|
+
case base
|
18
|
+
when ''
|
19
|
+
return parse 'address'
|
20
|
+
when 'string'
|
21
|
+
raise ParseError, "String type must have no suffix or numerical suffix" unless sub.empty?
|
22
|
+
when 'uint', 'int'
|
23
|
+
raise ParseError, "Integer type must have numerical suffix" unless sub =~ /\A[0-9]+\z/
|
24
|
+
|
25
|
+
size = sub.to_i
|
26
|
+
raise ParseError, "Integer size out of bounds" unless size >= 8 && size <= 256
|
27
|
+
raise ParseError, "Integer size must be multiple of 8" unless size % 8 == 0
|
28
|
+
when 'fixed', 'ufixed'
|
29
|
+
raise ParseError, "Fixed type must have suffix of form <high>x<low>, e.g. 128x128" unless sub =~ /\A[0-9]+x[0-9]+\z/
|
30
|
+
|
31
|
+
high, low = sub.split('x').map(&:to_i)
|
32
|
+
total = high + low
|
33
|
+
raise ParseError, "Fixed size out of bounds (max 32 bytes)" unless total >= 8 && total <= 256
|
34
|
+
raise ParseError, "Fixed high/low sizes must be multiples of 8" unless high % 8 == 0 && low % 8 == 0
|
35
|
+
when 'hash'
|
36
|
+
raise ParseError, "Hash type must have numerical suffix" unless sub =~ /\A[0-9]+\z/
|
37
|
+
when 'address'
|
38
|
+
raise ParseError, "Address cannot have suffix" unless sub.empty?
|
39
|
+
when 'bool'
|
40
|
+
raise ParseError, "Bool cannot have suffix" unless sub.empty?
|
41
|
+
else
|
42
|
+
raise ParseError, "Unrecognized type base: #{base}"
|
43
|
+
end
|
44
|
+
|
45
|
+
new(base, sub, dims.map{ |x| x[1...-1].to_i })
|
46
|
+
end
|
47
|
+
|
48
|
+
def size_type
|
49
|
+
@size_type ||= new('uint', 256, [])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
attr :base, :sub, :dims
|
54
|
+
|
55
|
+
def initialize(base, sub, dims)
|
56
|
+
@base = base
|
57
|
+
@sub = sub
|
58
|
+
@dims = dims
|
59
|
+
end
|
60
|
+
|
61
|
+
def ==(another_type)
|
62
|
+
base == another_type.base && sub == another_type.sub && dims == another_type.dims
|
63
|
+
end
|
64
|
+
|
65
|
+
def size
|
66
|
+
@size ||= if dims.empty?
|
67
|
+
if %w(string bytes).include?(base) && sub.empty?
|
68
|
+
nil
|
69
|
+
else
|
70
|
+
32
|
71
|
+
end
|
72
|
+
else
|
73
|
+
if dims.last == 0 # 0 for dynamic array []
|
74
|
+
nil
|
75
|
+
else
|
76
|
+
subtype.dynamic? ? nil : dims.last * subtype.size
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
def dynamic?
|
83
|
+
size.nil?
|
84
|
+
end
|
85
|
+
|
86
|
+
def subtype
|
87
|
+
@subtype ||= self.class.new(base, sub, dims[0...-1])
|
88
|
+
end
|
89
|
+
end
|
90
|
+
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::Hpb::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,32 @@
|
|
1
|
+
module Web3
|
2
|
+
|
3
|
+
module Hpb
|
4
|
+
|
5
|
+
class Block
|
6
|
+
|
7
|
+
include Web3::Hpb::Utility
|
8
|
+
|
9
|
+
attr_reader :raw_data
|
10
|
+
|
11
|
+
def initialize(block_data)
|
12
|
+
@raw_data = block_data
|
13
|
+
|
14
|
+
block_data.each do |k, v|
|
15
|
+
self.instance_variable_set("@#{k}", v)
|
16
|
+
self.class.send(:define_method, k, proc {self.instance_variable_get("@#{k}")})
|
17
|
+
end
|
18
|
+
|
19
|
+
@transactions = @transactions.collect { |t| Web3::Hpb::Transaction.new(t)}
|
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
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Web3
|
2
|
+
module Hpb
|
3
|
+
|
4
|
+
class CallTrace
|
5
|
+
|
6
|
+
include Web3::Hpb::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_hpb
|
25
|
+
wei_to_hpb 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_hpb
|
78
|
+
wei_to_hpb action['balance'].to_i(16)
|
79
|
+
end
|
80
|
+
|
81
|
+
def success?
|
82
|
+
!raw_data['error']
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|