coin-op 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,124 @@
1
+ require "bitcoin"
2
+
3
+ Bitcoin::NETWORKS[:mockchain] = {
4
+ :project => :bitcoin,
5
+ :magic_head => "mock",
6
+ :address_version => "6f",
7
+ :p2sh_version => "c4",
8
+ :privkey_version => "ef",
9
+ :default_port => 48333,
10
+ :protocol_version => 70001,
11
+ :max_money => 21_000_000 * 100_000_000,
12
+ :dns_seeds => [],
13
+ :genesis_hash => "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
14
+ :proof_of_work_limit => 553713663,
15
+ :alert_pubkeys => [],
16
+ :known_nodes => [],
17
+ :checkpoints => {},
18
+ :min_tx_fee => 10_000,
19
+ :min_relay_tx_fee => 10_000,
20
+ }
21
+
22
+ Bitcoin.network = :mockchain
23
+
24
+
25
+ module CoinOp::Bit
26
+
27
+ class MockChain
28
+ include ::Bitcoin::Builder
29
+
30
+ attr_reader :key, :store, :last, :coinbase_value
31
+
32
+ def initialize(config={})
33
+ @key = Bitcoin::Key.new
34
+ @key.generate
35
+ @config = config
36
+ @coinbase_value = 50e8
37
+
38
+ if @config[:db]
39
+ @store = Bitcoin::Storage.sequel(
40
+ :db => @config[:db], :log_level => :warn
41
+ )
42
+ @store.connect
43
+ if head = @store.get_head
44
+ @last = head
45
+ else
46
+ self.reset
47
+ end
48
+ else
49
+ self.reset
50
+ end
51
+ end
52
+
53
+ def reset
54
+ @store.reset if @store
55
+ @block0 = self.add :key => @key, :previous => "00"*32
56
+
57
+ Bitcoin.network[:genesis_hash] = @block0.hash
58
+ @store.store_block(@block0) if @store
59
+ @last = @block0
60
+ end
61
+
62
+ def mine(key=nil)
63
+ key ||= @key
64
+ block = self.add :key => key, :previous => @last.hash
65
+ end
66
+
67
+ def add(options={})
68
+ if !options[:key]
69
+ raise "Must provide :key"
70
+ end
71
+ options[:bits] ||= Bitcoin.network[:proof_of_work_limit]
72
+ previous_block = options[:previous] || @last
73
+
74
+ block = build_block(Bitcoin.decode_compact_bits(options[:bits])) do |b|
75
+ b.time options[:time] if options[:time]
76
+ b.prev_block previous_block
77
+ b.tx do |t|
78
+ t.input {|i| i.coinbase }
79
+ t.output do |o|
80
+ o.value @coinbase_value
81
+ o.script {|s| s.recipient options[:key].addr }
82
+ end
83
+ end
84
+ end
85
+ if options[:transactions]
86
+ options[:transactions].each do |transaction|
87
+ block.tx << transaction
88
+ end
89
+ end
90
+
91
+ @store.store_block(block) if @store
92
+ @last = block
93
+ block
94
+ end
95
+
96
+ def transaction(recipients)
97
+ last_transaction = @last.tx.first
98
+
99
+ transaction = Builder.build_tx do |t|
100
+ t.input do |i|
101
+ i.prev_out last_transaction
102
+ i.prev_out_index 0
103
+ i.signature_key @key
104
+ end
105
+
106
+ recipients.each do |address, value|
107
+ t.output do |o|
108
+ o.value value
109
+ o.script do |s|
110
+ s.type :address
111
+ s.recipient address
112
+ end
113
+ end
114
+ end
115
+
116
+ end
117
+
118
+ end
119
+
120
+
121
+ end
122
+
123
+ end
124
+
@@ -0,0 +1,70 @@
1
+ require "rbnacl"
2
+ require "openssl"
3
+
4
+ module CoinOp
5
+ module Crypto
6
+
7
+ class PassphraseBox
8
+ include CoinOp::Encodings
9
+ extend CoinOp::Encodings
10
+
11
+ # PBKDF2 work factor
12
+ ITERATIONS = 100_000
13
+
14
+ # Given passphrase and plaintext as strings, returns a Hash
15
+ # containing the ciphertext and other values needed for later
16
+ # decryption.
17
+ def self.encrypt(passphrase, plaintext)
18
+ box = self.new(passphrase)
19
+ box.encrypt(plaintext)
20
+ end
21
+
22
+ # PassphraseBox.decrypt "my great password",
23
+ # :salt => salt, :nonce => nonce, :ciphertext => ciphertext
24
+ #
25
+ def self.decrypt(passphrase, hash)
26
+ salt, nonce, ciphertext =
27
+ hash.values_at(:salt, :nonce, :ciphertext).map {|s| decode_base58(s) }
28
+ box = self.new(passphrase, salt, hash[:iterations])
29
+ box.decrypt(nonce, ciphertext)
30
+ end
31
+
32
+ attr_reader :salt
33
+
34
+ # Initialize with an existing salt and iterations to allow
35
+ # decryption. Otherwise, creates new values for these, meaning
36
+ # it creates an entirely new secret-box.
37
+ def initialize(passphrase, salt=nil, iterations=nil)
38
+ @salt = salt || RbNaCl::Random.random_bytes(16)
39
+ @iterations = iterations || ITERATIONS
40
+
41
+ key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(
42
+ passphrase, @salt,
43
+ # TODO: decide on a very safe work factor
44
+ # https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
45
+ #
46
+ @iterations, # number of iterations
47
+ 32 # key length in bytes
48
+ )
49
+ @box = RbNaCl::SecretBox.new(key)
50
+ end
51
+
52
+ def encrypt(plaintext)
53
+ nonce = RbNaCl::Random.random_bytes(RbNaCl::SecretBox.nonce_bytes)
54
+ ciphertext = @box.encrypt(nonce, plaintext)
55
+ {
56
+ :salt => base58(@salt),
57
+ :iterations => @iterations,
58
+ :nonce => base58(nonce),
59
+ :ciphertext => base58(ciphertext)
60
+ }
61
+ end
62
+
63
+ def decrypt(nonce, ciphertext)
64
+ @box.decrypt(nonce, ciphertext)
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,26 @@
1
+
2
+ module CoinOp
3
+
4
+ module Encodings
5
+ extend self
6
+
7
+ def hex(blob)
8
+ blob.unpack("H*")[0]
9
+ end
10
+
11
+ def decode_hex(string)
12
+ [string].pack("H*")
13
+ end
14
+
15
+ def base58(blob)
16
+ ::Bitcoin.encode_base58(self.hex(blob))
17
+ end
18
+
19
+ def decode_base58(string)
20
+ self.decode_hex(::Bitcoin.decode_base58(string))
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: coin-op
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Matthew King
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bitcoin-ruby
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: money-tree
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.8'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: starter
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.12
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.12
55
+ - !ruby/object:Gem::Dependency
56
+ name: sequel
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4.8'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4.8'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest-reporters
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ description:
98
+ email:
99
+ - matthew@bitvault.io
100
+ - dustin@bitvault.io
101
+ - julian@bitvault.io
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - LICENSE
107
+ - README.md
108
+ - lib/coin-op.rb
109
+ - lib/coin-op/bit.rb
110
+ - lib/coin-op/bit/input.rb
111
+ - lib/coin-op/bit/multi_wallet.rb
112
+ - lib/coin-op/bit/output.rb
113
+ - lib/coin-op/bit/script.rb
114
+ - lib/coin-op/bit/spendable.rb
115
+ - lib/coin-op/bit/transaction.rb
116
+ - lib/coin-op/blockchain/blockr.rb
117
+ - lib/coin-op/blockchain/mockchain.rb
118
+ - lib/coin-op/crypto.rb
119
+ - lib/coin-op/encodings.rb
120
+ homepage: https://github.com/BitVault/coin-op
121
+ licenses:
122
+ - MIT
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.2.0
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: Crypto currency classes in Ruby
144
+ test_files: []