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 +4 -4
- data/PREREQUISITES.md +47 -0
- data/README.md +32 -27
- data/ethereum.gemspec +4 -4
- data/lib/ethereum/abi.rb +10 -1
- data/lib/ethereum/decoder.rb +57 -23
- data/lib/ethereum/encoder.rb +26 -4
- data/lib/ethereum/version.rb +1 -1
- metadata +16 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab1aee5c95b0e162120826ec4d182dad03a7e771
|
4
|
+
data.tar.gz: 71652479b2bb2a4f81a5d8b417a8703dff1492c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
13
|
-
*
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
34
|
-
spec.add_dependency "digest-sha3", "~> 1.1
|
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
|
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
|
data/lib/ethereum/decoder.rb
CHANGED
@@ -2,47 +2,62 @@ module Ethereum
|
|
2
2
|
class Decoder
|
3
3
|
|
4
4
|
def decode(type, value, start = 0)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
21
|
-
|
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,
|
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
|
-
|
35
|
-
return
|
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
|
-
|
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
|
data/lib/ethereum/encoder.rb
CHANGED
@@ -3,11 +3,27 @@ module Ethereum
|
|
3
3
|
class Encoder
|
4
4
|
|
5
5
|
def encode(type, value)
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
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
|
data/lib/ethereum/version.rb
CHANGED
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.
|
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-
|
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: '
|
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: '
|
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
|
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
|
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
|
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
|
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.
|
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
|