ethereum.rb 2.0.1 → 2.0.2

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
  SHA1:
3
- metadata.gz: 118a182e1fe6df35ead4dd24f452ab8dbe163f1b
4
- data.tar.gz: 95b4a183b908e5c835f95af4772069603c08fb38
3
+ metadata.gz: 9c3d499f0acb7794b25b60c3caec8f728ce1212e
4
+ data.tar.gz: e3a239e91d23154acb7bbbc2ba4a528e7754b1eb
5
5
  SHA512:
6
- metadata.gz: b6353836a9589c7517beacb7bb29c402c08cc942e774954653eaf4f69d4202002f4cd67edc8c458cd29a4479bf4528fcb38b326ce16bb9b3838bfeab739a616f
7
- data.tar.gz: 1bcf61ed8af8111c10045e3a17e07011a8892f5db6d523d9a9863fc95078eee9856a398b82b3a6d1ec840d4ba22ea4af30a3f30ed4355e7ad75b0bfd30ca7d9a
6
+ metadata.gz: 5b91b2eeb93f071839e1f7985915c4ec1ca47a98d58741e6e314b374a7c3aed13db7e2da53672b2075f3783a8508050aa5830404b79755cba04cf91ebf69a453
7
+ data.tar.gz: c82e52904d885da8073c8a1af9f33a9f70610d2dd12e1acbeb35c937e9dffdb73e8a707b1025f2527c5b914881c4b2bfb43d96ce993a54388ccd90bb880f08ef
@@ -3,11 +3,7 @@ language: ruby
3
3
  rvm:
4
4
  - 2.3.1
5
5
  env:
6
- - PARITY="1.4.8"
7
6
  - PARITY="1.5.0"
8
- matrix:
9
- allow_failures:
10
- - env: PARITY="1.5.0"
11
7
  cache:
12
8
  bundler: true
13
9
  directories:
@@ -16,10 +12,10 @@ before_install:
16
12
  - sudo bin/install_parity
17
13
  - gem install bundler -v 1.11.2
18
14
  before_script:
19
- - parity --chain ~/.parity/ropsten.json --warp --password ~/.parity/pass --unlock 3089630d06fD90Ef48a0c43f000971587c1F3247 --author 3089630d06fD90Ef48a0c43f000971587c1F3247 daemon ~/.parity.pid --log-file ~/.parity.log
15
+ - parity --chain testnet -d ~/.parity --password ~/.parity/pass --unlock 3089630d06fD90Ef48a0c43f000971587c1F3247 --author 3089630d06fD90Ef48a0c43f000971587c1F3247 daemon ~/.parity.pid --log-file ~/.parity.log
20
16
  - cat ~/.parity.log
21
17
  - sleep 5
22
- - parity --chain ~/.parity/ropsten.json account list
18
+ - parity --chain testnet account list
23
19
  - cat ~/.parity.log
24
20
  - bundle exec rake ethereum:node:waitforsync
25
21
  - bundle exec rake ethereum:test:setup
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/marekkirejczyk/ethereum.rb.svg?branch=master)](https://travis-ci.org/marekkirejczyk/ethereum.rb) [![security](https://hakiri.io/github/NullVoxPopuli/MetaHash/master.svg)](https://hakiri.io/github/NullVoxPopuli/MetaHash/master) [![Dependency Status](https://gemnasium.com/marekkirejczyk/ethereum.rb.svg)](https://gemnasium.com/marekkirejczyk/ethereum.rb) [![Code Climate](https://codeclimate.com/github/marekkirejczyk/ethereum.rb/badges/gpa.svg)](https://codeclimate.com/github/marekkirejczyk/ethereum.rb)
4
4
 
5
- A ruby gem for interacting with Ethereum.
5
+ The goal of ethereum.rb is to make interacting with ethereum blockchain from ruby as easy as possible (but not easier).
6
6
 
7
7
  ## Highlights
8
8
 
@@ -14,8 +14,8 @@ A ruby gem for interacting with Ethereum.
14
14
 
15
15
  ## Compatibility and requirements
16
16
 
17
- * Tested with parity 1.4.8, might work with geth
18
- * Tested with solc 0.4.8
17
+ * Tested with parity 1.5.0, might work with geth (but was not tested)
18
+ * Tested with solc 0.4.9
19
19
  * Ruby 2.x
20
20
  * UNIX/Linux or OS X environment
21
21
 
@@ -77,16 +77,11 @@ module Ethereum
77
77
  end
78
78
 
79
79
  def call_raw(fun, *args)
80
- arg_types = fun.inputs.collect(&:type)
81
- return {result: :error, message: "missing parameters for #{fun.function_string}" } if arg_types.length != args.length
82
- payload = [fun.signature]
83
- arg_types.zip(args).each do |arg|
84
- payload << @formatter.to_payload(arg)
85
- end
86
- raw_result = @client.eth_call({to: @address, from: @sender, data: "0x" + payload.join()})
80
+ payload = fun.signature + @encoder.encode_arguments(fun.inputs, args)
81
+ raw_result = @client.eth_call({to: @address, from: @sender, data: "0x" + payload})
87
82
  raw_result = raw_result["result"]
88
83
  output = @decoder.decode_arguments(fun.outputs, raw_result)
89
- return {data: "0x" + payload.join(), raw: raw_result, formatted: output}
84
+ return {data: "0x" + payload, raw: raw_result, formatted: output}
90
85
  end
91
86
 
92
87
  def call(fun, *args)
@@ -99,15 +94,9 @@ module Ethereum
99
94
  end
100
95
 
101
96
  def transact(fun, *args)
102
- arg_types = fun.inputs.collect(&:type)
103
- return {result: :error, message: "missing parameters for #{fun.function_string}" } if arg_types.length != args.length
104
- payload = []
105
- payload << fun.signature
106
- arg_types.zip(args).each do |arg|
107
- payload << @formatter.to_payload(arg)
108
- end
109
- txid = @client.eth_send_transaction({to: @address, from: @sender, data: "0x" + payload.join()})["result"]
110
- return Ethereum::Transaction.new(txid, @client, payload.join(), args)
97
+ payload = fun.signature + @encoder.encode_arguments(fun.inputs, args)
98
+ txid = @client.eth_send_transaction({to: @address, from: @sender, data: "0x" + payload})["result"]
99
+ return Ethereum::Transaction.new(txid, @client, payload, args)
111
100
  end
112
101
 
113
102
  def transact_and_wait(fun, *args)
@@ -9,18 +9,25 @@ module Ethereum
9
9
  decode_dynamic_bytes(value, start)
10
10
  elsif "string" == core
11
11
  self.send(method_name, value, start)
12
+ elsif "int" == core
13
+ size = subtype.present? ? subtype.to_i : 256
14
+ self.send(method_name, value[start+63-(size/4-1)..start+63], size)
12
15
  else
13
16
  self.send(method_name, value[start..start+63])
14
17
  end
15
18
  end
16
19
 
20
+ def decode_fixed(value, n = 128)
21
+ decode_int(value).to_f / 2**n
22
+ end
23
+
17
24
  def decode_uint(value)
18
25
  value.hex
19
26
  end
20
27
 
21
- def decode_int(value)
28
+ def decode_int(value, size = 256)
22
29
  raise ArgumentError if value.nil?
23
- (value[0..1] == "ff") ? (value.hex - (2 ** 256)) : value.hex
30
+ (value[0..1] == "ff") ? (value.hex - (2 ** size)) : value.hex
24
31
  end
25
32
 
26
33
  def decode_bool(value)
@@ -4,54 +4,59 @@ module Ethereum
4
4
 
5
5
  def encode(type, value)
6
6
  core, subtype = Abi::parse_type(type)
7
- if core == "bytes" and subtype.nil?
8
- encode_dynamic_bytes(value)
9
- else
10
- method_name = "encode_#{core}".to_sym
11
- self.send(method_name, value)
12
- end
7
+ method_name = "encode_#{core}".to_sym
8
+ self.send(method_name, value, subtype)
13
9
  end
14
10
 
15
- def encode_int(value)
11
+ def encode_int(value, _ = nil)
16
12
  to_twos_complement(value).to_s(16).rjust(64, '0')
17
13
  end
18
14
 
19
- def encode_uint(value)
15
+ def encode_uint(value, _ = nil)
20
16
  raise ArgumentError if value < 0
21
17
  encode_int(value)
22
18
  end
23
19
 
24
- def encode_bool(value)
20
+ def encode_bool(value, _)
25
21
  (value ? "1" : "0").rjust(64, '0')
26
22
  end
27
23
 
28
- def encode_fixed(_value)
29
- raise NotImplementedError
24
+ def encode_fixed(value, subtype)
25
+ n = subtype.nil? ? 128 : /(\d+)x(\d+)/.match(subtype)[2].to_i
26
+ do_encode_fixed(value, n)
30
27
  end
31
28
 
32
- def encode_ufixed(_value)
29
+ def do_encode_fixed(value, n)
30
+ encode_uint((value * 2**n).to_i)
31
+ end
32
+
33
+ def encode_ufixed(_value, _)
33
34
  raise NotImplementedError
34
35
  end
35
36
 
36
- def encode_bytes(value)
37
+ def encode_bytes(value, subtype)
38
+ subtype.nil? ? encode_dynamic_bytes(value) : encode_static_bytes(value)
39
+ end
40
+
41
+ def encode_static_bytes(value)
37
42
  value.each_char.map {|x| x.ord.to_s(16)}.join("").ljust(64, '0')
38
43
  end
39
44
 
40
45
  def encode_dynamic_bytes(value)
41
46
  location = encode_uint(@inputs ? @inputs.size * 32 : 32)
42
47
  size = encode_uint(value.size)
43
- content = encode_bytes(value)
48
+ content = encode_static_bytes(value)
44
49
  [location, size + content]
45
50
  end
46
51
 
47
- def encode_string(value)
52
+ def encode_string(value, _)
48
53
  location = encode_uint(@inputs ? @inputs.size * 32 : 32)
49
54
  size = encode_uint(value.bytes.size)
50
55
  content = value.bytes.map {|x| x.to_s(16)}.join("").ljust(64, '0')
51
56
  [location, size + content]
52
57
  end
53
58
 
54
- def encode_address(value)
59
+ def encode_address(value, _)
55
60
  value = value.gsub(/^0x/,'')
56
61
  raise ArgumentError if value.size != 40
57
62
  value
@@ -62,6 +67,7 @@ module Ethereum
62
67
  end
63
68
 
64
69
  def encode_arguments(inputs, args)
70
+ raise "Wrong number of arguments" if inputs.length != args.length
65
71
  @head = ""
66
72
  @tail = ""
67
73
  @inputs = inputs
@@ -103,43 +103,10 @@ module Ethereum
103
103
  (hexstring.gsub(/^0x/,'')[0..1] == "ff") ? (hexstring.hex - (2 ** 256)) : hexstring.hex
104
104
  end
105
105
 
106
- def bool_to_payload(bool)
107
- int_to_payload(bool ? 1 : 0)
108
- end
109
-
110
- def address_to_payload(address)
111
- from_address(address)
112
- end
113
-
114
- def uint_to_payload(uint)
115
- self.to_twos_complement(uint).rjust(64, '0')
116
- end
117
-
118
- def int_to_payload(int)
119
- self.to_twos_complement(int).rjust(64, '0')
120
- end
121
-
122
- def bytes_to_payload(bytes)
123
- self.from_utf8(bytes).ljust(64, '0')
124
- end
125
-
126
- def string_to_payload(bytes)
127
- self.bytes_to_payload(bytes)
128
- end
129
-
130
- def construtor_params_to_payload(abi, params)
131
- abi.map.with_index { |var, i| to_payload([var["type"], params[i]]) }.join
132
- end
133
-
134
106
  def get_base_type(typename)
135
107
  typename.gsub(/\d+/,'')
136
108
  end
137
109
 
138
- def to_payload(args)
139
- converter = "#{self.get_base_type(args[0])}_to_payload".to_sym
140
- self.send(converter, args[1])
141
- end
142
-
143
110
  def from_payload(args)
144
111
  converter = "output_to_#{self.get_base_type(args[0])}".to_sym
145
112
  self.send(converter, args[1])
@@ -10,38 +10,31 @@ module Ethereum
10
10
 
11
11
  class Solidity
12
12
 
13
+ OUTPUT_REGEXP = /======= (\S*):(\S*) =======\s*Binary:\s*(\S*)\sContract JSON ABI\s(\S*)/
14
+
13
15
  def initialize(bin_path = "solc")
14
16
  @bin_path = bin_path
15
- @args = "--bin --abi --userdoc --devdoc --add-std --optimize -o"
17
+ @args = "--bin --abi --add-std --optimize"
16
18
  end
17
19
 
18
20
  def compile(filename)
19
- {}.tap do |result|
20
- Dir.mktmpdir do |dir|
21
- execute_solc(dir, filename)
22
- Dir.foreach(dir) do |file|
23
- process_file(dir, file, result)
24
- end
25
- end
21
+ result = {}
22
+ execute_solc(nil, 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
26
27
  end
28
+ result
27
29
  end
28
-
30
+
29
31
  private
30
- def process_file(dir, file, result)
31
- extension = File.extname(file)
32
- path = "#{dir}/#{file}"
33
- basename = File.basename(path, extension)
34
- unless File.directory?(path)
35
- result[basename] ||= {}
36
- result[basename][extension[1..-1]] = File.read(path)
37
- end
38
- end
39
-
40
32
  def execute_solc(dir, filename)
41
- cmd = "#{@bin_path} #{@args} '#{dir}' '#{filename}'"
42
- _, stderr, status = Open3.capture3(cmd)
33
+ cmd = "#{@bin_path} #{@args} '#{filename}'"
34
+ out, stderr, status = Open3.capture3(cmd)
43
35
  raise SystemCallError, "Unanable to run solc compliers" if status.exitstatus == 127
44
36
  raise CompilationError, stderr unless status.exitstatus == 0
37
+ out
45
38
  end
46
39
  end
47
40
  end
@@ -1,3 +1,3 @@
1
1
  module Ethereum
2
- VERSION = "2.0.1"
2
+ VERSION = "2.0.2"
3
3
  end
@@ -3,16 +3,17 @@ require 'open3'
3
3
  namespace :ethereum do
4
4
  namespace :node do
5
5
 
6
- desc "Run testnet node "
6
+ desc "Run testnet (ropsten) node"
7
7
  task :test do
8
- _, out, _ = Open3.capture3("parity --chain ~/.parity/ropsten.json account list")
8
+ args = "--chain testnet -d ~/.parity"
9
+ out, _, _ = Open3.capture3("parity #{args} account list")
9
10
  account = out.split(/[\[,\]]/)[1]
10
- cmd = "parity --chain ~/.parity/ropsten.json --password ~/.parity/pass --unlock #{account} --author #{account}"
11
+ cmd = "parity #{args} --password ~/.parity/pass --unlock #{account} --author #{account}"
11
12
  puts cmd
12
13
  system cmd
13
14
  end
14
15
 
15
- desc "Run morden (production) node"
16
+ desc "Run production node"
16
17
  task :run do
17
18
  _, out, _ = Open3.capture3("parity account list")
18
19
  account = out.split(/[\[,\]]/)[1]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ethereum.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marek Kirejczyk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-01-29 00:00:00.000000000 Z
11
+ date: 2017-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -194,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
194
  version: '0'
195
195
  requirements: []
196
196
  rubyforge_project:
197
- rubygems_version: 2.5.1
197
+ rubygems_version: 2.5.2
198
198
  signing_key:
199
199
  specification_version: 4
200
200
  summary: Ruby Ethereum client using the JSON-RPC interface