ethereum.rb 2.0.1 → 2.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 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