ethereum.rb 2.0.2 → 2.0.3

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: 9c3d499f0acb7794b25b60c3caec8f728ce1212e
4
- data.tar.gz: e3a239e91d23154acb7bbbc2ba4a528e7754b1eb
3
+ metadata.gz: ab1aee5c95b0e162120826ec4d182dad03a7e771
4
+ data.tar.gz: 71652479b2bb2a4f81a5d8b417a8703dff1492c6
5
5
  SHA512:
6
- metadata.gz: 5b91b2eeb93f071839e1f7985915c4ec1ca47a98d58741e6e314b374a7c3aed13db7e2da53672b2075f3783a8508050aa5830404b79755cba04cf91ebf69a453
7
- data.tar.gz: c82e52904d885da8073c8a1af9f33a9f70610d2dd12e1acbeb35c937e9dffdb73e8a707b1025f2527c5b914881c4b2bfb43d96ce993a54388ccd90bb880f08ef
6
+ metadata.gz: 66065eda0356fa17adf2e017e202c90f8f7e237b0652257816bee3e3cd73d16c435e4bfc1b27d9c69446f5a5d1b53e4b11515e13a56ce48b08f162cc99db90ae
7
+ data.tar.gz: 7a34dd68afe840e9f1c37edc64df9176aa7224f38f10fe3c954f3038de7099a76d62dd0fcddd3ae1680285b1ea33f3d9c94a01cc09c8aaf60cdd1571366c69c8
data/PREREQUISITES.md ADDED
@@ -0,0 +1,47 @@
1
+ # Prerequisites
2
+
3
+ ## Compatibility and requirements
4
+
5
+ * Tested with parity 1.5.0, might work with geth (but was not tested)
6
+ * Tested with solc 0.4.9
7
+ * Ruby 2.x
8
+ * UNIX/Linux or OS X environment
9
+
10
+ ## Prerequisites
11
+
12
+ Ethereum.rb requires installation of ethereum node and solidity compiler.
13
+
14
+ ### Ethereum node
15
+
16
+ Currently the lib supports only [parity](https://ethcore.io/parity.html). To install parity on mac simply:
17
+
18
+ $ brew install parity --beta
19
+
20
+ To install parity on linux download latest package from [parity github](https://github.com/ethcore/parity/releases) and install on your computer.
21
+
22
+ It might work with [geth](https://github.com/ethereum/go-ethereum/wiki/geth) as well, but this configuration is not tested. Library assumes that you have at least one wallet configured.
23
+
24
+ ### Solidity complier
25
+
26
+ To be able to compile [solidity](https://github.com/ethereum/solidity) contracts you need to install solc compiler. Installation instructions are available [here](http://solidity.readthedocs.io/en/latest/installing-solidity.html).
27
+ To install on mac simply:
28
+
29
+ $ brew install solidity --beta
30
+
31
+ In general get used to working on beta versions as ethereum ecosystem evolves quite fast.
32
+
33
+ ## Installation
34
+
35
+ Add this line to your application's Gemfile:
36
+
37
+ ```ruby
38
+ gem 'ethereum.rb'
39
+ ```
40
+
41
+ And then execute:
42
+
43
+ $ bundle
44
+
45
+ Or install it yourself as:
46
+
47
+ $ gem install ethereum.eb
data/README.md CHANGED
@@ -9,31 +9,14 @@ The goal of ethereum.rb is to make interacting with ethereum blockchain from rub
9
9
  * Pure Ruby implementation
10
10
  * IPC & HTTP Client with batch calls support
11
11
  * Compile Solidity contracts with solc compiler
12
- * Deploy and call contracts methods
13
- * Contract events
14
-
15
- ## Compatibility and requirements
16
-
17
- * Tested with parity 1.5.0, might work with geth (but was not tested)
18
- * Tested with solc 0.4.9
19
- * Ruby 2.x
20
- * UNIX/Linux or OS X environment
21
-
22
- ## Prerequisites
23
-
24
- Ethereum.rb requires installation of ethereum node and solidity compiler.
25
-
26
- ### Ethereum node
27
-
28
- Currently the lib supports only [parity](https://ethcore.io/parity.html). It might work with [geth](https://github.com/ethereum/go-ethereum/wiki/geth) as well, but this configuration is not tested. Library assumes that you have at least one wallet configured.
29
-
30
- ### Solidity complier
31
-
32
- To be able to compile [solidity](https://github.com/ethereum/solidity) contracts you need to install solc compiler. Installation instructions are available [here](http://solidity.readthedocs.io/en/latest/installing-solidity.html).
12
+ * Deploy and interact with contracts
13
+ * Support for contract events
33
14
 
34
15
  ## Installation
35
16
 
36
- Add this line to your application's Gemfile:
17
+ Before installing gem make sure to go through [prerequisites](https://github.com/marekkirejczyk/ethereum.rb/blob/master/PREREQUISITES.md) section.
18
+
19
+ To install gem simply add this line to your application's Gemfile:
37
20
 
38
21
  ```ruby
39
22
  gem 'ethereum.rb'
@@ -49,6 +32,18 @@ Or install it yourself as:
49
32
 
50
33
  ## Basic Usage
51
34
 
35
+ ### Running a node
36
+
37
+ Right after parity installation you will have one default account. There is a rake task to run test node, that you can run from your application directory:
38
+
39
+ $ rake ethereum:node:test
40
+
41
+ It will run parity node, unlock the first account on the account list, but you need to supply it with password. To do that adding create file containing password accessable from the following path:
42
+
43
+ `~/.parity/pass`
44
+
45
+ To run operations modifiying blockchain you will need test ether, you can get it [here](http://faucet.ropsten.be:3001/).
46
+
52
47
  ### IPC Client Connection
53
48
 
54
49
  To create client instance simply create Ethereum::IpcClient:
@@ -164,15 +159,25 @@ Logs from communication between ruby app and node are available under following
164
159
  /tmp/ethereum_ruby_http.log
165
160
  ```
166
161
 
162
+ ## Roadmap
163
+
164
+ * Dynamic arrays serialization
165
+ * Signing transactions
166
+
167
+
167
168
  ## Development
168
169
 
169
- After checking out the repo, run `bin/setup` to install dependencies.
170
- Make sure `rake ethereum:test:setup` passes before running tests.
171
- Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
170
+ Make sure `rake ethereum:test:setup` passes before running tests.
172
171
 
173
- You need ethereum node up and running for tests to pass and it needs to be working on testnet (Ropsten).
172
+ You can also run `bin/console` for an interactive prompt that will allow you to experiment.
173
+
174
+ Then, run `rake spec` to run the tests.
175
+
176
+ Test that do send transactions to blockchain are marked with `blockchain` tag. Good practice is to run first fast tests that use no ether and only if they pass, run slow tests that do spend ether. To do that use the following line:
174
177
 
175
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
178
+ $ bundle exec rspec --tag ~blockchain && bundle exec rspec --tag blockchain
179
+
180
+ You need ethereum node up and running for tests to pass and it needs to be working on testnet (Ropsten).
176
181
 
177
182
  ## Acknowledgements and license
178
183
 
data/ethereum.gemspec CHANGED
@@ -27,9 +27,9 @@ Gem::Specification.new do |spec|
27
27
 
28
28
  spec.add_development_dependency "bundler", "~> 1.13"
29
29
  spec.add_development_dependency "rake", "~> 12.0"
30
- spec.add_development_dependency "rspec"
31
- spec.add_development_dependency "pry"
30
+ spec.add_development_dependency "rspec", "~> 3.5"
31
+ spec.add_development_dependency "pry", "~> 0.10"
32
32
 
33
- spec.add_dependency "activesupport", "~> 5.0.1"
34
- spec.add_dependency "digest-sha3", "~> 1.1.0"
33
+ spec.add_dependency "activesupport", "~> 5.0"
34
+ spec.add_dependency "digest-sha3", "~> 1.1"
35
35
  end
data/lib/ethereum/abi.rb CHANGED
@@ -15,9 +15,18 @@ module Ethereum
15
15
 
16
16
  def self.parse_type(type)
17
17
  raise NotImplementedError if type.ends_with?("]")
18
- match = /(\D+)(\d.+)?/.match(type)
18
+ match = /(\D+)(\d.*)?/.match(type)
19
19
  [match[1], match[2]]
20
20
  end
21
21
 
22
+ def self.parse_array_type(type)
23
+ match = /(.+)\[(\d*)\]\z/.match(type)
24
+ if match
25
+ [true, match[2].present? ? match[2].to_i : nil, match[1]]
26
+ else
27
+ [false, nil, nil]
28
+ end
29
+ end
30
+
22
31
  end
23
32
  end
@@ -2,47 +2,62 @@ module Ethereum
2
2
  class Decoder
3
3
 
4
4
  def decode(type, value, start = 0)
5
- value = value.gsub(/^0x/,'')
6
- core, subtype = Abi::parse_type(type)
7
- method_name = "decode_#{core}".to_sym
8
- if "bytes" == core and subtype.nil?
9
- decode_dynamic_bytes(value, start)
10
- elsif "string" == core
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)
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()
15
10
  else
16
- self.send(method_name, value[start..start+63])
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)
17
15
  end
18
16
  end
19
17
 
20
- def decode_fixed(value, n = 128)
21
- decode_int(value).to_f / 2**n
18
+ def decode_static_array(arity, array_subtype, value, start)
19
+ (1..arity).map.with_index do |e, i|
20
+ decode(array_subtype, value, start + i * 64)
21
+ end
22
+ end
23
+
24
+ def decode_dynamic_array()
25
+ raise NotImplementedError
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)
22
30
  end
23
31
 
24
- def decode_uint(value)
25
- value.hex
32
+ def decode_uint(value, subtype = "256", start = 0)
33
+ trim(value, start, bitsize(subtype)).hex
26
34
  end
27
35
 
28
- def decode_int(value, size = 256)
36
+ def decode_int(value, subtype = "256", start = 0)
29
37
  raise ArgumentError if value.nil?
38
+ size = bitsize(subtype)
39
+ value = trim(value, start, size)
30
40
  (value[0..1] == "ff") ? (value.hex - (2 ** size)) : value.hex
31
41
  end
32
42
 
33
- def decode_bool(value)
34
- return true if value == "0000000000000000000000000000000000000000000000000000000000000001"
35
- return false if value == "0000000000000000000000000000000000000000000000000000000000000000"
43
+ def decode_bool(value, _, start)
44
+ value = trim(value, start, 4)
45
+ return true if value == "1"
46
+ return false if value == "0"
36
47
  raise ArgumentError
37
48
  end
38
49
 
39
- def decode_address(value)
50
+ def decode_address(value, _ = nil, _)
40
51
  raise ArgumentError if value.size != 40
41
52
  value
42
53
  end
43
54
 
44
- def decode_bytes(value)
45
- value.scan(/.{2}/).collect {|x| x.hex}.pack('C*').strip
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
46
61
  end
47
62
 
48
63
  def decode_dynamic_bytes(value, start = 0)
@@ -51,7 +66,7 @@ module Ethereum
51
66
  value[location+64..location+63+size].scan(/.{2}/).collect {|x| x.hex}.pack('C*')
52
67
  end
53
68
 
54
- def decode_string(value, start = 0)
69
+ def decode_string(value, _ = nil, start = 0)
55
70
  decode_dynamic_bytes(value, start).force_encoding('utf-8')
56
71
  end
57
72
 
@@ -61,5 +76,24 @@ module Ethereum
61
76
  types.each.with_index.map { |t , i| decode(t, data, i*64) }
62
77
  end
63
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, default = 256)
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
+
64
98
  end
65
99
  end
@@ -3,11 +3,27 @@ module Ethereum
3
3
  class Encoder
4
4
 
5
5
  def encode(type, value)
6
- core, subtype = Abi::parse_type(type)
7
- method_name = "encode_#{core}".to_sym
8
- self.send(method_name, value, subtype)
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()
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
+ (1..arity).map.with_index { |e, i| encode(array_subtype, array[i]) }.join
9
20
  end
10
21
 
22
+ def encode_dynamic_array()
23
+ raise NotImplementedError
24
+ end
25
+
26
+
11
27
  def encode_int(value, _ = nil)
12
28
  to_twos_complement(value).to_s(16).rjust(64, '0')
13
29
  end
@@ -50,7 +66,7 @@ module Ethereum
50
66
  end
51
67
 
52
68
  def encode_string(value, _)
53
- location = encode_uint(@inputs ? @inputs.size * 32 : 32)
69
+ location = encode_uint(@inputs ? size_of_inputs(@inputs) + @tail.size/2 : 32)
54
70
  size = encode_uint(value.bytes.size)
55
71
  content = value.bytes.map {|x| x.to_s(16)}.join("").ljust(64, '0')
56
72
  [location, size + content]
@@ -88,6 +104,12 @@ module Ethereum
88
104
  (number & ((1 << 256) - 1))
89
105
  end
90
106
 
107
+ def size_of_inputs(inputs)
108
+ inputs.map do |input|
109
+ _, arity, _ = Abi::parse_array_type(input.type)
110
+ arity.nil? ? 32 : arity * 32
111
+ end.inject(:+)
112
+ end
91
113
  end
92
114
 
93
115
  end
@@ -1,3 +1,3 @@
1
1
  module Ethereum
2
- VERSION = "2.0.2"
2
+ VERSION = "2.0.3"
3
3
  end
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.2
4
+ version: 2.0.3
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-02-01 00:00:00.000000000 Z
11
+ date: 2017-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -42,58 +42,58 @@ dependencies:
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '3.5'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '3.5'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: pry
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '0.10'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '0.10'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: activesupport
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 5.0.1
75
+ version: '5.0'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 5.0.1
82
+ version: '5.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: digest-sha3
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 1.1.0
89
+ version: '1.1'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 1.1.0
96
+ version: '1.1'
97
97
  description: Ethereum.rb is Ruby Ethereum client using the JSON-RPC interface. Provides
98
98
  interface for sending transactions, creating and interacting with contracts as well
99
99
  as usefull toolkit to work with Ethereum node.
@@ -111,6 +111,7 @@ files:
111
111
  - Gemfile
112
112
  - LICENSE
113
113
  - LICENSE.txt
114
+ - PREREQUISITES.md
114
115
  - README.md
115
116
  - Rakefile
116
117
  - bin/console
@@ -194,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
195
  version: '0'
195
196
  requirements: []
196
197
  rubyforge_project:
197
- rubygems_version: 2.5.2
198
+ rubygems_version: 2.5.1
198
199
  signing_key:
199
200
  specification_version: 4
200
201
  summary: Ruby Ethereum client using the JSON-RPC interface