eth 0.3.2 → 0.3.3

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: 1aa11c555d957c6c8c55d2ea7268609d3f9736f3
4
- data.tar.gz: 73b6328615458f16f7bbd5a5bcaf6720ce5c9178
3
+ metadata.gz: 31616ae94a3bcb7936694a979e1789f1e7cdb8be
4
+ data.tar.gz: 71821aeabc7dbc4ff6add09b97a01e06a7c44338
5
5
  SHA512:
6
- metadata.gz: f199ecb42d65c41df74875767570780f2d92d248fa8c8352203744d8337401883ecb05cad4d09d8886412b9672beb2a320af4adf8c5c83b9a5cc74dc6dc56fb1
7
- data.tar.gz: a90b8616b9ee5812a165ba685e24b8e9e1bfccc724cfb2c6ea5dfab9e9075b0e870a593a5aa0e33e704a61606cd8d8f8df48ece2ac8eac01acf22291a9c681fc
6
+ metadata.gz: 3bcafe0df121ace5b627daa94890aa2822db9f2fb73b940b5774cf300ede5499a96ded2a6403c5134ab82e8ce31d39ca64bc408062a28f0f009af02c9679e6d8
7
+ data.tar.gz: c4fa309b4924c2d21f402b2151d8dbf2170fe4791ddbdba0a6ca7a32a11325cc8e1f39b79692570beee84b8aece89a82c77eb6e492d9630f6f8c5033634ca5b9
data/README.md CHANGED
@@ -48,6 +48,14 @@ Or decode an encoded raw transaction:
48
48
  tx = Eth::Tx.decode hex
49
49
  ```
50
50
 
51
+ ### Configure
52
+ In order to prevent replay attacks, you must specify which Ethereum chain your transactions are created for. See [EIP 155](https://github.com/ethereum/EIPs/issues/155) for more detail.
53
+ ```
54
+ Eth.configure do |config|
55
+ config.chain_id = 18 #defaults to 13
56
+ end
57
+ ```
58
+
51
59
  Then sign the transaction:
52
60
  ```ruby
53
61
  tx.sign key
@@ -67,5 +75,4 @@ The gem is available as open source under the terms of the [MIT License](http://
67
75
  ## TODO
68
76
  - Better test suite.
69
77
  - Expose API for HD keys.
70
- - Separate out code pulled from [bitcoin-ruby](https://github.com/lian/bitcoin-ruby) and [ruby-ethereum](github.com/janx/ruby-ethereum) into their own gems to eliminate duplication.
71
78
  - Support signing with [libsecp256k1](https://github.com/bitcoin-core/secp256k1).
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "bundler/setup"
4
- require "ethereum-tx"
4
+ require "eth"
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency "ethereum-base", "~> 0.1.4"
23
23
  spec.add_dependency "ffi", "~> 1.0"
24
24
  spec.add_dependency "money-tree", "~> 0.9"
25
- spec.add_dependency "rlp", "~> 0.7"
25
+ spec.add_dependency "rlp", "~> 0.7.3"
26
26
 
27
27
  spec.add_development_dependency "bundler", "~> 1.12"
28
28
  spec.add_development_dependency "pry", "~> 0.1"
data/lib/eth.rb CHANGED
@@ -5,6 +5,7 @@ require 'money-tree'
5
5
  require 'rlp'
6
6
 
7
7
  module Eth
8
+ REPLAYABLE_CHAIN_ID = 13
8
9
 
9
10
  autoload :Key, 'eth/key'
10
11
  autoload :OpenSsl, 'eth/open_ssl'
@@ -12,4 +13,40 @@ module Eth
12
13
  autoload :Tx, 'eth/tx'
13
14
  autoload :Utils, 'eth/utils'
14
15
 
16
+ class << self
17
+ def configure
18
+ yield(configuration)
19
+ end
20
+
21
+ def chain_id
22
+ (configuration.chain_id || REPLAYABLE_CHAIN_ID).to_i
23
+ end
24
+
25
+ def v_base
26
+ (chain_id * 2) + 1
27
+ end
28
+
29
+ def replayable_v_base
30
+ (REPLAYABLE_CHAIN_ID * 2) + 1
31
+ end
32
+
33
+ def prevent_replays?
34
+ chain_id != REPLAYABLE_CHAIN_ID
35
+ end
36
+
37
+ def replayable_v?(v)
38
+ [replayable_v_base, replayable_v_base + 1].include? v
39
+ end
40
+
41
+
42
+ private
43
+
44
+ def configuration
45
+ @configuration ||= Configuration.new
46
+ end
47
+ end
48
+
49
+ class Configuration
50
+ attr_accessor :chain_id
51
+ end
15
52
  end
@@ -20,7 +20,7 @@ module Eth
20
20
  public_key.to_hex
21
21
  end
22
22
 
23
- def to_address
23
+ def address
24
24
  Utils.bin_to_hex(Utils.keccak256(public_bytes[1..-1])[-20..-1])
25
25
  end
26
26
 
@@ -1,6 +1,5 @@
1
- # lifted from https://github.com/lian/bitcoin-ruby
1
+ # originally lifted from https://github.com/lian/bitcoin-ruby
2
2
  # thanks to everyone there for figuring this out
3
- # TODO: Pull shared code out into a separate library
4
3
 
5
4
  module Eth
6
5
  class OpenSsl
@@ -56,13 +55,8 @@ module Eth
56
55
 
57
56
  def self.BN_num_bytes(ptr); (BN_num_bits(ptr) + 7) / 8; end
58
57
 
59
- # def self.sign_compact(hash, private_key, public_key_hex = nil, pubkey_compressed = nil)
60
58
  def self.sign_compact(hash, private_key, public_key_hex)
61
59
  private_key = [private_key].pack("H*") if private_key.bytesize >= 64
62
- private_key_hex = private_key.unpack("H*")[0]
63
-
64
- # public_key_hex = regenerate_key(private_key_hex).last unless public_key_hex
65
- # pubkey_compressed = (public_key_hex[0..1] == "04" ? false : true) unless pubkey_compressed
66
60
  pubkey_compressed = false
67
61
 
68
62
  init_ffi_ssl
@@ -90,7 +84,7 @@ module Eth
90
84
 
91
85
  if signature.get_array_of_pointer(0, 2).all?{|i| BN_num_bits(i) <= 256 }
92
86
  4.times{|i|
93
- head = [ 27 + i + (pubkey_compressed ? 4 : 0) ].pack("C")
87
+ head = [ Eth.v_base + i ].pack("C")
94
88
  if public_key_hex == recover_public_key_from_signature(hash, [head, r, s].join, i, pubkey_compressed)
95
89
  rec_id = i; break
96
90
  end
@@ -107,7 +101,6 @@ module Eth
107
101
  init_ffi_ssl
108
102
 
109
103
  signature = FFI::MemoryPointer.from_string(signature)
110
- #signature_bn = BN_bin2bn(signature, 65, BN_new())
111
104
  r = BN_bin2bn(signature[1], 32, BN_new())
112
105
  s = BN_bin2bn(signature[33], 32, BN_new())
113
106
 
@@ -168,14 +161,13 @@ module Eth
168
161
 
169
162
  def self.recover_compact(hash, signature)
170
163
  return false if signature.bytesize != 65
171
- #i = signature.unpack("C")[0] - 27
172
- #pubkey = recover_public_key_from_signature(hash, signature, (i & ~4), i >= 4)
173
164
 
174
165
  version = signature.unpack('C')[0]
175
- return false if version < 27 or version > 34
166
+ v_base = Eth.replayable_v?(version) ? Eth.replayable_v_base : Eth.v_base
167
+ return false if version < v_base
176
168
 
177
- compressed = (version >= 31) ? (version -= 4; true) : false
178
- pubkey = recover_public_key_from_signature(hash, signature, version-27, compressed)
169
+ compressed = false
170
+ pubkey = recover_public_key_from_signature(hash, signature, (version - v_base), compressed)
179
171
  end
180
172
 
181
173
  def self.init_ffi_ssl
@@ -33,7 +33,11 @@ module Eth
33
33
  end
34
34
 
35
35
  def unsigned_encoded
36
- RLP.encode self, sedes: Tx.exclude([:v, :r, :s])
36
+ RLP.encode(unsigned, sedes: sedes)
37
+ end
38
+
39
+ def signing_data
40
+ Utils.bin_to_hex unsigned_encoded
37
41
  end
38
42
 
39
43
  def encoded
@@ -104,5 +108,19 @@ module Eth
104
108
  Utils.keccak256 unsigned_encoded
105
109
  end
106
110
 
111
+ def unsigned
112
+ Tx.new to_h.merge(v: Eth.chain_id, r: 0, s: 0)
113
+ end
114
+
115
+ def sedes
116
+ if Eth.prevent_replays? && !(Eth.replayable_v? v)
117
+ self.class
118
+ else
119
+ UnsignedTx
120
+ end
121
+ end
122
+
107
123
  end
124
+
125
+ UnsignedTx = Tx.exclude([:v, :r, :s])
108
126
  end
@@ -1,3 +1,3 @@
1
1
  module Eth
2
- VERSION = "0.3.2"
2
+ VERSION = "0.3.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Ellis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-10-18 00:00:00.000000000 Z
11
+ date: 2016-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ethereum-base
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.7'
61
+ version: 0.7.3
62
62
  type: :runtime
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.7'
68
+ version: 0.7.3
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: bundler
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -166,7 +166,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
166
  version: '0'
167
167
  requirements: []
168
168
  rubyforge_project:
169
- rubygems_version: 2.4.5.1
169
+ rubygems_version: 2.5.1
170
170
  signing_key:
171
171
  specification_version: 4
172
172
  summary: Simple API to sign Ethereum transactions.