bitcoin 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. metadata +17 -288
  2. data/.rspec +0 -1
  3. data/.rvmrc +0 -1
  4. data/Gemfile +0 -4
  5. data/Gemfile.lock +0 -98
  6. data/Guardfile +0 -38
  7. data/README.markdown +0 -24
  8. data/Rakefile +0 -1
  9. data/bin/rbcoin +0 -8
  10. data/bitcoin.gemspec +0 -40
  11. data/config/cucumber.yml +0 -5
  12. data/config/darcs.boring +0 -121
  13. data/doc/DEFINITION_OF_DONE.markdown +0 -12
  14. data/doc/HISTORY.markdown +0 -19
  15. data/doc/LICENCE.markdown +0 -25
  16. data/doc/TODO.markdown +0 -31
  17. data/doc/UBIQUITOUS_LANGUAGE.markdown +0 -15
  18. data/features/descriptions/command_help.feature +0 -31
  19. data/features/descriptions/satoshi_wallet/add_address.feature +0 -49
  20. data/features/descriptions/satoshi_wallet/show_addresses.feature +0 -18
  21. data/features/descriptions/satoshi_wallet/show_version.feature +0 -17
  22. data/features/descriptions/satoshi_wallet/subcommand_help.feature +0 -20
  23. data/features/fixtures/ABOUT_FIXTURES.markdown +0 -6
  24. data/features/fixtures/addressbook_wallet.dat +0 -0
  25. data/features/fixtures/new_wallet.dat +0 -0
  26. data/features/step_definitions/command_steps.rb +0 -3
  27. data/features/step_definitions/wallet_steps.rb +0 -11
  28. data/features/support/env.rb +0 -9
  29. data/lib/bitcoin.rb +0 -5
  30. data/lib/bitcoin/cli.rb +0 -35
  31. data/lib/bitcoin/commands.rb +0 -3
  32. data/lib/bitcoin/commands/help_command.rb +0 -32
  33. data/lib/bitcoin/commands/satoshi_wallet.rb +0 -11
  34. data/lib/bitcoin/commands/satoshi_wallet/add_address_command.rb +0 -61
  35. data/lib/bitcoin/commands/satoshi_wallet/show_addresses_command.rb +0 -16
  36. data/lib/bitcoin/commands/satoshi_wallet/show_version_command.rb +0 -15
  37. data/lib/bitcoin/commands/satoshi_wallet_command.rb +0 -37
  38. data/lib/bitcoin/commands/satoshi_wallet_command_environment.rb +0 -28
  39. data/lib/bitcoin/console/capturing_stream_bundle.rb +0 -42
  40. data/lib/bitcoin/console/stream_bundle.rb +0 -21
  41. data/lib/bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository.rb +0 -155
  42. data/lib/bitcoin/data_access/satoshi/satoshi_version.rb +0 -58
  43. data/lib/bitcoin/data_access/satoshi/satoshi_wallet.rb +0 -39
  44. data/lib/bitcoin/domain/address_book.rb +0 -19
  45. data/lib/bitcoin/domain/bitcoin_address.rb +0 -33
  46. data/lib/bitcoin/filesystem/empty_temp_dir.rb +0 -74
  47. data/lib/bitcoin/rspec/argument_matchers.rb +0 -1
  48. data/lib/bitcoin/rspec/argument_matchers/block_evaluating_to_matcher.rb +0 -23
  49. data/lib/bitcoin/rspec/directory_helpers.rb +0 -22
  50. data/lib/bitcoin/version.rb +0 -3
  51. data/spec/bitcoin/cli_spec.rb +0 -128
  52. data/spec/bitcoin/commands/help_command_spec.rb +0 -53
  53. data/spec/bitcoin/commands/satoshi_wallet/add_address_command_spec.rb +0 -149
  54. data/spec/bitcoin/commands/satoshi_wallet/show_addresses_command_spec.rb +0 -26
  55. data/spec/bitcoin/commands/satoshi_wallet/show_version_command_spec.rb +0 -26
  56. data/spec/bitcoin/commands/satoshi_wallet_command_environment_spec.rb +0 -76
  57. data/spec/bitcoin/commands/satoshi_wallet_command_spec.rb +0 -73
  58. data/spec/bitcoin/console/_contracts/stream_bundle_contract.rb +0 -29
  59. data/spec/bitcoin/console/capturing_stream_bundle_spec.rb +0 -74
  60. data/spec/bitcoin/console/stream_bundle_spec.rb +0 -13
  61. data/spec/bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository_spec.rb +0 -78
  62. data/spec/bitcoin/data_access/satoshi/satoshi_version_spec.rb +0 -112
  63. data/spec/bitcoin/data_access/satoshi/satoshi_wallet_spec.rb +0 -102
  64. data/spec/bitcoin/domain/address_book_spec.rb +0 -63
  65. data/spec/bitcoin/domain/bitcoin_address_spec.rb +0 -52
  66. data/spec/bitcoin/filesystem/empty_temp_dir_spec.rb +0 -170
  67. data/spec/bitcoin/rspec/argument_matchers/block_evaluating_to_matcher_spec.rb +0 -36
  68. data/spec/spec_helper.rb +0 -29
@@ -1,6 +0,0 @@
1
- # About the fixtures
2
-
3
- Fixtures are bad, mmmkay?
4
-
5
- But until we have a bulletproof means of writing a full and correct Satoshi Wallet
6
- file, it's safer to use fixtures than to rely on our unproven Berkeley DB code.
@@ -1,3 +0,0 @@
1
- Then %r/the command should fail/ do
2
- Then "the exit status should be 1"
3
- end
@@ -1,11 +0,0 @@
1
- module Fixtures
2
- def fixture_file_data(filename)
3
- File.read(File.join(PROJECT_ROOT, "features", "fixtures", filename))
4
- end
5
- end
6
-
7
- World(Fixtures)
8
-
9
- Given %r/^a new Satoshi Wallet "([^"]*)"$/ do |wallet_filename|
10
- write_file(wallet_filename, fixture_file_data(wallet_filename))
11
- end
@@ -1,9 +0,0 @@
1
- require 'bundler'
2
- Bundler.setup
3
-
4
- PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), "..", "..")).freeze
5
-
6
- # So Aruba can find the binary
7
- ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
8
-
9
- require 'aruba/cucumber'
@@ -1,5 +0,0 @@
1
- require "bitcoin/version"
2
-
3
- module Bitcoin
4
- # Your code goes here...
5
- end
@@ -1,35 +0,0 @@
1
- require 'bitcoin/commands'
2
-
3
- module Bitcoin
4
- class CLI
5
- class CommandError < RuntimeError; end
6
-
7
- def initialize(stream_bundle)
8
- @stream_bundle = stream_bundle
9
- end
10
-
11
- def run(args)
12
- command_name, *remaining_args = *args
13
- dispatch_command(command_name, remaining_args)
14
- rescue CommandError => error
15
- 1
16
- else
17
- 0
18
- end
19
-
20
- private
21
-
22
- def dispatch_command(command_name, remaining_args)
23
- case command_name
24
- when nil, "help"
25
- Commands::HelpCommand.new(@stream_bundle).show_help
26
- when "satoshi-wallet"
27
- command_environment = Commands::SatoshiWalletCommandEnvironment.new(@stream_bundle)
28
- Commands::SatoshiWalletCommand.new(@stream_bundle, command_environment).run(remaining_args)
29
- else
30
- Commands::HelpCommand.new(@stream_bundle).show_unknown_command_help(command_name)
31
- raise CommandError.new
32
- end
33
- end
34
- end
35
- end
@@ -1,3 +0,0 @@
1
- require_relative 'commands/help_command'
2
- require_relative 'commands/satoshi_wallet_command'
3
- require_relative 'commands/satoshi_wallet_command_environment'
@@ -1,32 +0,0 @@
1
- require 'lstrip-on-steroids'
2
-
3
- module Bitcoin
4
- module Commands
5
- class HelpCommand
6
- def initialize(stream_bundle)
7
- @stream_bundle = stream_bundle
8
- end
9
-
10
- def show_help
11
- @stream_bundle.puts_output(
12
- -%{
13
- Usage: rbcoin COMMAND ...
14
-
15
- Commands:
16
- help Display help about rbcoin and rbcoin commands
17
- satoshi-wallet Manipulate the wallet.dat file of the original client
18
-
19
- Use "rbcoin COMMAND --help" or "rbcoin help COMMAND" for help on a single command
20
- Use "rbcoin --version" to see the rbcoin version number
21
- Use "rbcoin --exact-version" to see the all version details (with dependencies)
22
- }
23
- )
24
- end
25
-
26
- def show_unknown_command_help(command_name)
27
- @stream_bundle.puts_output(%'rbcoin failed: No such command "#{command_name}"')
28
- @stream_bundle.puts_output("Try: `rbcoin help`")
29
- end
30
- end
31
- end
32
- end
@@ -1,11 +0,0 @@
1
- module Bitcoin
2
- module Commands
3
- module SatoshiWallet
4
-
5
- end
6
- end
7
- end
8
-
9
- require_relative 'satoshi_wallet/add_address_command'
10
- require_relative 'satoshi_wallet/show_addresses_command'
11
- require_relative 'satoshi_wallet/show_version_command'
@@ -1,61 +0,0 @@
1
- require 'bitcoin/cli' # For CommandError
2
-
3
- require 'bitcoin/domain/bitcoin_address'
4
-
5
- module Bitcoin
6
- module Commands
7
- module SatoshiWallet
8
- class AddAddressCommand
9
- def initialize(stream_bundle)
10
- @stream_bundle = stream_bundle
11
- end
12
-
13
- def run(wallet, options)
14
- assert_valid_args(options[:args])
15
-
16
- address, name = *options[:args]
17
-
18
- assert_valid_name(name)
19
-
20
- wallet.add_address(Domain::BitcoinAddress.new(address), name: name)
21
- @stream_bundle.puts_output("Address added successfully")
22
- rescue Domain::BitcoinAddress::InvalidBitcoinAddressError => error
23
- @stream_bundle.puts_error(error.message)
24
- @stream_bundle.puts_error("The address was not added to the wallet")
25
- raise CLI::CommandError.new
26
- end
27
-
28
- private
29
-
30
- def assert_valid_args(args)
31
- if args.length < 2
32
- @stream_bundle.puts_error("You must provide both a Bitcoin address and a name to add to a wallet")
33
- @stream_bundle.puts_error("No changes were made to the wallet")
34
- raise CLI::CommandError.new
35
- elsif args.length > 2
36
- @stream_bundle.puts_error(
37
- -%{
38
- Received too many arguments
39
-
40
- To make sure the name is formatted correctly we ask you to use use quotes
41
- around the name, e.g.: "#{args.drop(1).join(" ")}"
42
-
43
- No changes were made to the wallet
44
- }
45
- )
46
- raise CLI::CommandError.new
47
- end
48
-
49
- def assert_valid_name(name)
50
- if name.bytesize > 252
51
- @stream_bundle.puts_error(%'The address name "#{name}" is too long\n')
52
- @stream_bundle.puts_error("Currently we do not allow address names over 252 bytes long\n")
53
- @stream_bundle.puts_error("The address was not added to the wallet\n")
54
- raise CLI::CommandError.new
55
- end
56
- end
57
- end
58
- end
59
- end
60
- end
61
- end
@@ -1,16 +0,0 @@
1
- module Bitcoin
2
- module Commands
3
- module SatoshiWallet
4
- class ShowAddressesCommand
5
- def initialize(stream_bundle)
6
- @stream_bundle = stream_bundle
7
- end
8
-
9
- def run(wallet, options)
10
- @stream_bundle.puts_output("# All addresses in #{options[:wallet_filename]}")
11
- @stream_bundle.puts_output(wallet.addresses)
12
- end
13
- end
14
- end
15
- end
16
- end
@@ -1,15 +0,0 @@
1
- module Bitcoin
2
- module Commands
3
- module SatoshiWallet
4
- class ShowVersionCommand
5
- def initialize(stream_bundle)
6
- @stream_bundle = stream_bundle
7
- end
8
-
9
- def run(wallet, options = { })
10
- @stream_bundle.puts_output(wallet.version)
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,37 +0,0 @@
1
- require 'tmpdir'
2
-
3
- require 'bitcoin/cli' # circular dependency on CLI for CommandError
4
- require 'bitcoin/commands/satoshi_wallet'
5
- require 'bitcoin/data_access/satoshi/satoshi_wallet'
6
- require 'bitcoin/domain/bitcoin_address'
7
- require 'bitcoin/filesystem/empty_temp_dir'
8
-
9
- module Bitcoin
10
- module Commands
11
- class SatoshiWalletCommand
12
- TEMP_DB_PATH = "bitcoinrb_db_tmp"
13
-
14
- def initialize(stream_bundle, command_environment)
15
- @stream_bundle = stream_bundle
16
- @command_environment = command_environment
17
- end
18
-
19
- def run(args)
20
- command_name, *remaining_args = *args
21
- command_class =
22
- case command_name
23
- when "add-address"
24
- SatoshiWallet::AddAddressCommand
25
- when "show-addresses"
26
- SatoshiWallet::ShowAddressesCommand
27
- when "show-version"
28
- SatoshiWallet::ShowVersionCommand
29
- else
30
- @stream_bundle.puts_error(%'Unknown satoshi-wallet subcommand: "#{command_name}"')
31
- raise CLI::CommandError.new
32
- end
33
- @command_environment.run_command(command_class.new(@stream_bundle), remaining_args)
34
- end
35
- end
36
- end
37
- end
@@ -1,28 +0,0 @@
1
- require 'bitcoin/filesystem/empty_temp_dir'
2
-
3
- module Bitcoin
4
- module Commands
5
- class SatoshiWalletCommandEnvironment
6
- def initialize(stream_bundle)
7
- @stream_bundle = stream_bundle
8
- end
9
-
10
- def run_command(command, arguments)
11
- wallet_filename, *remaining_args = *arguments
12
-
13
- if !File.exist?(wallet_filename)
14
- @stream_bundle.puts_error("Couldn't find wallet file: #{wallet_filename}")
15
- raise CLI::CommandError.new
16
- end
17
-
18
- absolute_wallet_path = File.expand_path(wallet_filename)
19
-
20
- FileSystem::EmptyTempDir.open(with_name: "bitcoinrb_db_tmp", parallel_to: absolute_wallet_path) do |temp_dir|
21
- DataAccess::Satoshi::SatoshiWallet.open(wallet_filename: absolute_wallet_path, db_dirname: temp_dir.absolute_path) do |wallet|
22
- command.run(wallet, wallet_filename: wallet_filename, args: remaining_args)
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,42 +0,0 @@
1
- require_relative 'stream_bundle'
2
-
3
- module Bitcoin
4
- module Console
5
- # CapturingStreamBundles are StreamBundles that record the data written to them
6
- # for easy inspection later. They are useful for testing purposes.
7
- class CapturingStreamBundle
8
- class << self
9
- def test_bundle
10
- new(StringIO.new, StringIO.new, StringIO.new)
11
- end
12
- end
13
-
14
- def initialize(input, output, error)
15
- @stream_bundle = StreamBundle.new(input, output, error)
16
-
17
- @captured_output = StringIO.new
18
- @captured_error = StringIO.new
19
- end
20
-
21
- def puts_output(stringlike)
22
- @stream_bundle.puts_output(stringlike)
23
- @captured_output.puts(stringlike)
24
- end
25
-
26
- def puts_error(stringlike)
27
- @stream_bundle.puts_error(stringlike)
28
- @captured_error.puts(stringlike)
29
- end
30
-
31
- def captured_output
32
- @captured_output.rewind
33
- @captured_output.read
34
- end
35
-
36
- def captured_error
37
- @captured_error.rewind
38
- @captured_error.read
39
- end
40
- end
41
- end
42
- end
@@ -1,21 +0,0 @@
1
- module Bitcoin
2
- module Console
3
- # StreamBundles are objects that encapsulate the standard unix pipes
4
- # (STDIN, STDOUT, STDERR)
5
- class StreamBundle
6
- def initialize(input, output, error)
7
- @input = input
8
- @output = output
9
- @error = error
10
- end
11
-
12
- def puts_output(stringlike)
13
- @output.puts(stringlike)
14
- end
15
-
16
- def puts_error(stringlike)
17
- @error.puts(stringlike)
18
- end
19
- end
20
- end
21
- end
@@ -1,155 +0,0 @@
1
- require 'sbdb'
2
- require 'bdb/base'
3
-
4
- module Bitcoin
5
- module DataAccess
6
- module Satoshi
7
- # Raw Berkeley DB access (thin wrapper around SBDB) for wallet data
8
- # WARNING! This code is in really bad shape. It works, but is verbose
9
- # and full of duplication. It needs massive refactoring.
10
- class BDBSatoshiWalletRepository
11
- def initialize(db_filename, options)
12
- @db_filename = db_filename
13
- @db_dirname = options[:db_dirname]
14
- end
15
-
16
- def bdb_bytes_to_utf8_string(bytes)
17
- bytes.pack("C*").force_encoding("UTF-8")
18
- end
19
-
20
- def get_value_immediate_uint32le(key_name)
21
- with_bdb_db do |db|
22
- db[make_key(key_name)].unpack("V").first
23
- end
24
- end
25
-
26
- def set_value_immediate_uint32le(key_name, value_data)
27
- with_bdb_db do |db|
28
- db[make_key(key_name)] = [ value_data ].pack("V")
29
- end
30
- end
31
-
32
- def get_key_and_value_data_string_utf8(key_name)
33
- with_bdb_db do |db|
34
- db_records(db).select { |record|
35
- record.first == key_name
36
- }.map { |name, data_hash|
37
- data_hash
38
- }.map { |data_hash|
39
- [ data_hash[:key_data], data_hash[:value_data] ].map { |value|
40
- bdb_bytes_to_utf8_string(value)
41
- }
42
- }
43
- end
44
- end
45
-
46
- def get_value_with_key_data_string_utf8(key_name, key_data)
47
- with_bdb_db do |db|
48
- value_data = db[make_key_with_data(key_name, key_data)]
49
- return unless value_data
50
- value_bytes = value_data.unpack("C*")
51
- value_bytes.shift(read_compact_size(value_bytes)).pack("C*")
52
- end
53
- end
54
-
55
- def set_value_with_key_data_string_utf8(key_name, key_data, value_data)
56
- with_bdb_db do |db|
57
- db[make_key_with_data(key_name, key_data)] = make_key(value_data)
58
- end
59
- end
60
-
61
- def make_key(key_name)
62
- key = [ ]
63
- key << write_compact_size(key_name)
64
- key.concat(key_name.unpack("C*"))
65
- key.pack("C*")
66
- end
67
-
68
- def make_key_with_data(key_name, key_data)
69
- make_key(key_name) + make_key(key_data)
70
- end
71
-
72
- # Maybe allow changing read/write & read-only when calling this?
73
- def with_bdb_env(&block)
74
- # This doesn't yet exactly mirror the DB setup in CWalletDB::LoadWallet
75
- SBDB::Env.new(
76
- dir: File.expand_path(@db_dirname),
77
- lg_max: 10_000_000,
78
- flags: Bdb::DB_CREATE | # Create the environment if it does not already exist.
79
- Bdb::DB_INIT_LOCK | # Initialize locking.
80
- Bdb::DB_INIT_LOG | # Initialize logging
81
- Bdb::DB_INIT_MPOOL | # Initialize the in-memory cache.
82
- Bdb::DB_INIT_TXN | # Initialize transactions
83
- Bdb::DB_THREAD | # TODO: What?
84
- Bdb::DB_RECOVER # TODO: What?
85
- ) do |env|
86
- yield env
87
- end
88
- end
89
-
90
- def with_bdb_db(&block)
91
- with_bdb_env do |env|
92
- bitcoin_logical_database_name = "main"
93
- # Leaving this here for reference: we could offer a read-only mode if we wanted (see Env flags though)
94
- read_write_flags = Bdb::DB_CREATE | Bdb::DB_AUTO_COMMIT
95
- read_only_flags = Bdb::DB_RDONLY
96
- env.open(SBDB::Btree, File.expand_path(@db_filename), name: bitcoin_logical_database_name, flags: read_write_flags) do |db|
97
- yield db
98
- end
99
- end
100
- end
101
-
102
- def db_records(db)
103
- db.to_hash.map { |key, value|
104
- # Key name
105
- key_bytes = key.bytes.to_a
106
- key_name_length = read_compact_size(key_bytes)
107
- key_name = key_bytes.shift(key_name_length).pack("C*").force_encoding("UTF-8")
108
-
109
- # Key data
110
- key_data_length = read_compact_size(key_bytes)
111
- key_data_raw = key_bytes.shift(key_data_length)
112
-
113
- # Value data
114
- value_bytes = value.bytes.to_a
115
- value_data_raw =
116
- case key_name
117
- when "version" # values that don't start with a length
118
- value_bytes
119
- else # variable-length values
120
- value_length = read_compact_size(value_bytes)
121
- value_bytes.shift(value_length)
122
- end
123
-
124
- [ key_name, { key_data: key_data_raw, value_data: value_data_raw } ]
125
- }
126
- end
127
-
128
- def write_compact_size(string)
129
- string.bytesize
130
- end
131
-
132
- def read_compact_size(byte_array)
133
- # The Satoshi client throws an error here if the determined length is greater
134
- # than (uint64)MAX_SIZE - I don't know if we need to worry about it
135
-
136
- byte_1 = byte_array.shift
137
- if byte_1.nil?
138
- 0
139
- elsif byte_1 < 253
140
- byte_1
141
- elsif byte_1 == 253
142
- # Little-endian 16-bit
143
- byte_array.shift(2).pack("C*").unpack("v").first
144
- elsif byte_1 == 254
145
- # Little-endian 32-bit int
146
- byte_array.shift(4).pack("C*").unpack("V").first
147
- else
148
- # 64-bit int (is this little-endian or native?)
149
- byte_array.shift(8).pack("C*").unpack("Q").first
150
- end
151
- end
152
- end
153
- end
154
- end
155
- end