eth 0.4.17 → 0.4.18

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
  SHA256:
3
- metadata.gz: d50d2e45f9d5e59e5d56cc1a5f43fd96d892fa991c3479d9f7b74623cc288593
4
- data.tar.gz: 519efad7ad2cc42e2402910ad298166dfa9266c552c579232715f8a7fa3b6a8b
3
+ metadata.gz: 2cfb1dbda97ae8033690aeb0ffe7410e2db112dbb3d2c78f34bad15db7dcbf45
4
+ data.tar.gz: '039a0fc3b15cd132f1409fc8636f32d501f237e338628c63672f21fed81047af'
5
5
  SHA512:
6
- metadata.gz: 7e38450c7a46789421250fe0f34900d4a1066c500744ba04cf76feddb52cba26bf9c94bc981c7979f07568e74799b3e31e4e887195ae235f29d7a33e3620dae2
7
- data.tar.gz: 0c3822f4a19288a63cb73fad38bab8cea19db5873c98ebc78aa5882ff921371617df97c728656ac0144aec2a13ab6c980be516036dfe0895ca6fb4b0a9c0fbb0
6
+ metadata.gz: e69bf16bccb10f673673c8f45167817930549813a3e9fa33b64e868a618f6bbd810c23a8512c1a0f535a18d38238b71ab18afdfd438e6ebd8cffb2deb5256a79
7
+ data.tar.gz: 67c6de579f25a7b9cdecd8fee97f5df927d8f0145c03b9604c324e86925ba905f6e98b42e49b1487178842ea25efe3a8f0ea35162ee96666db85345bf0281bd4
@@ -11,16 +11,26 @@ on:
11
11
 
12
12
  jobs:
13
13
  build:
14
- runs-on: ubuntu-latest
14
+ runs-on: ${{ matrix.os }}
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ os: [ubuntu-latest, macos-latest]
19
+ ruby: ['2.7', '3.0']
15
20
  steps:
16
21
  - uses: actions/checkout@v2
17
22
  - uses: ruby/setup-ruby@v1
18
23
  with:
19
- ruby-version: 3.0
24
+ ruby-version: ${{ matrix.ruby }}
25
+ bundler-cache: true
26
+ - name: Brew Automake
27
+ run: |
28
+ brew install automake
29
+ if: startsWith(matrix.os, 'macOS')
20
30
  - name: Install Dependencies
21
31
  run: |
22
32
  git submodule update --init
23
33
  bundle install
24
34
  - name: Run Tests
25
35
  run: |
26
- rspec
36
+ bundle exec rspec
@@ -8,9 +8,6 @@ on:
8
8
  push:
9
9
  branches:
10
10
  - develop
11
- schedule:
12
- -
13
- cron: "45 1 * * 3"
14
11
 
15
12
  jobs:
16
13
  analyze:
@@ -36,3 +33,12 @@ jobs:
36
33
  uses: github/codeql-action/autobuild@v1
37
34
  - name: "Perform CodeQL Analysis"
38
35
  uses: github/codeql-action/analyze@v1
36
+ - uses: ruby/setup-ruby@v1
37
+ with:
38
+ ruby-version: '2.7'
39
+ bundler-cache: true
40
+ - name: "Run rufo code formatting checks"
41
+ run: |
42
+ gem install rufo
43
+ rufo --check ./lib
44
+ rufo --check ./spec
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: Docs
3
+
4
+ on:
5
+ push:
6
+ branches:
7
+ - develop
8
+
9
+ jobs:
10
+ docs:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+ - uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: '2.7'
17
+ bundler-cache: true
18
+ - name: Run Yard Doc
19
+ run: |
20
+ gem install yard
21
+ yard doc
22
+ - name: Deploy GH Pages
23
+ uses: JamesIves/github-pages-deploy-action@4.1.7
24
+ with:
25
+ branch: gh-pages
26
+ folder: doc/
data/Gemfile CHANGED
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source 'https://rubygems.org'
3
+ # ref: https://github.com/GemHQ/money-tree/issues/50
4
+ gem "money-tree", git: "https://github.com/GemHQ/money-tree.git"
5
+
6
+ source "https://rubygems.org"
4
7
 
5
8
  # Specify your gem's dependencies in eth.gemspec
6
9
  gemspec
data/eth.gemspec CHANGED
@@ -1,46 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
  # coding: utf-8
3
3
 
4
- lib = File.expand_path('lib', __dir__).freeze
4
+ lib = File.expand_path("lib", __dir__).freeze
5
5
  $LOAD_PATH.unshift lib unless $LOAD_PATH.include? lib
6
6
 
7
- require 'eth/version'
7
+ require "eth/version"
8
8
 
9
9
  Gem::Specification.new do |spec|
10
- spec.name = "eth"
11
- spec.version = Eth::VERSION
12
- spec.authors = ["Steve Ellis", "Afri Schoedon"]
13
- spec.email = ["email@steveell.is", "ruby@q9f.cc"]
10
+ spec.name = "eth"
11
+ spec.version = Eth::VERSION
12
+ spec.authors = ["Steve Ellis", "Afri Schoedon"]
13
+ spec.email = ["email@steveell.is", "ruby@q9f.cc"]
14
14
 
15
- spec.summary = %q{Simple API to sign Ethereum transactions.}
16
- spec.description = %q{Library to build, parse, and sign Ethereum transactions.}
17
- spec.homepage = "https://github.com/se3000/ruby-eth"
18
- spec.license = "MIT"
15
+ spec.summary = %q{Simple API to sign Ethereum transactions.}
16
+ spec.description = %q{Library to build, parse, and sign Ethereum transactions.}
17
+ spec.homepage = "https://github.com/se3000/ruby-eth"
18
+ spec.license = "MIT"
19
19
 
20
20
  spec.metadata = {
21
- 'homepage_uri' => 'https://github.com/se3000/ruby-eth',
22
- 'source_code_uri' => 'https://github.com/se3000/ruby-eth',
23
- 'github_repo' => 'https://github.com/se3000/ruby-eth',
24
- 'bug_tracker_uri' => 'https://github.com/se3000/ruby-eth/issues',
21
+ "homepage_uri" => "https://github.com/se3000/ruby-eth",
22
+ "source_code_uri" => "https://github.com/se3000/ruby-eth",
23
+ "github_repo" => "https://github.com/se3000/ruby-eth",
24
+ "bug_tracker_uri" => "https://github.com/se3000/ruby-eth/issues",
25
25
  }.freeze
26
26
 
27
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28
- spec.bindir = "exe"
29
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
30
  spec.require_paths = ["lib"]
31
- spec.test_files = spec.files.grep %r{^(test|spec|features)/}
31
+ spec.test_files = spec.files.grep %r{^(test|spec|features)/}
32
32
 
33
- spec.add_dependency 'keccak', '~> 1.3'
34
- spec.add_dependency 'ffi', '~> 1.15'
35
- spec.add_dependency 'money-tree', '~> 0.10'
36
- spec.add_dependency 'rlp', '~> 0.7'
37
- spec.add_dependency 'scrypt', '~> 3.0'
33
+ spec.add_dependency "keccak", "~> 1.3"
34
+ spec.add_dependency "ffi", "~> 1.15"
35
+ spec.add_dependency "money-tree", "~> 0.11"
36
+ spec.add_dependency "openssl", "~> 3.0"
37
+ spec.add_dependency "rlp", "~> 0.7"
38
+ spec.add_dependency "scrypt", "~> 3.0"
38
39
 
39
40
  spec.platform = Gem::Platform::RUBY
40
- spec.required_ruby_version = ">= 2.2", "< 4.0"
41
+ spec.required_ruby_version = ">= 2.6", "< 4.0"
41
42
 
42
- spec.add_development_dependency 'bundler', '~> 2.2'
43
- spec.add_development_dependency 'pry', '~> 0.14'
44
- spec.add_development_dependency 'rake', '~> 13.0'
45
- spec.add_development_dependency 'rspec', '~> 3.10'
43
+ spec.add_development_dependency "bundler", "~> 2.2"
44
+ spec.add_development_dependency "pry", "~> 0.14"
45
+ spec.add_development_dependency "rake", "~> 13.0"
46
+ spec.add_development_dependency "rspec", "~> 3.10"
46
47
  end
data/lib/eth/address.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  module Eth
2
2
  class Address
3
-
4
3
  def initialize(address)
5
4
  @address = Utils.prefix_hex(address)
6
5
  end
@@ -25,7 +24,6 @@ module Eth
25
24
  Utils.prefix_hex(cased.join)
26
25
  end
27
26
 
28
-
29
27
  private
30
28
 
31
29
  attr_reader :address
@@ -57,6 +55,5 @@ module Eth
57
55
  def unprefixed
58
56
  Utils.remove_hex_prefix address
59
57
  end
60
-
61
58
  end
62
59
  end
data/lib/eth/gas.rb CHANGED
@@ -1,9 +1,7 @@
1
1
  module Eth
2
2
  class Gas
3
-
4
3
  GTXCOST = 21000 # TX BASE GAS COST
5
4
  GTXDATANONZERO = 68 # TX DATA NON ZERO BYTE GAS COST
6
5
  GTXDATAZERO = 4 # TX DATA ZERO BYTE GAS COST
7
-
8
6
  end
9
7
  end
@@ -1,5 +1,5 @@
1
- require 'json'
2
- require 'scrypt'
1
+ require "json"
2
+ require "scrypt"
3
3
 
4
4
  class Eth::Key::Decrypter
5
5
  include Eth::Utils
@@ -19,16 +19,15 @@ class Eth::Key::Decrypter
19
19
  bin_to_hex decrypted_data
20
20
  end
21
21
 
22
-
23
22
  private
24
23
 
25
24
  attr_reader :data, :key, :password
26
25
 
27
26
  def derive_key(password)
28
27
  case kdf
29
- when 'pbkdf2'
28
+ when "pbkdf2"
30
29
  @key = OpenSSL::PKCS5.pbkdf2_hmac(password, salt, iterations, key_length, digest)
31
- when 'scrypt'
30
+ when "scrypt"
32
31
  # OpenSSL 1.1 inclues OpenSSL::KDF.scrypt, but it is not available usually, otherwise we could do: OpenSSL::KDF.scrypt(password, salt: salt, N: n, r: r, p: p, length: key_length)
33
32
  @key = SCrypt::Engine.scrypt(password, salt, n, r, p, key_length)
34
33
  else
@@ -37,8 +36,8 @@ class Eth::Key::Decrypter
37
36
  end
38
37
 
39
38
  def check_macs
40
- mac1 = keccak256(key[(key_length/2), key_length] + ciphertext)
41
- mac2 = hex_to_bin crypto_data['mac']
39
+ mac1 = keccak256(key[(key_length / 2), key_length] + ciphertext)
40
+ mac2 = hex_to_bin crypto_data["mac"]
42
41
 
43
42
  if mac1 != mac2
44
43
  raise "Message Authentications Codes do not match!"
@@ -50,11 +49,11 @@ class Eth::Key::Decrypter
50
49
  end
51
50
 
52
51
  def crypto_data
53
- @crypto_data ||= data['crypto'] || data['Crypto']
52
+ @crypto_data ||= data["crypto"] || data["Crypto"]
54
53
  end
55
54
 
56
55
  def ciphertext
57
- hex_to_bin crypto_data['ciphertext']
56
+ hex_to_bin crypto_data["ciphertext"]
58
57
  end
59
58
 
60
59
  def cipher_name
@@ -64,41 +63,41 @@ class Eth::Key::Decrypter
64
63
  def cipher
65
64
  @cipher ||= OpenSSL::Cipher.new(cipher_name).tap do |cipher|
66
65
  cipher.decrypt
67
- cipher.key = key[0, (key_length/2)]
66
+ cipher.key = key[0, (key_length / 2)]
68
67
  cipher.iv = iv
69
68
  end
70
69
  end
71
70
 
72
71
  def iv
73
- hex_to_bin crypto_data['cipherparams']['iv']
72
+ hex_to_bin crypto_data["cipherparams"]["iv"]
74
73
  end
75
74
 
76
75
  def salt
77
- hex_to_bin crypto_data['kdfparams']['salt']
76
+ hex_to_bin crypto_data["kdfparams"]["salt"]
78
77
  end
79
78
 
80
79
  def iterations
81
- crypto_data['kdfparams']['c'].to_i
80
+ crypto_data["kdfparams"]["c"].to_i
82
81
  end
83
82
 
84
83
  def kdf
85
- crypto_data['kdf']
84
+ crypto_data["kdf"]
86
85
  end
87
86
 
88
87
  def key_length
89
- crypto_data['kdfparams']['dklen'].to_i
88
+ crypto_data["kdfparams"]["dklen"].to_i
90
89
  end
91
90
 
92
91
  def n
93
- crypto_data['kdfparams']['n'].to_i
92
+ crypto_data["kdfparams"]["n"].to_i
94
93
  end
95
94
 
96
95
  def r
97
- crypto_data['kdfparams']['r'].to_i
96
+ crypto_data["kdfparams"]["r"].to_i
98
97
  end
99
98
 
100
99
  def p
101
- crypto_data['kdfparams']['p'].to_i
100
+ crypto_data["kdfparams"]["p"].to_i
102
101
  end
103
102
 
104
103
  def digest
@@ -108,6 +107,4 @@ class Eth::Key::Decrypter
108
107
  def digest_name
109
108
  "sha256"
110
109
  end
111
-
112
-
113
110
  end
@@ -1,5 +1,5 @@
1
- require 'json'
2
- require 'securerandom'
1
+ require "json"
2
+ require "securerandom"
3
3
 
4
4
  class Eth::Key::Encrypter
5
5
  include Eth::Utils
@@ -48,7 +48,6 @@ class Eth::Key::Encrypter
48
48
  @id ||= options[:id] || SecureRandom.uuid
49
49
  end
50
50
 
51
-
52
51
  private
53
52
 
54
53
  attr_reader :derived_key, :encrypted_key, :key, :options
@@ -57,7 +56,7 @@ class Eth::Key::Encrypter
57
56
  @cipher ||= OpenSSL::Cipher.new(cipher_name).tap do |cipher|
58
57
  cipher.encrypt
59
58
  cipher.iv = iv
60
- cipher.key = derived_key[0, (key_length/2)]
59
+ cipher.key = derived_key[0, (key_length / 2)]
61
60
  end
62
61
  end
63
62
 
@@ -74,7 +73,7 @@ class Eth::Key::Encrypter
74
73
  end
75
74
 
76
75
  def mac
77
- keccak256(derived_key[(key_length/2), key_length] + encrypted_key)
76
+ keccak256(derived_key[(key_length / 2), key_length] + encrypted_key)
78
77
  end
79
78
 
80
79
  def cipher_name
@@ -107,22 +106,21 @@ class Eth::Key::Encrypter
107
106
 
108
107
  def salt
109
108
  @salt ||= if options[:salt]
110
- hex_to_bin options[:salt]
111
- else
112
- SecureRandom.random_bytes(salt_length)
113
- end
109
+ hex_to_bin options[:salt]
110
+ else
111
+ SecureRandom.random_bytes(salt_length)
112
+ end
114
113
  end
115
114
 
116
115
  def iv
117
116
  @iv ||= if options[:iv]
118
- hex_to_bin options[:iv]
119
- else
120
- SecureRandom.random_bytes(iv_length)
121
- end
117
+ hex_to_bin options[:iv]
118
+ else
119
+ SecureRandom.random_bytes(iv_length)
120
+ end
122
121
  end
123
122
 
124
123
  def address
125
124
  Eth::Key.new(priv: key).address
126
125
  end
127
-
128
126
  end
data/lib/eth/key.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Eth
2
2
  class Key
3
- autoload :Decrypter, 'eth/key/decrypter'
4
- autoload :Encrypter, 'eth/key/encrypter'
3
+ autoload :Decrypter, "eth/key/decrypter"
4
+ autoload :Encrypter, "eth/key/encrypter"
5
5
 
6
6
  attr_reader :private_key, :public_key
7
7
 
@@ -17,7 +17,7 @@ module Eth
17
17
  end
18
18
 
19
19
  def self.personal_recover(message, signature)
20
- bin_signature = Utils.hex_to_bin(signature).bytes.rotate(-1).pack('c*')
20
+ bin_signature = Utils.hex_to_bin(signature).bytes.rotate(-1).pack("c*")
21
21
  OpenSsl.recover_compact(Utils.keccak256(Utils.prefix_message(message)), bin_signature)
22
22
  end
23
23
 
@@ -41,6 +41,7 @@ module Eth
41
41
  def address
42
42
  Utils.public_key_to_address public_hex
43
43
  end
44
+
44
45
  alias_method :to_address, :address
45
46
 
46
47
  def sign(message)
@@ -60,10 +61,9 @@ module Eth
60
61
  end
61
62
 
62
63
  def personal_sign(message)
63
- Utils.bin_to_hex(sign(Utils.prefix_message(message)).bytes.rotate(1).pack('c*'))
64
+ Utils.bin_to_hex(sign(Utils.prefix_message(message)).bytes.rotate(1).pack("c*"))
64
65
  end
65
66
 
66
-
67
67
  private
68
68
 
69
69
  def message_hash(message)
@@ -72,8 +72,7 @@ module Eth
72
72
 
73
73
  def valid_s?(signature)
74
74
  s_value = Utils.v_r_s_for(signature).last
75
- s_value <= Secp256k1::N/2 && s_value != 0
75
+ s_value <= Secp256k1::N / 2 && s_value != 0
76
76
  end
77
-
78
77
  end
79
78
  end
data/lib/eth/open_ssl.rb CHANGED
@@ -1,28 +1,22 @@
1
1
  # originally lifted from https://github.com/lian/bitcoin-ruby
2
2
  # thanks to everyone there for figuring this out
3
3
 
4
+ # encoding: ascii-8bit
5
+
6
+ require "openssl"
7
+ require "ffi"
8
+
4
9
  module Eth
5
10
  class OpenSsl
6
11
  extend FFI::Library
7
12
 
8
- if FFI::Platform.windows?
9
- ffi_lib 'libeay32', 'ssleay32'
10
- else
11
- ffi_lib [
12
- 'libssl.so.1.1.0', 'libssl.so.1.1',
13
- 'libssl.so.1.0.0', 'libssl.so.10',
14
- 'ssl'
15
- ]
16
- end
13
+ # Use the library loaded by the extension require above.
14
+ ffi_lib FFI::CURRENT_PROCESS
17
15
 
18
16
  NID_secp256k1 = 714
19
17
  POINT_CONVERSION_COMPRESSED = 2
20
18
  POINT_CONVERSION_UNCOMPRESSED = 4
21
19
 
22
- # OpenSSL 1.1.0 version as a numerical version value as defined in:
23
- # https://www.openssl.org/docs/man1.1.0/man3/OpenSSL_version.html
24
- VERSION_1_1_0_NUM = 0x10100000
25
-
26
20
  # OpenSSL 1.1.0 engine constants, taken from:
27
21
  # https://github.com/openssl/openssl/blob/2be8c56a39b0ec2ec5af6ceaf729df154d784a43/include/openssl/crypto.h
28
22
  OPENSSL_INIT_ENGINE_RDRAND = 0x00000200
@@ -30,13 +24,11 @@ module Eth
30
24
  OPENSSL_INIT_ENGINE_CRYPTODEV = 0x00001000
31
25
  OPENSSL_INIT_ENGINE_CAPI = 0x00002000
32
26
  OPENSSL_INIT_ENGINE_PADLOCK = 0x00004000
33
- OPENSSL_INIT_ENGINE_ALL_BUILTIN = (
34
- OPENSSL_INIT_ENGINE_RDRAND |
35
- OPENSSL_INIT_ENGINE_DYNAMIC |
36
- OPENSSL_INIT_ENGINE_CRYPTODEV |
37
- OPENSSL_INIT_ENGINE_CAPI |
38
- OPENSSL_INIT_ENGINE_PADLOCK
39
- )
27
+ OPENSSL_INIT_ENGINE_ALL_BUILTIN = (OPENSSL_INIT_ENGINE_RDRAND |
28
+ OPENSSL_INIT_ENGINE_DYNAMIC |
29
+ OPENSSL_INIT_ENGINE_CRYPTODEV |
30
+ OPENSSL_INIT_ENGINE_CAPI |
31
+ OPENSSL_INIT_ENGINE_PADLOCK)
40
32
 
41
33
  # OpenSSL 1.1.0 load strings constant, taken from:
42
34
  # https://github.com/openssl/openssl/blob/c162c126be342b8cd97996346598ecf7db56130f/include/openssl/ssl.h
@@ -50,215 +42,354 @@ module Eth
50
42
  attach_function :SSLeay, [], :long
51
43
  end
52
44
 
53
- # Returns the version of SSL present.
54
- #
55
- # @return [Integer] version number as an integer.
56
- def self.version
57
- if self.respond_to?(:OpenSSL_version_num)
58
- OpenSSL_version_num()
59
- else
60
- SSLeay()
61
- end
62
- end
63
-
64
- if version >= VERSION_1_1_0_NUM
45
+ begin
65
46
  # Initialization procedure for the library was changed in OpenSSL 1.1.0
66
47
  attach_function :OPENSSL_init_ssl, [:uint64, :pointer], :int
67
- else
48
+ rescue FFI::NotFoundError
68
49
  attach_function :SSL_library_init, [], :int
69
50
  attach_function :ERR_load_crypto_strings, [], :void
70
51
  attach_function :SSL_load_error_strings, [], :void
71
52
  end
72
53
 
73
54
  attach_function :RAND_poll, [], :int
55
+
74
56
  attach_function :BN_CTX_free, [:pointer], :int
75
57
  attach_function :BN_CTX_new, [], :pointer
76
- attach_function :BN_add, [:pointer, :pointer, :pointer], :int
77
- attach_function :BN_bin2bn, [:pointer, :int, :pointer], :pointer
78
- attach_function :BN_bn2bin, [:pointer, :pointer], :int
79
- attach_function :BN_cmp, [:pointer, :pointer], :int
58
+ attach_function :BN_add, %i[pointer pointer pointer], :int
59
+ attach_function :BN_bin2bn, %i[pointer int pointer], :pointer
60
+ attach_function :BN_bn2bin, %i[pointer pointer], :int
61
+ attach_function :BN_cmp, %i[pointer pointer], :int
80
62
  attach_function :BN_dup, [:pointer], :pointer
81
63
  attach_function :BN_free, [:pointer], :int
82
- attach_function :BN_mod_inverse, [:pointer, :pointer, :pointer, :pointer], :pointer
83
- attach_function :BN_mod_mul, [:pointer, :pointer, :pointer, :pointer, :pointer], :int
84
- attach_function :BN_mod_sub, [:pointer, :pointer, :pointer, :pointer, :pointer], :int
85
- attach_function :BN_mul_word, [:pointer, :int], :int
64
+ attach_function :BN_mod_inverse, %i[pointer pointer pointer pointer], :pointer
65
+ attach_function :BN_mod_mul, %i[pointer pointer pointer pointer pointer], :int
66
+ attach_function :BN_mod_sub, %i[pointer pointer pointer pointer pointer], :int
67
+ attach_function :BN_mul_word, %i[pointer int], :int
86
68
  attach_function :BN_new, [], :pointer
87
- attach_function :BN_num_bits, [:pointer], :int
88
- attach_function :BN_rshift, [:pointer, :pointer, :int], :int
89
- attach_function :BN_set_word, [:pointer, :int], :int
90
- attach_function :ECDSA_SIG_free, [:pointer], :void
91
- attach_function :ECDSA_do_sign, [:pointer, :uint, :pointer], :pointer
92
- attach_function :EC_GROUP_get_curve_GFp, [:pointer, :pointer, :pointer, :pointer, :pointer], :int
69
+ attach_function :BN_rshift, %i[pointer pointer int], :int
70
+ attach_function :BN_rshift1, %i[pointer pointer], :int
71
+ attach_function :BN_set_word, %i[pointer int], :int
72
+ attach_function :BN_sub, %i[pointer pointer pointer], :int
73
+ attach_function :EC_GROUP_get_curve_GFp, %i[pointer pointer pointer pointer pointer], :int
93
74
  attach_function :EC_GROUP_get_degree, [:pointer], :int
94
- attach_function :EC_GROUP_get_order, [:pointer, :pointer, :pointer], :int
75
+ attach_function :EC_GROUP_get_order, %i[pointer pointer pointer], :int
95
76
  attach_function :EC_KEY_free, [:pointer], :int
96
77
  attach_function :EC_KEY_get0_group, [:pointer], :pointer
78
+ attach_function :EC_KEY_get0_private_key, [:pointer], :pointer
97
79
  attach_function :EC_KEY_new_by_curve_name, [:int], :pointer
98
- attach_function :EC_KEY_set_conv_form, [:pointer, :int], :void
99
- attach_function :EC_KEY_set_private_key, [:pointer, :pointer], :int
100
- attach_function :EC_KEY_set_public_key, [:pointer, :pointer], :int
80
+ attach_function :EC_KEY_set_conv_form, %i[pointer int], :void
81
+ attach_function :EC_KEY_set_private_key, %i[pointer pointer], :int
82
+ attach_function :EC_KEY_set_public_key, %i[pointer pointer], :int
101
83
  attach_function :EC_POINT_free, [:pointer], :int
102
- attach_function :EC_POINT_mul, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer], :int
84
+ attach_function :EC_POINT_mul, %i[pointer pointer pointer pointer pointer pointer], :int
103
85
  attach_function :EC_POINT_new, [:pointer], :pointer
104
- attach_function :EC_POINT_set_compressed_coordinates_GFp, [:pointer, :pointer, :pointer, :int, :pointer], :int
105
- attach_function :i2o_ECPublicKey, [:pointer, :pointer], :uint
86
+ attach_function :EC_POINT_set_compressed_coordinates_GFp,
87
+ %i[pointer pointer pointer int pointer], :int
88
+ attach_function :i2o_ECPublicKey, %i[pointer pointer], :uint
89
+ attach_function :ECDSA_do_sign, %i[pointer uint pointer], :pointer
90
+ attach_function :BN_num_bits, [:pointer], :int
91
+ attach_function :ECDSA_SIG_free, [:pointer], :void
92
+ attach_function :EC_POINT_add, %i[pointer pointer pointer pointer pointer], :int
93
+ attach_function :EC_POINT_point2hex, %i[pointer pointer int pointer], :string
94
+ attach_function :EC_POINT_hex2point, %i[pointer string pointer pointer], :pointer
95
+ attach_function :d2i_ECDSA_SIG, %i[pointer pointer long], :pointer
96
+ attach_function :i2d_ECDSA_SIG, %i[pointer pointer], :int
97
+ attach_function :OPENSSL_free, :CRYPTO_free, [:pointer], :void
98
+
99
+ def self.BN_num_bytes(ptr) # rubocop:disable Naming/MethodName
100
+ (BN_num_bits(ptr) + 7) / 8
101
+ end
106
102
 
107
- class << self
108
- def BN_num_bytes(ptr)
109
- (BN_num_bits(ptr) + 7) / 8
103
+ # resolve public from private key, using ffi and libssl.so
104
+ # example:
105
+ # keypair = Bitcoin.generate_key; Bitcoin::OpenSSL_EC.regenerate_key(keypair.first) == keypair
106
+ def self.regenerate_key(private_key)
107
+ private_key = [private_key].pack("H*") if private_key.bytesize >= (32 * 2)
108
+ private_key_hex = private_key.unpack("H*")[0]
109
+
110
+ group = OpenSSL::PKey::EC::Group.new("secp256k1")
111
+ key = OpenSSL::PKey::EC.new(group)
112
+ key.private_key = OpenSSL::BN.new(private_key_hex, 16)
113
+ key.public_key = group.generator.mul(key.private_key)
114
+
115
+ priv_hex = key.private_key.to_bn.to_s(16).downcase.rjust(64, "0")
116
+ if priv_hex != private_key_hex
117
+ raise "regenerated wrong private_key, raise here before generating a faulty public_key too!"
110
118
  end
111
119
 
112
- def sign_compact(hash, private_key, public_key_hex)
113
- private_key = [private_key].pack("H*") if private_key.bytesize >= 64
114
- pubkey_compressed = false
120
+ [priv_hex, key.public_key.to_bn.to_s(16).downcase]
121
+ end
115
122
 
116
- init_ffi_ssl
117
- eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
118
- priv_key = BN_bin2bn(private_key, private_key.bytesize, BN_new())
123
+ # Given the components of a signature and a selector value, recover and
124
+ # return the public key that generated the signature according to the
125
+ # algorithm in SEC1v2 section 4.1.6.
126
+ #
127
+ # rec_id is an index from 0 to 3 that indicates which of the 4 possible
128
+ # keys is the correct one. Because the key recovery operation yields
129
+ # multiple potential keys, the correct key must either be stored alongside
130
+ # the signature, or you must be willing to try each rec_id in turn until
131
+ # you find one that outputs the key you are expecting.
132
+ #
133
+ # If this method returns nil, it means recovery was not possible and rec_id
134
+ # should be iterated.
135
+ #
136
+ # Given the above two points, a correct usage of this method is inside a
137
+ # for loop from 0 to 3, and if the output is nil OR a key that is not the
138
+ # one you expect, you try again with the next rec_id.
139
+ #
140
+ # message_hash = hash of the signed message.
141
+ # signature = the R and S components of the signature, wrapped.
142
+ # rec_id = which possible key to recover.
143
+ # is_compressed = whether or not the original pubkey was compressed.
144
+ def self.recover_public_key_from_signature(message_hash, signature, rec_id, is_compressed)
145
+ return nil if rec_id < 0 || signature.bytesize != 65
146
+ init_ffi_ssl
147
+
148
+ signature = FFI::MemoryPointer.from_string(signature)
149
+ # signature_bn = BN_bin2bn(signature, 65, BN_new())
150
+ r = BN_bin2bn(signature[1], 32, BN_new())
151
+ s = BN_bin2bn(signature[33], 32, BN_new())
152
+
153
+ i = rec_id / 2
154
+ eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
155
+
156
+ EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED) if is_compressed
157
+
158
+ group = EC_KEY_get0_group(eckey)
159
+ order = BN_new()
160
+ EC_GROUP_get_order(group, order, nil)
161
+ x = BN_dup(order)
162
+ BN_mul_word(x, i)
163
+ BN_add(x, x, r)
164
+
165
+ field = BN_new()
166
+ EC_GROUP_get_curve_GFp(group, field, nil, nil, nil)
167
+
168
+ if BN_cmp(x, field) >= 0
169
+ [r, s, order, x, field].each { |item| BN_free(item) }
170
+ EC_KEY_free(eckey)
171
+ return nil
172
+ end
119
173
 
120
- group, order, ctx = EC_KEY_get0_group(eckey), BN_new(), BN_CTX_new()
121
- EC_GROUP_get_order(group, order, ctx)
174
+ big_r = EC_POINT_new(group)
175
+ EC_POINT_set_compressed_coordinates_GFp(group, big_r, x, rec_id % 2, nil)
176
+
177
+ big_q = EC_POINT_new(group)
178
+ n = EC_GROUP_get_degree(group)
179
+ e = BN_bin2bn(message_hash, message_hash.bytesize, BN_new())
180
+ BN_rshift(e, e, 8 - (n & 7)) if 8 * message_hash.bytesize > n
181
+
182
+ ctx = BN_CTX_new()
183
+ zero = BN_new()
184
+ rr = BN_new()
185
+ sor = BN_new()
186
+ eor = BN_new()
187
+ BN_set_word(zero, 0)
188
+ BN_mod_sub(e, zero, e, order, ctx)
189
+ BN_mod_inverse(rr, r, order, ctx)
190
+ BN_mod_mul(sor, s, rr, order, ctx)
191
+ BN_mod_mul(eor, e, rr, order, ctx)
192
+ EC_POINT_mul(group, big_q, eor, big_r, sor, ctx)
193
+ EC_KEY_set_public_key(eckey, big_q)
194
+ BN_CTX_free(ctx)
195
+
196
+ [r, s, order, x, field, e, zero, rr, sor, eor].each { |item| BN_free(item) }
197
+ [big_r, big_q].each { |item| EC_POINT_free(item) }
198
+
199
+ length = i2o_ECPublicKey(eckey, nil)
200
+ buf = FFI::MemoryPointer.new(:uint8, length)
201
+ ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
202
+ pub_hex = buf.read_string(length).unpack("H*")[0] if i2o_ECPublicKey(eckey, ptr) == length
203
+
204
+ EC_KEY_free(eckey)
205
+
206
+ pub_hex
207
+ end
122
208
 
123
- pub_key = EC_POINT_new(group)
124
- EC_POINT_mul(group, pub_key, priv_key, nil, nil, ctx)
125
- EC_KEY_set_private_key(eckey, priv_key)
126
- EC_KEY_set_public_key(eckey, pub_key)
209
+ # Regenerate a DER-encoded signature such that the S-value complies with the BIP62
210
+ # specification.
211
+ #
212
+ def self.signature_to_low_s(signature)
213
+ init_ffi_ssl
214
+
215
+ buf = FFI::MemoryPointer.new(:uint8, 34)
216
+ temp = signature.unpack("C*")
217
+ length_r = temp[3]
218
+ length_s = temp[5 + length_r]
219
+ sig = FFI::MemoryPointer.from_string(signature)
220
+
221
+ # Calculate the lower s value
222
+ s = BN_bin2bn(sig[6 + length_r], length_s, BN_new())
223
+ eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
224
+ group = EC_KEY_get0_group(eckey)
225
+ order = BN_new()
226
+ halforder = BN_new()
227
+ ctx = BN_CTX_new()
228
+
229
+ EC_GROUP_get_order(group, order, ctx)
230
+ BN_rshift1(halforder, order)
231
+ BN_sub(s, order, s) if BN_cmp(s, halforder) > 0
232
+
233
+ BN_free(halforder)
234
+ BN_free(order)
235
+ BN_CTX_free(ctx)
236
+
237
+ length_s = BN_bn2bin(s, buf)
238
+ # p buf.read_string(length_s).unpack("H*")
239
+
240
+ # Re-encode the signature in DER format
241
+ sig = [0x30, 0, 0x02, length_r]
242
+ sig.concat(temp.slice(4, length_r))
243
+ sig << 0x02
244
+ sig << length_s
245
+ sig.concat(buf.read_string(length_s).unpack("C*"))
246
+ sig[1] = sig.size - 2
247
+
248
+ BN_free(s)
249
+ EC_KEY_free(eckey)
250
+
251
+ sig.pack("C*")
252
+ end
127
253
 
128
- signature = ECDSA_do_sign(hash, hash.bytesize, eckey)
254
+ def self.sign_compact(hash, private_key, public_key_hex = nil, pubkey_compressed = nil)
255
+ msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hash)
129
256
 
130
- BN_free(order)
131
- BN_CTX_free(ctx)
132
- EC_POINT_free(pub_key)
133
- BN_free(priv_key)
134
- EC_KEY_free(eckey)
257
+ private_key = [private_key].pack("H*") if private_key.bytesize >= 64
258
+ private_key_hex = private_key.unpack("H*")[0]
135
259
 
136
- buf, rec_id, head = FFI::MemoryPointer.new(:uint8, 32), nil, nil
137
- r, s = signature.get_array_of_pointer(0, 2).map{|i| BN_bn2bin(i, buf); buf.read_string(BN_num_bytes(i)).rjust(32, "\x00") }
260
+ public_key_hex ||= regenerate_key(private_key_hex).last
261
+ pubkey_compressed ||= public_key_hex[0..1] != "04"
138
262
 
139
- if signature.get_array_of_pointer(0, 2).all?{|i| BN_num_bits(i) <= 256 }
140
- 4.times{|i|
141
- head = [ Eth.v_base + i ].pack("C")
142
- if public_key_hex == recover_public_key_from_signature(hash, [head, r, s].join, i, pubkey_compressed)
143
- rec_id = i; break
144
- end
145
- }
146
- end
263
+ init_ffi_ssl
264
+ eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
265
+ priv_key = BN_bin2bn(private_key, private_key.bytesize, BN_new())
147
266
 
148
- ECDSA_SIG_free(signature)
267
+ group = EC_KEY_get0_group(eckey)
268
+ order = BN_new()
269
+ ctx = BN_CTX_new()
270
+ EC_GROUP_get_order(group, order, ctx)
149
271
 
150
- [ head, [r,s] ].join if rec_id
151
- end
272
+ pub_key = EC_POINT_new(group)
273
+ EC_POINT_mul(group, pub_key, priv_key, nil, nil, ctx)
274
+ EC_KEY_set_private_key(eckey, priv_key)
275
+ EC_KEY_set_public_key(eckey, pub_key)
152
276
 
153
- def recover_public_key_from_signature(message_hash, signature, rec_id, is_compressed)
154
- return nil if rec_id < 0 or signature.bytesize != 65
155
- init_ffi_ssl
277
+ signature = ECDSA_do_sign(msg32, msg32.size, eckey)
156
278
 
157
- signature = FFI::MemoryPointer.from_string(signature)
158
- r = BN_bin2bn(signature[1], 32, BN_new())
159
- s = BN_bin2bn(signature[33], 32, BN_new())
279
+ BN_free(order)
280
+ BN_CTX_free(ctx)
281
+ EC_POINT_free(pub_key)
282
+ BN_free(priv_key)
283
+ EC_KEY_free(eckey)
160
284
 
161
- _n, i = 0, rec_id / 2
162
- eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
285
+ buf = FFI::MemoryPointer.new(:uint8, 32)
286
+ head = nil
287
+ r, s = signature.get_array_of_pointer(0, 2).map do |i|
288
+ BN_bn2bin(i, buf)
289
+ buf.read_string(BN_num_bytes(i)).rjust(32, "\x00")
290
+ end
163
291
 
164
- EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED) if is_compressed
292
+ rec_id = nil
293
+ if signature.get_array_of_pointer(0, 2).all? { |i| BN_num_bits(i) <= 256 }
294
+ 4.times do |i|
295
+ head = [27 + i + (pubkey_compressed ? 4 : 0)].pack("C")
296
+ recovered_key = recover_public_key_from_signature(
297
+ msg32.read_string(32), [head, r, s].join, i, pubkey_compressed
298
+ )
299
+ if public_key_hex == recovered_key
300
+ rec_id = i
301
+ break
302
+ end
303
+ end
304
+ end
165
305
 
166
- group = EC_KEY_get0_group(eckey)
167
- order = BN_new()
168
- EC_GROUP_get_order(group, order, nil)
169
- x = BN_dup(order)
170
- BN_mul_word(x, i)
171
- BN_add(x, x, r)
306
+ ECDSA_SIG_free(signature)
172
307
 
173
- field = BN_new()
174
- EC_GROUP_get_curve_GFp(group, field, nil, nil, nil)
308
+ [head, [r, s]].join if rec_id
309
+ end
175
310
 
176
- if BN_cmp(x, field) >= 0
177
- bn_free_each r, s, order, x, field
178
- EC_KEY_free(eckey)
179
- return nil
180
- end
311
+ def self.recover_compact(hash, signature)
312
+ return false if signature.bytesize != 65
313
+ msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hash)
314
+
315
+ version = signature.unpack("C")[0]
181
316
 
182
- big_r = EC_POINT_new(group)
183
- EC_POINT_set_compressed_coordinates_GFp(group, big_r, x, rec_id % 2, nil)
184
-
185
- big_q = EC_POINT_new(group)
186
- n = EC_GROUP_get_degree(group)
187
- e = BN_bin2bn(message_hash, message_hash.bytesize, BN_new())
188
- BN_rshift(e, e, 8 - (n & 7)) if 8 * message_hash.bytesize > n
189
-
190
- ctx = BN_CTX_new()
191
- zero, rr, sor, eor = BN_new(), BN_new(), BN_new(), BN_new()
192
- BN_set_word(zero, 0)
193
- BN_mod_sub(e, zero, e, order, ctx)
194
- BN_mod_inverse(rr, r, order, ctx)
195
- BN_mod_mul(sor, s, rr, order, ctx)
196
- BN_mod_mul(eor, e, rr, order, ctx)
197
- EC_POINT_mul(group, big_q, eor, big_r, sor, ctx)
198
- EC_KEY_set_public_key(eckey, big_q)
199
- BN_CTX_free(ctx)
200
-
201
- bn_free_each r, s, order, x, field, e, zero, rr, sor, eor
202
- [big_r, big_q].each{|j| EC_POINT_free(j) }
203
-
204
- recover_public_hex eckey
317
+ # Version of signature should be 27 or 28, but 0 and 1 are also possible versions
318
+ # which can show up in Ledger hardwallet signings
319
+ if version < 27
320
+ version += 27
205
321
  end
206
322
 
207
- def recover_compact(hash, signature)
208
- return false if signature.bytesize != 65
323
+ return false if version < 27 || version > 34
209
324
 
210
- version = signature.unpack('C')[0]
325
+ compressed = version >= 31
326
+ version -= 4 if compressed
211
327
 
212
- # Version of signature should be 27 or 28, but 0 and 1 are also possible versions
213
- # which can show up in Ledger hardwallet signings
214
- if version < 27
215
- version += 27
216
- end
328
+ recover_public_key_from_signature(msg32.read_string(32), signature, version - 27, compressed)
329
+ end
217
330
 
218
- v_base = Eth.replayable_v?(version) ? Eth.replayable_chain_id : Eth.v_base
331
+ # lifted from https://github.com/GemHQ/money-tree
332
+ def self.ec_add(point0, point1)
333
+ init_ffi_ssl
219
334
 
220
- return false if version < v_base
335
+ eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
336
+ group = EC_KEY_get0_group(eckey)
221
337
 
222
- recover_public_key_from_signature(hash, signature, (version - v_base), false)
223
- end
338
+ point_0_hex = point0.to_bn.to_s(16)
339
+ point_0_pt = EC_POINT_hex2point(group, point_0_hex, nil, nil)
340
+ point_1_hex = point1.to_bn.to_s(16)
341
+ point_1_pt = EC_POINT_hex2point(group, point_1_hex, nil, nil)
224
342
 
225
- def init_ffi_ssl
226
- return if @ssl_loaded
227
- if version >= VERSION_1_1_0_NUM
228
- OPENSSL_init_ssl(
229
- OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_ENGINE_ALL_BUILTIN,
230
- nil
231
- )
232
- else
233
- SSL_library_init()
234
- ERR_load_crypto_strings()
235
- SSL_load_error_strings()
236
- end
343
+ sum_point = EC_POINT_new(group)
344
+ EC_POINT_add(group, sum_point, point_0_pt, point_1_pt, nil)
345
+ hex = EC_POINT_point2hex(group, sum_point, POINT_CONVERSION_UNCOMPRESSED, nil)
346
+ EC_KEY_free(eckey)
347
+ EC_POINT_free(sum_point)
348
+ hex
349
+ end
237
350
 
238
- RAND_poll()
239
- @ssl_loaded = true
240
- end
351
+ # repack signature for OpenSSL 1.0.1k handling of DER signatures
352
+ # https://github.com/bitcoin/bitcoin/pull/5634/files
353
+ def self.repack_der_signature(signature)
354
+ init_ffi_ssl
241
355
 
356
+ return false if signature.empty?
242
357
 
243
- private
358
+ # New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
359
+ norm_der = FFI::MemoryPointer.new(:pointer)
360
+ sig_ptr = FFI::MemoryPointer.new(:pointer).put_pointer(
361
+ 0, FFI::MemoryPointer.from_string(signature)
362
+ )
244
363
 
245
- def bn_free_each(*list)
246
- list.each{|j| BN_free(j) }
247
- end
364
+ norm_sig = d2i_ECDSA_SIG(nil, sig_ptr, signature.bytesize)
248
365
 
249
- def recover_public_hex(eckey)
250
- length = i2o_ECPublicKey(eckey, nil)
251
- buf = FFI::MemoryPointer.new(:uint8, length)
252
- ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
253
- pub_hex = if i2o_ECPublicKey(eckey, ptr) == length
254
- buf.read_string(length).unpack("H*")[0]
255
- end
366
+ derlen = i2d_ECDSA_SIG(norm_sig, norm_der)
367
+ ECDSA_SIG_free(norm_sig)
368
+ return false if derlen <= 0
256
369
 
257
- EC_KEY_free(eckey)
370
+ ret = norm_der.read_pointer.read_string(derlen)
371
+ OPENSSL_free(norm_der.read_pointer)
258
372
 
259
- pub_hex
260
- end
373
+ ret
261
374
  end
262
375
 
376
+ def self.init_ffi_ssl
377
+ @ssl_loaded ||= false
378
+ return if @ssl_loaded
379
+
380
+ if self.method_defined?(:OPENSSL_init_ssl)
381
+ OPENSSL_init_ssl(
382
+ OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_ENGINE_ALL_BUILTIN,
383
+ nil
384
+ )
385
+ else
386
+ SSL_library_init()
387
+ ERR_load_crypto_strings()
388
+ SSL_load_error_strings()
389
+ end
390
+
391
+ RAND_poll()
392
+ @ssl_loaded = true
393
+ end
263
394
  end
264
395
  end
data/lib/eth/secp256k1.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  module Eth
2
2
  class Secp256k1
3
-
4
3
  N = 115792089237316195423570985008687907852837564279074904382605163141518161494337
5
-
6
4
  end
7
5
  end
data/lib/eth/sedes.rb CHANGED
@@ -35,6 +35,5 @@ module Eth
35
35
  def binary
36
36
  RLP::Sedes.binary
37
37
  end
38
-
39
38
  end
40
39
  end
data/lib/eth/tx.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  module Eth
2
2
  class Tx
3
-
4
3
  include RLP::Sedes::Serializable
5
4
  extend Sedes
6
5
 
@@ -13,7 +12,7 @@ module Eth
13
12
  data_bin: binary,
14
13
  v: big_endian_int,
15
14
  r: big_endian_int,
16
- s: big_endian_int
15
+ s: big_endian_int,
17
16
  })
18
17
 
19
18
  attr_writer :signature
@@ -28,7 +27,7 @@ module Eth
28
27
  end
29
28
 
30
29
  def initialize(params)
31
- fields = {v: 0, r: 0, s: 0}.merge params
30
+ fields = { v: 0, r: 0, s: 0 }.merge params
32
31
  fields[:to] = Utils.normalize_address(fields[:to])
33
32
 
34
33
  self.chain_id = (params[:chain_id]) ? params.delete(:chain_id) : Eth.chain_id
@@ -105,6 +104,7 @@ module Eth
105
104
  def hash
106
105
  "0x#{Utils.bin_to_hex Utils.keccak256_rlp(self)}"
107
106
  end
107
+
108
108
  alias_method :id, :hash
109
109
 
110
110
  def data_hex
@@ -120,7 +120,7 @@ module Eth
120
120
  end
121
121
 
122
122
  def data=(string)
123
- Eth.tx_data_hex? ? self.data_hex=(string) : self.data_bin=(string)
123
+ Eth.tx_data_hex? ? self.data_hex = (string) : self.data_bin = (string)
124
124
  end
125
125
 
126
126
  def chain_id
@@ -190,7 +190,6 @@ module Eth
190
190
  UnsignedTx
191
191
  end
192
192
  end
193
-
194
193
  end
195
194
 
196
195
  UnsignedTx = Tx.exclude([:v, :r, :s])
data/lib/eth/utils.rb CHANGED
@@ -3,11 +3,11 @@ module Eth
3
3
  extend self
4
4
 
5
5
  def normalize_address(address)
6
- if address.nil? || address == ''
7
- ''
6
+ if address.nil? || address == ""
7
+ ""
8
8
  elsif address.size == 40
9
9
  hex_to_bin address
10
- elsif address.size == 42 && address[0..1] == '0x'
10
+ elsif address.size == 42 && address[0..1] == "0x"
11
11
  hex_to_bin address[2..-1]
12
12
  else
13
13
  address
@@ -23,7 +23,7 @@ module Eth
23
23
  end
24
24
 
25
25
  def base256_to_int(str)
26
- RLP::Sedes.big_endian_int.deserialize str.sub(/\A(\x00)+/, '')
26
+ RLP::Sedes.big_endian_int.deserialize str.sub(/\A(\x00)+/, "")
27
27
  end
28
28
 
29
29
  def int_to_base256(int)
@@ -43,7 +43,7 @@ module Eth
43
43
  end
44
44
 
45
45
  def remove_hex_prefix(s)
46
- s[0,2] == '0x' ? s[2..-1] : s
46
+ s[0, 2] == "0x" ? s[2..-1] : s
47
47
  end
48
48
 
49
49
  def bin_to_prefixed_hex(binary)
@@ -89,14 +89,14 @@ module Eth
89
89
  end
90
90
 
91
91
  def zunpad(x)
92
- x.sub(/\A\x00+/, '')
92
+ x.sub(/\A\x00+/, "")
93
93
  end
94
94
 
95
- def zpad_int(n, l=32)
95
+ def zpad_int(n, l = 32)
96
96
  zpad encode_int(n), l
97
97
  end
98
98
 
99
- def zpad_hex(s, l=32)
99
+ def zpad_hex(s, l = 32)
100
100
  zpad decode_hex(s), l
101
101
  end
102
102
 
@@ -108,8 +108,6 @@ module Eth
108
108
  Address.new(address).checksummed
109
109
  end
110
110
 
111
-
112
-
113
111
  private
114
112
 
115
113
  def lpad(x, symbol, l)
@@ -124,6 +122,5 @@ module Eth
124
122
 
125
123
  int_to_base256 n
126
124
  end
127
-
128
125
  end
129
126
  end
data/lib/eth/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eth
2
- VERSION = "0.4.17"
2
+ VERSION = "0.4.18"
3
3
  end
data/lib/eth.rb CHANGED
@@ -1,20 +1,20 @@
1
- require 'digest/keccak'
2
- require 'ffi'
3
- require 'money-tree'
4
- require 'rlp'
1
+ require "digest/keccak"
2
+ require "ffi"
3
+ require "money-tree"
4
+ require "rlp"
5
5
 
6
6
  module Eth
7
7
  BYTE_ZERO = "\x00".freeze
8
- UINT_MAX = 2**256 - 1
8
+ UINT_MAX = 2 ** 256 - 1
9
9
 
10
- autoload :Address, 'eth/address'
11
- autoload :Gas, 'eth/gas'
12
- autoload :Key, 'eth/key'
13
- autoload :OpenSsl, 'eth/open_ssl'
14
- autoload :Secp256k1, 'eth/secp256k1'
15
- autoload :Sedes, 'eth/sedes'
16
- autoload :Tx, 'eth/tx'
17
- autoload :Utils, 'eth/utils'
10
+ autoload :Address, "eth/address"
11
+ autoload :Gas, "eth/gas"
12
+ autoload :Key, "eth/key"
13
+ autoload :OpenSsl, "eth/open_ssl"
14
+ autoload :Secp256k1, "eth/secp256k1"
15
+ autoload :Sedes, "eth/sedes"
16
+ autoload :Tx, "eth/tx"
17
+ autoload :Utils, "eth/utils"
18
18
 
19
19
  class << self
20
20
  def configure
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.17
4
+ version: 0.4.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Ellis
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-12-01 00:00:00.000000000 Z
12
+ date: 2022-01-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: keccak
@@ -45,14 +45,28 @@ dependencies:
45
45
  requirements:
46
46
  - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '0.10'
48
+ version: '0.11'
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: '0.10'
55
+ version: '0.11'
56
+ - !ruby/object:Gem::Dependency
57
+ name: openssl
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
56
70
  - !ruby/object:Gem::Dependency
57
71
  name: rlp
58
72
  requirement: !ruby/object:Gem::Requirement
@@ -147,6 +161,7 @@ extra_rdoc_files: []
147
161
  files:
148
162
  - ".github/workflows/build.yml"
149
163
  - ".github/workflows/codeql.yml"
164
+ - ".github/workflows/docs.yml"
150
165
  - ".gitignore"
151
166
  - ".gitmodules"
152
167
  - ".rspec"
@@ -186,7 +201,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
186
201
  requirements:
187
202
  - - ">="
188
203
  - !ruby/object:Gem::Version
189
- version: '2.2'
204
+ version: '2.6'
190
205
  - - "<"
191
206
  - !ruby/object:Gem::Version
192
207
  version: '4.0'
@@ -196,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
211
  - !ruby/object:Gem::Version
197
212
  version: '0'
198
213
  requirements: []
199
- rubygems_version: 3.2.31
214
+ rubygems_version: 3.2.32
200
215
  signing_key:
201
216
  specification_version: 4
202
217
  summary: Simple API to sign Ethereum transactions.