platon 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/main.yml +18 -0
- data/.gitignore +15 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +69 -0
- data/LICENSE.txt +21 -0
- data/README.md +216 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/doc/zh-cn.md +1762 -0
- data/lib/bech32.rb +82 -0
- data/lib/platon.rb +77 -0
- data/lib/platon/abi.rb +32 -0
- data/lib/platon/address.rb +62 -0
- data/lib/platon/client.rb +175 -0
- data/lib/platon/contract.rb +351 -0
- data/lib/platon/contract_event.rb +24 -0
- data/lib/platon/contract_initializer.rb +54 -0
- data/lib/platon/decoder.rb +99 -0
- data/lib/platon/deployment.rb +49 -0
- data/lib/platon/encoder.rb +120 -0
- data/lib/platon/explorer_url_helper.rb +0 -0
- data/lib/platon/formatter.rb +142 -0
- data/lib/platon/function.rb +36 -0
- data/lib/platon/function_input.rb +13 -0
- data/lib/platon/function_output.rb +14 -0
- data/lib/platon/gas.rb +9 -0
- data/lib/platon/http_client.rb +55 -0
- data/lib/platon/initializer.rb +0 -0
- data/lib/platon/ipc_client.rb +45 -0
- data/lib/platon/key.rb +105 -0
- data/lib/platon/key/decrypter.rb +113 -0
- data/lib/platon/key/encrypter.rb +128 -0
- data/lib/platon/open_ssl.rb +267 -0
- data/lib/platon/ppos.rb +344 -0
- data/lib/platon/railtie.rb +0 -0
- data/lib/platon/secp256k1.rb +7 -0
- data/lib/platon/sedes.rb +40 -0
- data/lib/platon/segwit_addr.rb +66 -0
- data/lib/platon/singleton.rb +39 -0
- data/lib/platon/solidity.rb +40 -0
- data/lib/platon/transaction.rb +41 -0
- data/lib/platon/tx.rb +201 -0
- data/lib/platon/utils.rb +180 -0
- data/lib/platon/version.rb +5 -0
- data/lib/tasks/platon_contract.rake +27 -0
- data/platon-ruby-logo.png +0 -0
- data/platon.gemspec +50 -0
- metadata +235 -0
File without changes
|
data/lib/platon/sedes.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Platon
|
2
|
+
module Sedes
|
3
|
+
include RLP::Sedes
|
4
|
+
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def address
|
8
|
+
Binary.fixed_length(20, allow_empty: true)
|
9
|
+
end
|
10
|
+
|
11
|
+
def int20
|
12
|
+
BigEndianInt.new(20)
|
13
|
+
end
|
14
|
+
|
15
|
+
def int32
|
16
|
+
BigEndianInt.new(32)
|
17
|
+
end
|
18
|
+
|
19
|
+
def int256
|
20
|
+
BigEndianInt.new(256)
|
21
|
+
end
|
22
|
+
|
23
|
+
def hash32
|
24
|
+
Binary.fixed_length(32)
|
25
|
+
end
|
26
|
+
|
27
|
+
def trie_root
|
28
|
+
Binary.fixed_length(32, allow_empty: true)
|
29
|
+
end
|
30
|
+
|
31
|
+
def big_endian_int
|
32
|
+
RLP::Sedes.big_endian_int
|
33
|
+
end
|
34
|
+
|
35
|
+
def binary
|
36
|
+
RLP::Sedes.binary
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Platon
|
2
|
+
|
3
|
+
class SegwitAddr
|
4
|
+
|
5
|
+
HRP_MAINNET = 'lat' ### TODO
|
6
|
+
HRP_TESTNET = 'atp'
|
7
|
+
HRP_REGTEST = 'atx'
|
8
|
+
|
9
|
+
attr_accessor :hrp # human-readable part
|
10
|
+
attr_accessor :ver # witness version
|
11
|
+
attr_accessor :prog # witness program
|
12
|
+
|
13
|
+
def initialize(addr = nil)
|
14
|
+
@hrp = HRP_TESTNET ## TODO
|
15
|
+
parse_addr(addr) if addr
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns segwit script pubkey which generated from witness version and witness program.
|
19
|
+
def to_script_pubkey
|
20
|
+
(prog.map{|p|[p].pack("C")}.join).unpack('H*').first
|
21
|
+
end
|
22
|
+
|
23
|
+
# parse script pubkey into witness version and witness program
|
24
|
+
def script_pubkey=(script_pubkey)
|
25
|
+
@prog = [script_pubkey].pack('H*').unpack("C*")
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns segwit address string which generated from hrp, witness version and witness program.
|
29
|
+
def addr
|
30
|
+
Bech32.encode(hrp, convert_bits(prog, 8, 5), 1)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def parse_addr(addr)
|
36
|
+
@hrp, data, spec = Bech32.decode(addr)
|
37
|
+
raise 'Invalid address.' if hrp.nil? || data[0].nil? || ![HRP_MAINNET, HRP_TESTNET, HRP_REGTEST].include?(hrp) #TODO
|
38
|
+
@ver = data[0]
|
39
|
+
@prog = convert_bits(data, 5, 8, false)
|
40
|
+
end
|
41
|
+
|
42
|
+
def convert_bits(data, from, to, padding=true)
|
43
|
+
acc = 0
|
44
|
+
bits = 0
|
45
|
+
ret = []
|
46
|
+
maxv = (1 << to) - 1
|
47
|
+
max_acc = (1 << (from + to - 1)) - 1
|
48
|
+
data.each do |v|
|
49
|
+
return nil if v < 0 || (v >> from) != 0
|
50
|
+
acc = ((acc << from) | v) & max_acc
|
51
|
+
bits += from
|
52
|
+
while bits >= to
|
53
|
+
bits -= to
|
54
|
+
ret << ((acc >> bits) & maxv)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
if padding
|
58
|
+
ret << ((acc << (to - bits)) & maxv) unless bits == 0
|
59
|
+
elsif bits >= from || ((acc << (to - bits)) & maxv) != 0
|
60
|
+
return nil
|
61
|
+
end
|
62
|
+
ret
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class Platon::Singleton
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
attr_accessor :client, :ipcpath, :host, :log, :instance, :default_account
|
6
|
+
|
7
|
+
def instance
|
8
|
+
@instance ||= configure_instance(create_instance)
|
9
|
+
end
|
10
|
+
|
11
|
+
def setup
|
12
|
+
yield(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def reset
|
16
|
+
@instance = nil
|
17
|
+
@client = nil
|
18
|
+
@host = nil
|
19
|
+
@log = nil
|
20
|
+
@ipcpath = nil
|
21
|
+
@default_account = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def create_instance
|
26
|
+
return Platon::IpcClient.new(@ipcpath) if @client == :ipc
|
27
|
+
return Platon::HttpClient.new(@host) if @client == :http
|
28
|
+
Platon::IpcClient.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def configure_instance(instance)
|
32
|
+
instance.tap do |i|
|
33
|
+
i.default_account = @default_account if @default_account.present?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
module Platon
|
5
|
+
class CompilationError < StandardError;
|
6
|
+
def initialize(msg)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Solidity
|
12
|
+
|
13
|
+
OUTPUT_REGEXP = /======= (\S*):(\S*) =======\s*Binary:\s*(\S*)\s*Contract JSON ABI\s*(.*)/
|
14
|
+
|
15
|
+
def initialize(bin_path = "solc")
|
16
|
+
@bin_path = bin_path
|
17
|
+
@args = "--bin --abi --optimize"
|
18
|
+
end
|
19
|
+
|
20
|
+
def compile(filename)
|
21
|
+
result = {}
|
22
|
+
execute_solc(filename).scan(OUTPUT_REGEXP).each do |match|
|
23
|
+
_file, name, bin, abi = match
|
24
|
+
result[name] = {}
|
25
|
+
result[name]["abi"] = abi
|
26
|
+
result[name]["bin"] = bin
|
27
|
+
end
|
28
|
+
result
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def execute_solc(filename)
|
33
|
+
p cmd = "#{@bin_path} #{@args} '#{filename}'"
|
34
|
+
out, stderr, status = Open3.capture3(cmd)
|
35
|
+
raise SystemCallError, "Unanable to run solc compliers" if status.exitstatus == 127
|
36
|
+
raise CompilationError, stderr unless status.exitstatus == 0
|
37
|
+
out
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Platon
|
2
|
+
|
3
|
+
class Transaction
|
4
|
+
|
5
|
+
DEFAULT_TIMEOUT = 300.seconds
|
6
|
+
DEFAULT_STEP = 5.seconds
|
7
|
+
|
8
|
+
attr_accessor :id, :mined, :connection, :input, :input_parameters
|
9
|
+
|
10
|
+
def initialize(id, connection, data, input_parameters = [])
|
11
|
+
@mined = false
|
12
|
+
@connection = connection
|
13
|
+
@id = id
|
14
|
+
@input = data
|
15
|
+
@input_parameters = input_parameters
|
16
|
+
end
|
17
|
+
|
18
|
+
def address
|
19
|
+
@id
|
20
|
+
end
|
21
|
+
|
22
|
+
def mined?
|
23
|
+
return true if @mined
|
24
|
+
tx = @connection.platon_get_transaction_by_hash(@id)
|
25
|
+
@mined = !tx.nil? && tx["blockNumber"].present?
|
26
|
+
end
|
27
|
+
|
28
|
+
def wait_for_miner(timeout: DEFAULT_TIMEOUT, step: DEFAULT_STEP)
|
29
|
+
start_time = Time.now
|
30
|
+
loop do
|
31
|
+
raise Timeout::Error if ((Time.now - start_time) > timeout)
|
32
|
+
return true if self.mined?
|
33
|
+
sleep step
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.from_blockchain(address, connection = IpcClient.new)
|
38
|
+
Transaction.new(address, connection, nil, nil)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/platon/tx.rb
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
module Platon
|
2
|
+
class Tx
|
3
|
+
|
4
|
+
include RLP::Sedes::Serializable
|
5
|
+
extend Sedes
|
6
|
+
|
7
|
+
set_serializable_fields({
|
8
|
+
nonce: big_endian_int,
|
9
|
+
gas_price: big_endian_int,
|
10
|
+
gas_limit: big_endian_int,
|
11
|
+
to: address,
|
12
|
+
value: big_endian_int,
|
13
|
+
data_bin: binary,
|
14
|
+
v: big_endian_int,
|
15
|
+
r: big_endian_int,
|
16
|
+
s: big_endian_int
|
17
|
+
})
|
18
|
+
|
19
|
+
attr_writer :signature
|
20
|
+
|
21
|
+
def self.decode(data)
|
22
|
+
data = Utils.hex_to_bin(data) if data.match(/\A(?:0x)?\h+\Z/)
|
23
|
+
txh = deserialize(RLP.decode data).to_h
|
24
|
+
|
25
|
+
txh[:chain_id] = Platon.chain_id_from_signature(txh)
|
26
|
+
|
27
|
+
self.new txh
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(params)
|
31
|
+
fields = {v: 0, r: 0, s: 0}.merge params
|
32
|
+
fields[:to] = Utils.normalize_address(fields[:to])
|
33
|
+
|
34
|
+
self.chain_id = (params[:chain_id]) ? params.delete(:chain_id) : nil
|
35
|
+
|
36
|
+
if params[:data]
|
37
|
+
self.data = params.delete(:data)
|
38
|
+
fields[:data_bin] = data_bin
|
39
|
+
end
|
40
|
+
serializable_initialize fields
|
41
|
+
|
42
|
+
check_transaction_validity
|
43
|
+
end
|
44
|
+
|
45
|
+
def unsigned_encoded
|
46
|
+
us = unsigned
|
47
|
+
RLP.encode(us, sedes: us.sedes)
|
48
|
+
end
|
49
|
+
|
50
|
+
def signing_data
|
51
|
+
Utils.bin_to_prefixed_hex unsigned_encoded
|
52
|
+
end
|
53
|
+
|
54
|
+
def encoded
|
55
|
+
RLP.encode self
|
56
|
+
end
|
57
|
+
|
58
|
+
def hex
|
59
|
+
Utils.bin_to_prefixed_hex encoded
|
60
|
+
end
|
61
|
+
|
62
|
+
def sign(key)
|
63
|
+
sig = key.sign(unsigned_encoded)
|
64
|
+
vrs = Utils.v_r_s_for sig
|
65
|
+
self.v = self.chain_id ? ((self.chain_id * 2) + vrs[0] + 8) : vrs[0]
|
66
|
+
self.r = vrs[1]
|
67
|
+
self.s = vrs[2]
|
68
|
+
|
69
|
+
clear_signature
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_h
|
74
|
+
hash_keys.inject({}) do |hash, field|
|
75
|
+
hash[field] = send field
|
76
|
+
hash
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def from
|
81
|
+
if ecdsa_signature
|
82
|
+
public_key = OpenSsl.recover_compact(signature_hash, ecdsa_signature)
|
83
|
+
Utils.public_key_to_address(public_key) if public_key
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def signature
|
88
|
+
return @signature if @signature
|
89
|
+
@signature = { v: v, r: r, s: s } if [v, r, s].all? && (v > 0)
|
90
|
+
end
|
91
|
+
|
92
|
+
def ecdsa_signature
|
93
|
+
return @ecdsa_signature if @ecdsa_signature
|
94
|
+
|
95
|
+
if [v, r, s].all? && (v > 0)
|
96
|
+
s_v = (self.chain_id) ? (v - (self.chain_id * 2) - 8) : v
|
97
|
+
@ecdsa_signature = [
|
98
|
+
Utils.int_to_base256(s_v),
|
99
|
+
Utils.zpad_int(r),
|
100
|
+
Utils.zpad_int(s),
|
101
|
+
].join
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def hash
|
106
|
+
"0x#{Utils.bin_to_hex Utils.keccak256_rlp(self)}"
|
107
|
+
end
|
108
|
+
alias_method :id, :hash
|
109
|
+
|
110
|
+
def data_hex
|
111
|
+
Utils.bin_to_prefixed_hex data_bin
|
112
|
+
end
|
113
|
+
|
114
|
+
def data_hex=(hex)
|
115
|
+
self.data_bin = Utils.hex_to_bin(hex)
|
116
|
+
end
|
117
|
+
|
118
|
+
def data
|
119
|
+
true ? data_hex : data_bin
|
120
|
+
# Platon.tx_data_hex? ? data_hex : data_bin
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
def data=(string)
|
125
|
+
true ? self.data_hex=(string) : self.data_bin=(string)
|
126
|
+
# Platon.tx_data_hex? ? self.data_hex=(string) : self.data_bin=(string)
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
def chain_id
|
131
|
+
@chain_id
|
132
|
+
end
|
133
|
+
|
134
|
+
def chain_id=(cid)
|
135
|
+
if cid != @chain_id
|
136
|
+
self.v = 0
|
137
|
+
self.r = 0
|
138
|
+
self.s = 0
|
139
|
+
|
140
|
+
clear_signature
|
141
|
+
end
|
142
|
+
|
143
|
+
@chain_id = (cid == 0) ? nil : cid
|
144
|
+
end
|
145
|
+
|
146
|
+
def prevent_replays?
|
147
|
+
!self.chain_id.nil?
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
def clear_signature
|
153
|
+
@signature = nil
|
154
|
+
@ecdsa_signature = nil
|
155
|
+
end
|
156
|
+
|
157
|
+
def hash_keys
|
158
|
+
keys = self.class.serializable_fields.keys
|
159
|
+
keys.delete(:data_bin)
|
160
|
+
keys + [:data, :chain_id]
|
161
|
+
end
|
162
|
+
|
163
|
+
def check_transaction_validity
|
164
|
+
if [gas_price, gas_limit, value, nonce].max > UINT_MAX
|
165
|
+
raise InvalidTransaction, "Values way too high!"
|
166
|
+
elsif gas_limit < intrinsic_gas_used
|
167
|
+
raise InvalidTransaction, "Gas limit too low"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def intrinsic_gas_used
|
172
|
+
num_zero_bytes = data_bin.count(BYTE_ZERO)
|
173
|
+
num_non_zero_bytes = data_bin.size - num_zero_bytes
|
174
|
+
|
175
|
+
Gas::GTXCOST +
|
176
|
+
Gas::GTXDATAZERO * num_zero_bytes +
|
177
|
+
Gas::GTXDATANONZERO * num_non_zero_bytes
|
178
|
+
end
|
179
|
+
|
180
|
+
def signature_hash
|
181
|
+
Utils.keccak256 unsigned_encoded
|
182
|
+
end
|
183
|
+
|
184
|
+
def unsigned
|
185
|
+
Tx.new to_h.merge(v: (self.chain_id) ? self.chain_id : 0, r: 0, s: 0)
|
186
|
+
end
|
187
|
+
|
188
|
+
protected
|
189
|
+
|
190
|
+
def sedes
|
191
|
+
if self.prevent_replays? && !(Platon.replayable_v? v)
|
192
|
+
self.class
|
193
|
+
else
|
194
|
+
UnsignedTx
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
UnsignedTx = Tx.exclude([:v, :r, :s])
|
201
|
+
end
|
data/lib/platon/utils.rb
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
module Platon
|
2
|
+
module Utils
|
3
|
+
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def normalize_address(address)
|
7
|
+
if address.nil? || address == ''
|
8
|
+
''
|
9
|
+
elsif address.size == 40
|
10
|
+
hex_to_bin address
|
11
|
+
elsif address.size == 42 && address[0..1] == '0x'
|
12
|
+
hex_to_bin address[2..-1]
|
13
|
+
else
|
14
|
+
address
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def bin_to_hex(string)
|
19
|
+
RLP::Utils.encode_hex string
|
20
|
+
end
|
21
|
+
|
22
|
+
def hex_to_bin(string)
|
23
|
+
RLP::Utils.decode_hex remove_hex_prefix(string)
|
24
|
+
end
|
25
|
+
|
26
|
+
def base256_to_int(str)
|
27
|
+
RLP::Sedes.big_endian_int.deserialize str.sub(/\A(\x00)+/, '')
|
28
|
+
end
|
29
|
+
|
30
|
+
def int_to_base256(int)
|
31
|
+
RLP::Sedes.big_endian_int.serialize int
|
32
|
+
end
|
33
|
+
|
34
|
+
def v_r_s_for(signature)
|
35
|
+
[
|
36
|
+
signature[0].bytes[0],
|
37
|
+
Utils.base256_to_int(signature[1..32]),
|
38
|
+
Utils.base256_to_int(signature[33..65]),
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
def prefix_hex(hex)
|
43
|
+
hex.match(/\A0x/) ? hex : "0x#{hex}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def remove_hex_prefix(s)
|
47
|
+
s[0,2] == '0x' ? s[2..-1] : s
|
48
|
+
end
|
49
|
+
|
50
|
+
def bin_to_prefixed_hex(binary)
|
51
|
+
prefix_hex bin_to_hex(binary)
|
52
|
+
end
|
53
|
+
|
54
|
+
def prefix_message(message)
|
55
|
+
"\x19Platon Signed Message:\n#{message.length}#{message}"
|
56
|
+
# "\x19Ethereum Signed Message:\n#{message.length}#{message}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def public_key_to_address(hex)
|
60
|
+
bytes = hex_to_bin(hex)
|
61
|
+
address_bytes = Utils.keccak256(bytes[1..-1])[-20..-1]
|
62
|
+
format_address bin_to_prefixed_hex(address_bytes)
|
63
|
+
end
|
64
|
+
|
65
|
+
# bech32 address to bin
|
66
|
+
def bech32_to_bin(bech32Address)
|
67
|
+
address = decode_bech32_address(bech32Address)
|
68
|
+
hex_to_bin address
|
69
|
+
end
|
70
|
+
|
71
|
+
def is_bech32_address?(bech32Address)
|
72
|
+
return false if bech32Address.length != 42
|
73
|
+
hrp,data,spec = Bech32.decode bech32Address
|
74
|
+
return false if data == nil
|
75
|
+
return true
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# Resolve the bech32 address
|
80
|
+
#
|
81
|
+
# @method decode_bech32_address
|
82
|
+
# @param {String} bech32Address
|
83
|
+
# @return {String} formatted address
|
84
|
+
# eg: Platon::Utils.decode_bech32_address("atp1kh9dktnszj04zn6d8ae9edhqfmt4awx94n6h4m")
|
85
|
+
def decode_bech32_address(bech32Address)
|
86
|
+
if is_bech32_address?(bech32Address) ## is_bech32_address? ## TODO
|
87
|
+
|
88
|
+
segwit_addr = SegwitAddr.new(bech32Address)
|
89
|
+
address = segwit_addr.to_script_pubkey
|
90
|
+
if address
|
91
|
+
return "0x" + address
|
92
|
+
end
|
93
|
+
end
|
94
|
+
return ''
|
95
|
+
end
|
96
|
+
|
97
|
+
# Transforms given string to bech32 address
|
98
|
+
#
|
99
|
+
# @method to_bech32_address
|
100
|
+
# @param {String} hrp
|
101
|
+
# @param {String} address
|
102
|
+
# @return {String} formatted bech32 address
|
103
|
+
|
104
|
+
# Platon::Utils.to_bech32_address("atp","0xb5cadb2e70149f514f4d3f725cb6e04ed75eb8c5")
|
105
|
+
def to_bech32_address(hrp,address)
|
106
|
+
if true ## isAddress
|
107
|
+
segwit_addr = SegwitAddr.new
|
108
|
+
segwit_addr.hrp = hrp
|
109
|
+
segwit_addr.script_pubkey = remove_hex_prefix(address) ## remove 0x
|
110
|
+
segwit_addr.addr
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def sha256(x)
|
115
|
+
Digest::SHA256.digest x
|
116
|
+
end
|
117
|
+
|
118
|
+
def keccak256(x)
|
119
|
+
Digest::SHA3.new(256).digest(x)
|
120
|
+
end
|
121
|
+
|
122
|
+
def keccak512(x)
|
123
|
+
Digest::SHA3.new(512).digest(x)
|
124
|
+
end
|
125
|
+
|
126
|
+
def keccak256_rlp(x)
|
127
|
+
keccak256 RLP.encode(x)
|
128
|
+
end
|
129
|
+
|
130
|
+
def ripemd160(x)
|
131
|
+
Digest::RMD160.digest x
|
132
|
+
end
|
133
|
+
|
134
|
+
def hash160(x)
|
135
|
+
ripemd160 sha256(x)
|
136
|
+
end
|
137
|
+
|
138
|
+
def zpad(x, l)
|
139
|
+
lpad x, BYTE_ZERO, l
|
140
|
+
end
|
141
|
+
|
142
|
+
def zunpad(x)
|
143
|
+
x.sub(/\A\x00+/, '')
|
144
|
+
end
|
145
|
+
|
146
|
+
def zpad_int(n, l=32)
|
147
|
+
zpad encode_int(n), l
|
148
|
+
end
|
149
|
+
|
150
|
+
def zpad_hex(s, l=32)
|
151
|
+
zpad decode_hex(s), l
|
152
|
+
end
|
153
|
+
|
154
|
+
def valid_address?(address)
|
155
|
+
Address.new(address).valid?
|
156
|
+
end
|
157
|
+
|
158
|
+
def format_address(address)
|
159
|
+
Address.new(address).checksummed
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
def lpad(x, symbol, l)
|
167
|
+
return x if x.size >= l
|
168
|
+
symbol * (l - x.size) + x
|
169
|
+
end
|
170
|
+
|
171
|
+
def encode_int(n)
|
172
|
+
unless n.is_a?(Integer) && n >= 0 && n <= UINT_MAX
|
173
|
+
raise ArgumentError, "Integer invalid or out of range: #{n}"
|
174
|
+
end
|
175
|
+
|
176
|
+
int_to_base256 n
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
end
|