platon 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +18 -0
  3. data/.gitignore +15 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +10 -0
  6. data/Gemfile +12 -0
  7. data/Gemfile.lock +69 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +216 -0
  10. data/Rakefile +12 -0
  11. data/bin/console +15 -0
  12. data/bin/setup +8 -0
  13. data/doc/zh-cn.md +1762 -0
  14. data/lib/bech32.rb +82 -0
  15. data/lib/platon.rb +77 -0
  16. data/lib/platon/abi.rb +32 -0
  17. data/lib/platon/address.rb +62 -0
  18. data/lib/platon/client.rb +175 -0
  19. data/lib/platon/contract.rb +351 -0
  20. data/lib/platon/contract_event.rb +24 -0
  21. data/lib/platon/contract_initializer.rb +54 -0
  22. data/lib/platon/decoder.rb +99 -0
  23. data/lib/platon/deployment.rb +49 -0
  24. data/lib/platon/encoder.rb +120 -0
  25. data/lib/platon/explorer_url_helper.rb +0 -0
  26. data/lib/platon/formatter.rb +142 -0
  27. data/lib/platon/function.rb +36 -0
  28. data/lib/platon/function_input.rb +13 -0
  29. data/lib/platon/function_output.rb +14 -0
  30. data/lib/platon/gas.rb +9 -0
  31. data/lib/platon/http_client.rb +55 -0
  32. data/lib/platon/initializer.rb +0 -0
  33. data/lib/platon/ipc_client.rb +45 -0
  34. data/lib/platon/key.rb +105 -0
  35. data/lib/platon/key/decrypter.rb +113 -0
  36. data/lib/platon/key/encrypter.rb +128 -0
  37. data/lib/platon/open_ssl.rb +267 -0
  38. data/lib/platon/ppos.rb +344 -0
  39. data/lib/platon/railtie.rb +0 -0
  40. data/lib/platon/secp256k1.rb +7 -0
  41. data/lib/platon/sedes.rb +40 -0
  42. data/lib/platon/segwit_addr.rb +66 -0
  43. data/lib/platon/singleton.rb +39 -0
  44. data/lib/platon/solidity.rb +40 -0
  45. data/lib/platon/transaction.rb +41 -0
  46. data/lib/platon/tx.rb +201 -0
  47. data/lib/platon/utils.rb +180 -0
  48. data/lib/platon/version.rb +5 -0
  49. data/lib/tasks/platon_contract.rake +27 -0
  50. data/platon-ruby-logo.png +0 -0
  51. data/platon.gemspec +50 -0
  52. metadata +235 -0
@@ -0,0 +1,24 @@
1
+ module Platon
2
+ class ContractEvent
3
+
4
+ attr_accessor :name, :signature, :input_types, :inputs, :event_string, :address, :client
5
+
6
+ def initialize(data)
7
+ @name = data["name"]
8
+ @input_types = data["inputs"].collect {|x| x["type"]}
9
+ @inputs = data["inputs"].collect {|x| x["name"]}
10
+ @event_string = "#{@name}(#{@input_types.join(",")})"
11
+ @signature = Digest::SHA3.hexdigest(@event_string, 256)
12
+ end
13
+
14
+ def set_address(address)
15
+ @address = address
16
+ end
17
+
18
+ def set_client(client)
19
+ @client = client
20
+ end
21
+
22
+ end
23
+ end
24
+
@@ -0,0 +1,54 @@
1
+ module Platon
2
+
3
+ class ContractInitializer
4
+
5
+ attr_accessor :abi, :binary, :name, :libraries, :needs_linking, :project_initializer, :contract
6
+
7
+ def initialize(contract_name, contract, project_initializer)
8
+ @abi = JSON.parse(contract["abi"]) unless contract.nil?
9
+ @binary = contract["bin"] unless contract.nil?
10
+ @name = contract_name
11
+ @project_initializer = project_initializer
12
+ matchdata = @binary.scan(/_+[a-zA-Z]+_+/).uniq
13
+ @needs_linking = matchdata.present?
14
+ if @needs_linking
15
+ @libraries = matchdata.collect do |libname|
16
+ {name: libname.gsub(/_+/,''), sigil: libname}
17
+ end
18
+ end
19
+ end
20
+
21
+ def link_libraries
22
+ if @needs_linking
23
+ @libraries.each do |library|
24
+ name = library[:name]
25
+ if @project_initializer.libraries[name].nil?
26
+ ENV['ETHEREUM_DEPLOYER_WAIT_TIME'] ||= "120"
27
+ wait_time = ENV['ETHEREUM_DEPLOYER_WAIT_TIME'].to_i
28
+ library_instance = library[:name].constantize.new
29
+ puts "Deploying library #{name}"
30
+ library_instance.deploy_and_wait(wait_time)
31
+ puts "Library deployed at #{library_instance.address}"
32
+ @project_initializer.libraries[name] = library_instance.address
33
+ @binary.gsub!(library[:sigil], library_instance.address.gsub(/^0x/,''))
34
+ else
35
+ address = @project_initializer.libraries[name]
36
+ @binary.gsub!(library[:sigil], address.gsub(/^0x/,''))
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def build(connection)
43
+ @contract = Platon::Contract.new(@name, @binary, @abi, client)
44
+ @contract.build(connection)
45
+ end
46
+
47
+ def generate_javascripts(path)
48
+ data = {name: @name, abi: @abi, binary: @binary}
49
+ File.open(File.join(path, "#{@name}.json"), 'w') {|f| f.puts data.to_json}
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,99 @@
1
+ module Platon
2
+ class Decoder
3
+
4
+ def decode(type, value, start = 0)
5
+ is_array, arity, array_subtype = Abi::parse_array_type(type)
6
+ if is_array && arity
7
+ decode_static_array(arity, array_subtype, value, start)
8
+ elsif is_array
9
+ decode_dynamic_array(array_subtype, value, start)
10
+ else
11
+ value = value.gsub(/^0x/,'')
12
+ core, subtype = Abi::parse_type(type)
13
+ method_name = "decode_#{core}".to_sym
14
+ self.send(method_name, value, subtype, start)
15
+ end
16
+ end
17
+
18
+ def decode_static_array(arity, array_subtype, value, start)
19
+ (0..arity-1).map { |i| decode(array_subtype, value, start + i * 64) }
20
+ end
21
+
22
+ def decode_dynamic_array(array_subtype, value, start)
23
+ location = decode_uint(value[start..(start+63)]) * 2
24
+ size = decode_uint(value[location..location+63])
25
+ (0..size-1).map { |i| decode(array_subtype, value, location + (i+1) * 64) }
26
+ end
27
+
28
+ def decode_fixed(value, subtype = "128x128", start = 0)
29
+ decode_int(trim(value, start, fixed_bitsize(subtype))).to_f / 2**exponent(subtype)
30
+ end
31
+
32
+ def decode_uint(value, subtype = "256", start = 0)
33
+ trim(value, start, bitsize(subtype)).hex
34
+ end
35
+
36
+ def decode_int(value, subtype = "256", start = 0)
37
+ raise ArgumentError if value.nil?
38
+ size = bitsize(subtype)
39
+ value = trim(value, start, size)
40
+ (value[0..1] == "ff") ? (value.hex - (2 ** size)) : value.hex
41
+ end
42
+
43
+ def decode_bool(value, _, start)
44
+ value = trim(value, start, 4)
45
+ return true if value == "1"
46
+ return false if value == "0"
47
+ raise ArgumentError
48
+ end
49
+
50
+ def decode_address(value, _ = nil, start)
51
+ raise ArgumentError if value.size-start < 64
52
+ value[start+24..start+63]
53
+ end
54
+
55
+ def decode_bytes(value, subtype, start)
56
+ subtype.present? ? decode_static_bytes(value, subtype, start) : decode_dynamic_bytes(value, start)
57
+ end
58
+
59
+ def decode_static_bytes(value, subtype = nil, start = 0)
60
+ trim(value, start, subtype.to_i*8).scan(/.{2}/).collect {|x| x.hex}.pack('C*').strip
61
+ end
62
+
63
+ def decode_dynamic_bytes(value, start = 0)
64
+ location = decode_uint(value[start..(start+63)]) * 2
65
+ size = decode_uint(value[location..location+63]) * 2
66
+ value[location+64..location+63+size].scan(/.{2}/).collect {|x| x.hex}.pack('C*')
67
+ end
68
+
69
+ def decode_string(value, _ = nil, start = 0)
70
+ decode_dynamic_bytes(value, start).force_encoding('utf-8')
71
+ end
72
+
73
+ def decode_arguments(arguments, data)
74
+ data = data.gsub(/^0x/,'')
75
+ types = arguments.map { |o| o.type }
76
+ types.each.with_index.map { |t , i| decode(t, data, i*64) }
77
+ end
78
+
79
+ private
80
+ def trim(value, start, bitsize = 256)
81
+ value[start+63-(bitsize/4-1)..start+63]
82
+ end
83
+
84
+ def bitsize(subtype, default = 256)
85
+ subtype.present? ? subtype.to_i : default
86
+ end
87
+
88
+ def fixed_bitsize(subtype = nil)
89
+ subtype ||= "128x128"
90
+ _, x, n = /(\d+)x(\d+)/.match(subtype).to_a
91
+ x.to_i + n.to_i
92
+ end
93
+
94
+ def exponent(subtype, default = 128)
95
+ subtype.nil? ? default : /(\d+)x(\d+)/.match(subtype)[2].to_i
96
+ end
97
+
98
+ end
99
+ end
@@ -0,0 +1,49 @@
1
+ module Platon
2
+
3
+ class Deployment
4
+
5
+ DEFAULT_TIMEOUT = 300.seconds
6
+ DEFAULT_STEP = 5.seconds
7
+
8
+ attr_accessor :id, :contract_address, :connection, :deployed, :mined
9
+ attr_reader :valid_deployment
10
+
11
+ def initialize(txid, connection)
12
+ @id = txid
13
+ @connection = connection
14
+ @deployed = false
15
+ @contract_address = nil
16
+ @valid_deployment = false
17
+ end
18
+
19
+ def mined?
20
+ return true if @mined
21
+ @mined = @connection.platon_get_transaction_by_hash(@id)["result"]["blockNumber"].present?
22
+ @mined ||= false
23
+ end
24
+
25
+ def check_deployed
26
+ return false unless @id
27
+ contract_receipt = @connection.platon_get_transaction_receipt(@id)
28
+ result = contract_receipt["result"]
29
+ has_contract_address = result && result["contractAddress"]
30
+ @contract_address ||= result["contractAddress"] if has_contract_address
31
+ has_contract_address && result["blockNumber"]
32
+ end
33
+
34
+ def deployed?
35
+ @valid_deployment ||= check_deployed
36
+ end
37
+
38
+ def wait_for_deployment(timeout: DEFAULT_TIMEOUT, step: DEFAULT_STEP)
39
+ start_time = Time.now
40
+ loop do
41
+ raise "Transaction #{@id} timed out." if ((Time.now - start_time) > timeout)
42
+ yield if block_given?
43
+ return true if deployed?
44
+ sleep step
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,120 @@
1
+ module Platon
2
+
3
+ class Encoder
4
+
5
+ def encode(type, value)
6
+ is_array, arity, array_subtype = Abi::parse_array_type(type)
7
+ if is_array && arity
8
+ encode_static_array(arity, array_subtype, value)
9
+ elsif is_array
10
+ encode_dynamic_array(array_subtype, value)
11
+ else
12
+ core, subtype = Abi::parse_type(type)
13
+ method_name = "encode_#{core}".to_sym
14
+ self.send(method_name, value, subtype)
15
+ end
16
+ end
17
+
18
+ def encode_static_array(arity, array_subtype, array)
19
+ raise "Wrong number of arguments" if arity != array.size
20
+ array.inject("") { |a, e| a << encode(array_subtype, e) }
21
+ end
22
+
23
+ def encode_dynamic_array(array_subtype, array)
24
+ location = encode_uint(@inputs ? size_of_inputs(@inputs) + @tail.size/2 : 32)
25
+ size = encode_uint(array.size)
26
+ data = array.inject("") { |a, e| a << encode(array_subtype, e) }
27
+ [location, size + data]
28
+ end
29
+
30
+ def encode_int(value, _ = nil)
31
+ to_twos_complement(value).to_s(16).rjust(64, '0')
32
+ end
33
+
34
+ def encode_uint(value, _ = nil)
35
+ raise ArgumentError if value < 0
36
+ encode_int(value)
37
+ end
38
+
39
+ def encode_bool(value, _)
40
+ (value ? "1" : "0").rjust(64, '0')
41
+ end
42
+
43
+ def encode_fixed(value, subtype)
44
+ n = subtype.nil? ? 128 : /(\d+)x(\d+)/.match(subtype)[2].to_i
45
+ do_encode_fixed(value, n)
46
+ end
47
+
48
+ def do_encode_fixed(value, n)
49
+ encode_uint((value * 2**n).to_i)
50
+ end
51
+
52
+ def encode_ufixed(_value, _)
53
+ raise NotImplementedError
54
+ end
55
+
56
+ def encode_bytes(value, subtype)
57
+ subtype.nil? ? encode_dynamic_bytes(value) : encode_static_bytes(value)
58
+ end
59
+
60
+ def encode_static_bytes(value)
61
+ value.bytes.map {|x| x.to_s(16).rjust(2, '0')}.join("").ljust(64, '0')
62
+ end
63
+
64
+ def encode_dynamic_bytes(value)
65
+ location = encode_uint(@inputs ? size_of_inputs(@inputs) + @tail.size/2 : 32)
66
+ size = encode_uint(value.size)
67
+ content = encode_static_bytes(value)
68
+ [location, size + content]
69
+ end
70
+
71
+ def encode_string(value, _)
72
+ location = encode_uint(@inputs ? size_of_inputs(@inputs) + @tail.size/2 : 32)
73
+ size = encode_uint(value.bytes.size)
74
+ content = value.bytes.map {|x| x.to_s(16).rjust(2, '0')}.join("").ljust(64, '0')
75
+ [location, size + content]
76
+ end
77
+
78
+ def encode_address(value, _)
79
+ # puts "value: #{value}"
80
+ value = Utils.decode_bech32_address(value) if Utils.is_bech32_address?(value)
81
+ value = "0" * 24 + value.gsub(/^0x/,'')
82
+ raise ArgumentError if value.size != 64
83
+ value
84
+ end
85
+
86
+ def ensure_prefix(value)
87
+ value.start_with?("0x") ? value : ("0x" + value)
88
+ end
89
+
90
+ def encode_arguments(inputs, args)
91
+ raise "Wrong number of arguments" if inputs.length != args.length
92
+ @head = ""
93
+ @tail = ""
94
+ @inputs = inputs
95
+ inputs.each.with_index do |input, index|
96
+ encoded = encode(input.type, args[index])
97
+ if encoded.is_a? Array
98
+ @head << encoded[0]
99
+ @tail << encoded[1]
100
+ else
101
+ @head << encoded
102
+ end
103
+ end
104
+ @head + @tail
105
+ end
106
+
107
+ private
108
+ def to_twos_complement(number)
109
+ (number & ((1 << 256) - 1))
110
+ end
111
+
112
+ def size_of_inputs(inputs)
113
+ inputs.map do |input|
114
+ _, arity, _ = Abi::parse_array_type(input.type)
115
+ arity.nil? ? 32 : arity * 32
116
+ end.inject(:+)
117
+ end
118
+ end
119
+
120
+ end
File without changes
@@ -0,0 +1,142 @@
1
+ module Platon
2
+ class Formatter
3
+
4
+ UNITS = {
5
+ 'von': 1,
6
+ 'kvon': 1000,
7
+ 'mvon': 1000000,
8
+ 'gvon': 1000000000, ## 10 ** 9
9
+ 'microatp': 1000000000000,
10
+ 'milliatp': 1000000000000000,
11
+ 'atp': 1000000000000000000, ## 10 ** 18
12
+ 'katp': 1000000000000000000000,
13
+ 'matp': 1000000000000000000000000,
14
+ 'gatp': 1000000000000000000000000000,
15
+ 'tatp': 1000000000000000000000000000000
16
+ }
17
+
18
+ def valid_address?(address_string)
19
+ address = address_string.gsub(/^0x/,'')
20
+ return false if address == "0000000000000000000000000000000000000000"
21
+ return false if address.length != 40
22
+ return !(address.match(/[0-9a-fA-F]+/).nil?)
23
+ end
24
+
25
+ def from_bool(boolval)
26
+ return nil if boolval.nil?
27
+ boolval ? "1" : "0"
28
+ end
29
+
30
+ def to_bool(hexstring)
31
+ return nil if hexstring.nil?
32
+ (hexstring == "0000000000000000000000000000000000000000000000000000000000000001")
33
+ end
34
+
35
+ def to_ascii(hexstring)
36
+ return nil if hexstring.nil?
37
+ hexstring.gsub(/^0x/,'').scan(/.{2}/).collect {|x| x.hex}.pack("c*")
38
+ end
39
+
40
+ def to_utf8(hexstring)
41
+ return nil if hexstring.nil?
42
+ hexstring.gsub(/^0x/,'').scan(/.{2}/).collect {|x| x.hex}.pack("U*").delete("\u0000")
43
+ end
44
+
45
+ def from_ascii(ascii_string)
46
+ return nil if ascii_string.nil?
47
+ ascii_string.unpack('H*')[0]
48
+ end
49
+
50
+ def from_utf8(utf8_string)
51
+ return nil if utf8_string.nil?
52
+ utf8_string.force_encoding('UTF-8').split("").collect {|x| x.ord.to_s(16).rjust(2, '0')}.join("")
53
+ end
54
+
55
+ def to_address(hexstring)
56
+ return "0x0000000000000000000000000000000000000000" if hexstring.nil?
57
+ "0x" + hexstring[-40..-1]
58
+ end
59
+
60
+ def to_von(amount, unit = "atp") #TODO
61
+ return nil if amount.nil?
62
+ BigDecimal(UNITS[unit.to_sym] * amount, 16).to_s.to_i rescue nil
63
+ end
64
+
65
+ def from_von(amount, unit = "atp") #TODO
66
+ return nil if amount.nil?
67
+ (BigDecimal(amount, 16) / BigDecimal(UNITS[unit.to_sym], 16)).to_s rescue nil
68
+ end
69
+
70
+ def to_gvon(amount, unit = "gvon")
71
+ return nil if amount.nil?
72
+ BigDecimal(UNITS[unit.to_sym] * amount, 16).to_s.to_i rescue nil
73
+ end
74
+
75
+ def from_gvon(amount, unit = "gvon")
76
+ return nil if amount.nil?
77
+ (BigDecimal(amount, 16) / BigDecimal(UNITS[unit.to_sym], 16)).to_s rescue nil
78
+ end
79
+
80
+ def from_address(address)
81
+ return "0x0000000000000000000000000000000000000000" if address.nil?
82
+ address.gsub(/^0x/,'').rjust(64, "0")
83
+ end
84
+
85
+ def to_param(string)
86
+ string.ljust(64, '0')
87
+ end
88
+
89
+ def from_input(string)
90
+ string[10..-1].scan(/.{64}/)
91
+ end
92
+
93
+ def to_twos_complement(number)
94
+ (number & ((1 << 256) - 1)).to_s(16)
95
+ end
96
+
97
+ def to_int(hexstring)
98
+ return nil if hexstring.nil?
99
+ (hexstring.gsub(/^0x/,'')[0..1] == "ff") ? (hexstring.hex - (2 ** 256)) : hexstring.hex
100
+ end
101
+
102
+ def get_base_type(typename)
103
+ typename.gsub(/\d+/,'')
104
+ end
105
+
106
+ def from_payload(args)
107
+ converter = "output_to_#{self.get_base_type(args[0])}".to_sym
108
+ self.send(converter, args[1])
109
+ end
110
+
111
+ def output_to_address(bytes)
112
+ self.to_address(bytes)
113
+ end
114
+
115
+ def output_to_bytes(bytes)
116
+ self.to_utf8(bytes)
117
+ end
118
+
119
+ def output_to_string(bytes)
120
+ self.to_utf8(bytes)
121
+ end
122
+
123
+ def output_to_uint(bytes)
124
+ self.to_int(bytes)
125
+ end
126
+
127
+ def output_to_int(bytes)
128
+ self.to_int(bytes)
129
+ end
130
+
131
+ def output_to_bool(bytes)
132
+ self.to_bool(bytes.gsub(/^0x/,''))
133
+ end
134
+
135
+ def to_output(args)
136
+ converter = "output_to_#{self.get_base_type(args[0])}".to_sym
137
+ self.send(converter, args[1])
138
+ end
139
+
140
+ end
141
+
142
+ end