contracthashtool 0.0.1 → 0.0.2

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: 5ea9a50c8b3de136a68cb441d43095480f5a56a6
4
- data.tar.gz: 4d4289f4a76d6798e9915c4a0f4f845c57539e4f
3
+ metadata.gz: 08284e65956a5805962806d2f4ba2748d792655c
4
+ data.tar.gz: 9a2aa606c96675f60d95ef93329256526ec098cc
5
5
  SHA512:
6
- metadata.gz: cd2dd769fb0e97861e4af5cc90ee490663ed43d982b4a1892b751b8babee6b6eed7ed4a39a364ecc50a066d431217df89410f1c563d8c929c639f6d22d23b415
7
- data.tar.gz: b55a653977efabc2c6dbc92ab1fff871943bf1ca2450aef613938214c96996764ce8520de51c0ed696a174ea977288ad73536a66e3d0330c3b41122c09a42aef
6
+ metadata.gz: c330b0fb70042dc4c010e07ce86b21304cb6418fab35f2f096990b051c83ec1c89f05bb895193e2caf765588f97702bb8a9388ed13b6435177bcb08d7195323a
7
+ data.tar.gz: 615298ef744d2d9dd860e73d9375307cc86ba4cece7eaf8d7eb649076fbf5778851a69b060f94f7962809e2348b5302e77255e6d5fba1d587ab663a7c6c69dfa
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
- # Contracthashtool
1
+ # contracthashtool-ruby
2
2
 
3
- Ruby port of https://github.com/Blockstream/contracthashtool
3
+ Ruby port of: https://github.com/Blockstream/contracthashtool
4
+
5
+ See also Appendix A of: https://blockstream.com/sidechains.pdf
4
6
 
5
7
  ## Installation
6
8
 
@@ -26,22 +28,52 @@ require 'bitcoin'
26
28
 
27
29
  Bitcoin.network = :testnet3
28
30
 
29
- r = '5121038695b28f1649c711aedb1fec8df54874334cfb7ddf31ba3132a94d00bdc9715251ae'
30
- p = 'cMcpaCT6pHkyS4347i4rSmecaQtLiu1eH28NWmBiePn8bi6N4kzh'
31
- a = 'mqWkEAFeQdrQvyaWNRn5vijPJeiQAjtxL2'
32
- n = '3a11be476485a6273fad4a0e09117d42'
31
+ # Example parameters from the original tool's usage().
32
+
33
+ redeem_script_template = '5121038695b28f1649c711aedb1fec8df54874334cfb7ddf31ba3132a94d00bdc9715251ae'
34
+ payee_address = 'mqWkEAFeQdrQvyaWNRn5vijPJeiQAjtxL2'
35
+ nonce_hex = '3a11be476485a6273fad4a0e09117d42'
36
+ private_key_wif = 'cMcpaCT6pHkyS4347i4rSmecaQtLiu1eH28NWmBiePn8bi6N4kzh'
37
+
38
+ # Someone wanting to send funds to the sidechain would call this
39
+ # to calculate a P2SH address to send to. They would then send the
40
+ # MDFs (mutually distrusting functionaries) the target address
41
+ # and nonce so they are able to locate the subsequent transaction.
42
+ # The caller would then send the desired amount of coin to the P2SH
43
+ # address to initiate the peg protocol.
44
+
45
+ nonce, redeem_script, p2sh_address =
46
+ Contracthashtool.generate(redeem_script_template, payee_address, nonce_hex)
47
+
48
+ puts "nonce: #{nonce}"
49
+ puts "P2SH address: #{p2sh_address}"
50
+ puts "new redeem script: #{redeem_script}"
51
+
52
+ # Each MDF would call this to derive a private key to redeem the
53
+ # cross-chain seed transaction after the confirmation period lapses.
54
+ # They would then presumably create and sign a transaction on the
55
+ # sidechain paying the desired amount of sidecoin to the target address.
56
+ # And then we've succeeded in executing one direction of a federated peg.
57
+ # Rinse, wash, and repeat to go back.
58
+
59
+ key = Contracthashtool.claim(private_key_wif, payee_address, nonce)
60
+ puts "new privkey: #{key.to_base58}"
33
61
 
34
- nonce, p2sh_address = Contracthashtool.generate(r,a,n)
35
- puts "nonce: #{nonce}, address: #{p2sh_address}"
62
+ # Verify homomorphic derivation was successful.
36
63
 
37
- key = Contracthashtool.claim(p,a,n)
38
- puts "new privkey: #{key.to_base58}
64
+ signature = key.sign_message("derp")
65
+ script = Bitcoin::Script.new([redeem_script].pack("H*"))
66
+ pubkey = Bitcoin::Key.new(nil, script.get_multisig_pubkeys.first.unpack("H*").first)
67
+ raise "nope" unless pubkey.verify_message(signature, "derp")
39
68
  ```
40
69
 
41
- ## Contributing
70
+ <pre>
71
+ <code>
72
+ $ bundle exec ruby test.rb
73
+ nonce: 3a11be476485a6273fad4a0e09117d42
74
+ P2SH address: 2MvGPFfDXbJZyH79u187VNZbuCgyRBhcdsw
75
+ new redeem script: 512102944aba05d40d8df1724f8ab2f5f3a58d052d26aedc93e175534cb782becc8ff751ae
76
+ new privkey: cSBD8yM62R82RfbugiGK8Lui9gdMB81NtZBckxe5YxRsDSKySwHK
77
+ </code>
78
+ </pre>
42
79
 
43
- 1. Fork it ( https://github.com/[my-github-username]/contracthashtool/fork )
44
- 2. Create your feature branch (`git checkout -b my-new-feature`)
45
- 3. Commit your changes (`git commit -am 'Add some feature'`)
46
- 4. Push to the branch (`git push origin my-new-feature`)
47
- 5. Create a new Pull Request
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["andy.alness@gmail.com"]
11
11
  spec.summary = %q{Ruby port of contracthashtool}
12
12
  spec.description = %q{Ruby port of Blockstream's contracthashtool for federated peg support}
13
- spec.homepage = ""
13
+ spec.homepage = "https://github.com/aalness/contracthashtool-ruby"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
@@ -21,6 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.7"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
 
24
- spec.add_dependency "bitcoin-ruby"
25
- spec.add_dependency "ffi"
24
+ spec.add_dependency "bitcoin-ruby", "~> 0.0", ">= 0.0.6"
25
+ spec.add_dependency "ffi", "~> 1.9"
26
26
  end
@@ -6,13 +6,13 @@ require "ffi"
6
6
  module Contracthashtool
7
7
 
8
8
  # generate a contract address
9
- def self.generate(redeem_script_hex, payee_address, nonce_hex=nil)
9
+ def self.generate(redeem_script_hex, payee_address_or_ascii, nonce_hex=nil)
10
10
  redeem_script = Bitcoin::Script.new([redeem_script_hex].pack("H*"))
11
11
  raise "only multisig redeem scripts are currently supported" unless redeem_script.is_multisig?
12
- nonce_hex, data = compute_data(payee_address, nonce_hex)
12
+ nonce_hex, data = compute_data(payee_address_or_ascii, nonce_hex)
13
13
 
14
14
  derived_keys = []
15
- group = OpenSSL::PKey::EC::Group.new('secp256k1')
15
+ group = OpenSSL::PKey::EC::Group.new("secp256k1")
16
16
  redeem_script.get_multisig_pubkeys.each do |pubkey|
17
17
  tweak = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("SHA256"), pubkey, data).to_i(16)
18
18
  raise "order exceeded, pick a new nonce" if tweak >= group.order
@@ -26,19 +26,19 @@ module Contracthashtool
26
26
  end
27
27
 
28
28
  m = redeem_script.get_signatures_required
29
- p2sh_script = Bitcoin::Script.to_p2sh_multisig_script(m, *derived_keys)[0]
29
+ p2sh_script, redeem_script = Bitcoin::Script.to_p2sh_multisig_script(m, *derived_keys)
30
30
 
31
- [ nonce_hex, Bitcoin::Script.new(p2sh_script).get_p2sh_address ]
31
+ [ nonce_hex, redeem_script.unpack("H*")[0], Bitcoin::Script.new(p2sh_script).get_p2sh_address ]
32
32
  end
33
33
 
34
34
  # claim a contract
35
- def self.claim(private_key_wif, payee_address, nonce_hex)
35
+ def self.claim(private_key_wif, payee_address_or_ascii, nonce_hex)
36
36
  key = Bitcoin::Key.from_base58(private_key_wif)
37
- data = compute_data(payee_address, nonce_hex)[1]
37
+ data = compute_data(payee_address_or_ascii, nonce_hex)[1]
38
38
 
39
39
  pubkey = [key.pub].pack("H*")
40
40
  tweak = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("SHA256"), pubkey, data).to_i(16)
41
- group = OpenSSL::PKey::EC::Group.new('secp256k1')
41
+ group = OpenSSL::PKey::EC::Group.new("secp256k1")
42
42
  raise "order exceeded, verify parameters" if tweak >= group.order
43
43
 
44
44
  derived_key = (tweak + key.priv.to_i(16)) % group.order
@@ -46,25 +46,30 @@ module Contracthashtool
46
46
  end
47
47
 
48
48
  # compute HMAC data
49
- def self.compute_data(address, nonce_hex)
49
+ def self.compute_data(address_or_ascii, nonce_hex)
50
50
  nonce = nonce_hex ? [nonce_hex].pack("H32") : SecureRandom.random_bytes(16)
51
- hash160 = [Bitcoin.hash160_from_address(address)].pack("H*")
52
- address_type = Bitcoin.address_type(address)
53
- case address_type
54
- when :hash160
55
- address_type = "P2PH"
56
- when :p2sh
57
- address_type = "P2SH"
51
+ if Bitcoin.valid_address?(address_or_ascii)
52
+ address_type = Bitcoin.address_type(address_or_ascii)
53
+ case address_type
54
+ when :hash160
55
+ address_type = "P2PH"
56
+ when :p2sh
57
+ address_type = "P2SH"
58
+ else
59
+ raise "unsupported address type #{address_type}"
60
+ end
61
+ contract_bytes = [Bitcoin.hash160_from_address(address_or_ascii)].pack("H*")
58
62
  else
59
- raise "unsuppoorted address type #{address_type}"
63
+ address_type = "TEXT"
64
+ contract_bytes = address_or_ascii
60
65
  end
61
- [ nonce.unpack("H*")[0], address_type + nonce + hash160 ]
66
+ [ nonce.unpack("H*")[0], address_type + nonce + contract_bytes ]
62
67
  end
63
68
 
64
69
  # lifted from https://github.com/GemHQ/money-tree
65
70
  module EC_ADD
66
71
  extend ::FFI::Library
67
- ffi_lib 'ssl'
72
+ ffi_lib "ssl"
68
73
 
69
74
  NID_secp256k1 = 714
70
75
  POINT_CONVERSION_COMPRESSED = 2
@@ -1,3 +1,3 @@
1
1
  module Contracthashtool
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contracthashtool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Alness
@@ -42,30 +42,36 @@ dependencies:
42
42
  name: bitcoin-ruby
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.0'
45
48
  - - ">="
46
49
  - !ruby/object:Gem::Version
47
- version: '0'
50
+ version: 0.0.6
48
51
  type: :runtime
49
52
  prerelease: false
50
53
  version_requirements: !ruby/object:Gem::Requirement
51
54
  requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '0.0'
52
58
  - - ">="
53
59
  - !ruby/object:Gem::Version
54
- version: '0'
60
+ version: 0.0.6
55
61
  - !ruby/object:Gem::Dependency
56
62
  name: ffi
57
63
  requirement: !ruby/object:Gem::Requirement
58
64
  requirements:
59
- - - ">="
65
+ - - "~>"
60
66
  - !ruby/object:Gem::Version
61
- version: '0'
67
+ version: '1.9'
62
68
  type: :runtime
63
69
  prerelease: false
64
70
  version_requirements: !ruby/object:Gem::Requirement
65
71
  requirements:
66
- - - ">="
72
+ - - "~>"
67
73
  - !ruby/object:Gem::Version
68
- version: '0'
74
+ version: '1.9'
69
75
  description: Ruby port of Blockstream's contracthashtool for federated peg support
70
76
  email:
71
77
  - andy.alness@gmail.com
@@ -81,7 +87,7 @@ files:
81
87
  - contracthashtool.gemspec
82
88
  - lib/contracthashtool.rb
83
89
  - lib/contracthashtool/version.rb
84
- homepage: ''
90
+ homepage: https://github.com/aalness/contracthashtool-ruby
85
91
  licenses:
86
92
  - MIT
87
93
  metadata: {}