bitcoin 0.1.2 → 0.2.0
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.
- metadata +17 -288
- data/.rspec +0 -1
- data/.rvmrc +0 -1
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -98
- data/Guardfile +0 -38
- data/README.markdown +0 -24
- data/Rakefile +0 -1
- data/bin/rbcoin +0 -8
- data/bitcoin.gemspec +0 -40
- data/config/cucumber.yml +0 -5
- data/config/darcs.boring +0 -121
- data/doc/DEFINITION_OF_DONE.markdown +0 -12
- data/doc/HISTORY.markdown +0 -19
- data/doc/LICENCE.markdown +0 -25
- data/doc/TODO.markdown +0 -31
- data/doc/UBIQUITOUS_LANGUAGE.markdown +0 -15
- data/features/descriptions/command_help.feature +0 -31
- data/features/descriptions/satoshi_wallet/add_address.feature +0 -49
- data/features/descriptions/satoshi_wallet/show_addresses.feature +0 -18
- data/features/descriptions/satoshi_wallet/show_version.feature +0 -17
- data/features/descriptions/satoshi_wallet/subcommand_help.feature +0 -20
- data/features/fixtures/ABOUT_FIXTURES.markdown +0 -6
- data/features/fixtures/addressbook_wallet.dat +0 -0
- data/features/fixtures/new_wallet.dat +0 -0
- data/features/step_definitions/command_steps.rb +0 -3
- data/features/step_definitions/wallet_steps.rb +0 -11
- data/features/support/env.rb +0 -9
- data/lib/bitcoin.rb +0 -5
- data/lib/bitcoin/cli.rb +0 -35
- data/lib/bitcoin/commands.rb +0 -3
- data/lib/bitcoin/commands/help_command.rb +0 -32
- data/lib/bitcoin/commands/satoshi_wallet.rb +0 -11
- data/lib/bitcoin/commands/satoshi_wallet/add_address_command.rb +0 -61
- data/lib/bitcoin/commands/satoshi_wallet/show_addresses_command.rb +0 -16
- data/lib/bitcoin/commands/satoshi_wallet/show_version_command.rb +0 -15
- data/lib/bitcoin/commands/satoshi_wallet_command.rb +0 -37
- data/lib/bitcoin/commands/satoshi_wallet_command_environment.rb +0 -28
- data/lib/bitcoin/console/capturing_stream_bundle.rb +0 -42
- data/lib/bitcoin/console/stream_bundle.rb +0 -21
- data/lib/bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository.rb +0 -155
- data/lib/bitcoin/data_access/satoshi/satoshi_version.rb +0 -58
- data/lib/bitcoin/data_access/satoshi/satoshi_wallet.rb +0 -39
- data/lib/bitcoin/domain/address_book.rb +0 -19
- data/lib/bitcoin/domain/bitcoin_address.rb +0 -33
- data/lib/bitcoin/filesystem/empty_temp_dir.rb +0 -74
- data/lib/bitcoin/rspec/argument_matchers.rb +0 -1
- data/lib/bitcoin/rspec/argument_matchers/block_evaluating_to_matcher.rb +0 -23
- data/lib/bitcoin/rspec/directory_helpers.rb +0 -22
- data/lib/bitcoin/version.rb +0 -3
- data/spec/bitcoin/cli_spec.rb +0 -128
- data/spec/bitcoin/commands/help_command_spec.rb +0 -53
- data/spec/bitcoin/commands/satoshi_wallet/add_address_command_spec.rb +0 -149
- data/spec/bitcoin/commands/satoshi_wallet/show_addresses_command_spec.rb +0 -26
- data/spec/bitcoin/commands/satoshi_wallet/show_version_command_spec.rb +0 -26
- data/spec/bitcoin/commands/satoshi_wallet_command_environment_spec.rb +0 -76
- data/spec/bitcoin/commands/satoshi_wallet_command_spec.rb +0 -73
- data/spec/bitcoin/console/_contracts/stream_bundle_contract.rb +0 -29
- data/spec/bitcoin/console/capturing_stream_bundle_spec.rb +0 -74
- data/spec/bitcoin/console/stream_bundle_spec.rb +0 -13
- data/spec/bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository_spec.rb +0 -78
- data/spec/bitcoin/data_access/satoshi/satoshi_version_spec.rb +0 -112
- data/spec/bitcoin/data_access/satoshi/satoshi_wallet_spec.rb +0 -102
- data/spec/bitcoin/domain/address_book_spec.rb +0 -63
- data/spec/bitcoin/domain/bitcoin_address_spec.rb +0 -52
- data/spec/bitcoin/filesystem/empty_temp_dir_spec.rb +0 -170
- data/spec/bitcoin/rspec/argument_matchers/block_evaluating_to_matcher_spec.rb +0 -36
- data/spec/spec_helper.rb +0 -29
@@ -1,58 +0,0 @@
|
|
1
|
-
module Bitcoin
|
2
|
-
module DataAccess
|
3
|
-
module Satoshi
|
4
|
-
class SatoshiVersion
|
5
|
-
include Comparable
|
6
|
-
|
7
|
-
class << self
|
8
|
-
# Takes an array of unsigned bytes as extracted from a BDB wallet
|
9
|
-
def from_wallet_bytes(bytes)
|
10
|
-
from_wallet_int(bytes.pack("C*").unpack("V").first)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Takes an 4-byte unsigned little-endian integer as extracted from a BDB wallet
|
14
|
-
def from_wallet_int(int_version)
|
15
|
-
new(*[int_version / 1_000_000, (int_version / 10_000) % 100, (int_version / 100) % 100, int_version % 100])
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def initialize(*version_components)
|
20
|
-
@version_components = pad_4(version_components)
|
21
|
-
end
|
22
|
-
|
23
|
-
def <=>(other)
|
24
|
-
other.compare_version_components(@version_components)
|
25
|
-
end
|
26
|
-
|
27
|
-
def to_s
|
28
|
-
components = @version_components.dup
|
29
|
-
components.delete_at(3) if components[3] == 0
|
30
|
-
components.join(".")
|
31
|
-
end
|
32
|
-
|
33
|
-
alias_method :to_str, :to_s
|
34
|
-
|
35
|
-
def to_wallet_bytes
|
36
|
-
[
|
37
|
-
@version_components.zip([1_000_000, 10_000, 100, 1]).map { |component, multiplier|
|
38
|
-
component * multiplier
|
39
|
-
}.inject(:+)
|
40
|
-
].pack("V").unpack("C*")
|
41
|
-
end
|
42
|
-
|
43
|
-
protected
|
44
|
-
|
45
|
-
def compare_version_components(other_version_components)
|
46
|
-
other_version_components <=> @version_components
|
47
|
-
end
|
48
|
-
|
49
|
-
# Pads 3-digit arrays with a 4th 0 value if necessary
|
50
|
-
def pad_4(components)
|
51
|
-
([0] * 4).tap do |padded|
|
52
|
-
padded[0...components.length] = components
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository'
|
2
|
-
require 'bitcoin/data_access/satoshi/satoshi_version'
|
3
|
-
require 'bitcoin/domain/address_book'
|
4
|
-
require 'bitcoin/domain/bitcoin_address'
|
5
|
-
|
6
|
-
module Bitcoin
|
7
|
-
module DataAccess
|
8
|
-
module Satoshi
|
9
|
-
class SatoshiWallet
|
10
|
-
class << self
|
11
|
-
def open(options, &block)
|
12
|
-
raise ArgumentError.new("You must provide a block to SatoshiWallet.new") unless block_given?
|
13
|
-
yield(new(BDBSatoshiWalletRepository.new(options[:wallet_filename], db_dirname: options[:db_dirname])))
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(wallet_repository)
|
18
|
-
@wallet_repository = wallet_repository
|
19
|
-
end
|
20
|
-
|
21
|
-
def version
|
22
|
-
SatoshiVersion.from_wallet_int(@wallet_repository.get_value_immediate_uint32le("version"))
|
23
|
-
end
|
24
|
-
|
25
|
-
def addresses
|
26
|
-
addresses =
|
27
|
-
@wallet_repository.get_key_and_value_data_string_utf8("name").map { |key_data, value_data|
|
28
|
-
{ address: Domain::BitcoinAddress.new(key_data), name: value_data }
|
29
|
-
}
|
30
|
-
Domain::AddressBook.new(addresses)
|
31
|
-
end
|
32
|
-
|
33
|
-
def add_address(bitcoin_address, options)
|
34
|
-
@wallet_repository.set_value_with_key_data_string_utf8("name", bitcoin_address.to_s, options[:name])
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Bitcoin
|
2
|
-
module Domain
|
3
|
-
class AddressBook
|
4
|
-
def initialize(address_list = [])
|
5
|
-
@address_list = Marshal.load(Marshal.dump(address_list))
|
6
|
-
end
|
7
|
-
|
8
|
-
def to_a
|
9
|
-
@address_list
|
10
|
-
end
|
11
|
-
|
12
|
-
def to_s
|
13
|
-
@address_list.map { |address|
|
14
|
-
"#{address[:address]} #{address[:name]}"
|
15
|
-
}.join("\n")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
module Bitcoin
|
2
|
-
module Domain
|
3
|
-
# A Value Object representing a Bitcoin address
|
4
|
-
class BitcoinAddress
|
5
|
-
# An error indicating that we tried to create a BitcoinAddress with an invalid string
|
6
|
-
class InvalidBitcoinAddressError < ArgumentError
|
7
|
-
def initialize(address)
|
8
|
-
super(%'The address "#{address}" is not a valid Bitcoin address')
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize(string_address)
|
13
|
-
raise InvalidBitcoinAddressError.new(string_address) unless string_address.length == 34
|
14
|
-
@string_address = string_address
|
15
|
-
end
|
16
|
-
|
17
|
-
def to_s
|
18
|
-
@string_address
|
19
|
-
end
|
20
|
-
|
21
|
-
def ==(other)
|
22
|
-
other.is_a?(BitcoinAddress) &&
|
23
|
-
other.has_string_address_representation?(@string_address)
|
24
|
-
end
|
25
|
-
|
26
|
-
protected
|
27
|
-
|
28
|
-
def has_string_address_representation?(string_representation)
|
29
|
-
@string_address == string_representation
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
|
-
module Bitcoin
|
4
|
-
module FileSystem
|
5
|
-
# A class for managing temporary directories
|
6
|
-
#
|
7
|
-
# Example:
|
8
|
-
#
|
9
|
-
# EmptyTempDir.new(with_name: "foo", parallel_to: "/tmp/myfile") do |temp_dir|
|
10
|
-
# # ...
|
11
|
-
# end
|
12
|
-
#
|
13
|
-
# creates the directory "/tmp/foo". It will be deleted at the end of the block,
|
14
|
-
# regardless of whether it existed before or not.
|
15
|
-
#
|
16
|
-
# If it existed before, it will be emptied before the block starts.
|
17
|
-
#
|
18
|
-
# If the requested directory name exists but is a file, the behaviour is undefined
|
19
|
-
class EmptyTempDir
|
20
|
-
class << self
|
21
|
-
def open(options, &block)
|
22
|
-
raise ArgumentError.new("You must provide a block to EmptyTempDir.open") if block.nil?
|
23
|
-
BlockRunner.new(dirname(options[:with_name], options[:parallel_to])).run(block)
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def dirname(name, parallel_to)
|
29
|
-
File.expand_path(File.join(File.dirname(parallel_to), name))
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class BlockRunner
|
34
|
-
def initialize(path)
|
35
|
-
@path = path
|
36
|
-
raise_if_path_is_unsafe
|
37
|
-
end
|
38
|
-
|
39
|
-
def run(proc)
|
40
|
-
ensure_empty_directory(absolute_path)
|
41
|
-
result = proc.(self)
|
42
|
-
ensure
|
43
|
-
FileUtils.rm_rf(absolute_path)
|
44
|
-
result
|
45
|
-
end
|
46
|
-
|
47
|
-
def absolute_path
|
48
|
-
@path
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def ensure_empty_directory(absolute_path)
|
54
|
-
if File.directory?(@path)
|
55
|
-
File.join(@path, "*")
|
56
|
-
FileUtils.rm_rf(Dir[path_entries_wildcard])
|
57
|
-
else
|
58
|
-
FileUtils.mkdir(@path)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def raise_if_path_is_unsafe
|
63
|
-
if path_entries_wildcard =~ %r"^/+\*"
|
64
|
-
raise ArgumentError.new("Unacceptable directory name for EmptyTempDir")
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def path_entries_wildcard
|
69
|
-
File.join(@path, "*")
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
require_relative 'argument_matchers/block_evaluating_to_matcher'
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Bitcoin
|
2
|
-
module RSpec
|
3
|
-
module ArgumentMatchers
|
4
|
-
class BlockEvaluatingToMatcher
|
5
|
-
def initialize(expected_value)
|
6
|
-
@expected_value = expected_value
|
7
|
-
end
|
8
|
-
|
9
|
-
def description
|
10
|
-
"block_evaluating_to(#{@expected_value.inspect})"
|
11
|
-
end
|
12
|
-
|
13
|
-
def ==(other)
|
14
|
-
@expected_value == other.()
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def block_evaluating_to(expected_value)
|
19
|
-
BlockEvaluatingToMatcher.new(expected_value)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Bitcoin
|
2
|
-
module RSpec
|
3
|
-
module DirectoryHelpers
|
4
|
-
module ClassMethods
|
5
|
-
def ensure_empty_test_dir(dirname)
|
6
|
-
before(:each) do
|
7
|
-
ensure_empty_directory(dirname)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.included(host)
|
13
|
-
host.extend(ClassMethods)
|
14
|
-
end
|
15
|
-
|
16
|
-
def ensure_empty_directory(dirname)
|
17
|
-
FileUtils.rm_rf(dirname)
|
18
|
-
FileUtils.mkdir_p(dirname)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/lib/bitcoin/version.rb
DELETED
data/spec/bitcoin/cli_spec.rb
DELETED
@@ -1,128 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
require 'bitcoin/cli'
|
4
|
-
|
5
|
-
# Dependencies only used in the spec
|
6
|
-
require 'bitcoin/console/capturing_stream_bundle'
|
7
|
-
|
8
|
-
module Bitcoin
|
9
|
-
describe CLI do
|
10
|
-
let(:stream_bundle) { Console::CapturingStreamBundle.test_bundle }
|
11
|
-
let(:cli) { CLI.new(stream_bundle) }
|
12
|
-
|
13
|
-
describe "help" do
|
14
|
-
shared_examples_for "inputs that trigger a full help message" do
|
15
|
-
let(:help_command) { mock(Commands::HelpCommand, show_help: nil) }
|
16
|
-
|
17
|
-
before(:each) do
|
18
|
-
Commands::HelpCommand.stub(new: help_command)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "creates a Help Command" do
|
22
|
-
Commands::HelpCommand.should_receive(:new).with(stream_bundle)
|
23
|
-
run_command
|
24
|
-
end
|
25
|
-
|
26
|
-
it "shows the full help" do
|
27
|
-
help_command.should_receive(:show_help)
|
28
|
-
run_command
|
29
|
-
end
|
30
|
-
|
31
|
-
it "returns 0", because: "the CLI wrapper exits with this value" do
|
32
|
-
run_command.should eq 0
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "<no command>" do
|
37
|
-
def run_command
|
38
|
-
cli.run([ ])
|
39
|
-
end
|
40
|
-
|
41
|
-
it_behaves_like "inputs that trigger a full help message"
|
42
|
-
end
|
43
|
-
|
44
|
-
describe "help" do
|
45
|
-
def run_command
|
46
|
-
cli.run(%w[ help ])
|
47
|
-
end
|
48
|
-
|
49
|
-
it_behaves_like "inputs that trigger a full help message"
|
50
|
-
end
|
51
|
-
|
52
|
-
describe "<unknown command>" do
|
53
|
-
let(:help_command) { mock(Commands::HelpCommand, show_unknown_command_help: nil) }
|
54
|
-
|
55
|
-
before(:each) do
|
56
|
-
Commands::HelpCommand.stub(new: help_command)
|
57
|
-
end
|
58
|
-
|
59
|
-
def run_command
|
60
|
-
cli.run(%w[ thiscommanddoesnotexist ])
|
61
|
-
end
|
62
|
-
|
63
|
-
it "creates a Help Command" do
|
64
|
-
Commands::HelpCommand.should_receive(:new).with(stream_bundle)
|
65
|
-
run_command
|
66
|
-
end
|
67
|
-
|
68
|
-
it "shows the unknown command help" do
|
69
|
-
help_command.should_receive(:show_unknown_command_help).with("thiscommanddoesnotexist")
|
70
|
-
run_command
|
71
|
-
end
|
72
|
-
|
73
|
-
it "returns 1", because: "the CLI wrapper exits with this value" do
|
74
|
-
run_command.should eq 1
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe "satoshi-wallet" do
|
80
|
-
let(:wallet_command) { mock(Commands::SatoshiWalletCommand, run: nil) }
|
81
|
-
let(:satoshi_wallet_command_environment) { mock(Commands::SatoshiWalletCommandEnvironment) }
|
82
|
-
|
83
|
-
before(:each) do
|
84
|
-
Commands::SatoshiWalletCommand.stub(new: wallet_command)
|
85
|
-
Commands::SatoshiWalletCommandEnvironment.stub(new: satoshi_wallet_command_environment)
|
86
|
-
end
|
87
|
-
|
88
|
-
def run_command
|
89
|
-
cli.run(%W[ satoshi-wallet subcommand-name wallet.dat foo bar ])
|
90
|
-
end
|
91
|
-
|
92
|
-
it "creates an environment" do
|
93
|
-
Commands::SatoshiWalletCommandEnvironment.should_receive(:new).with(stream_bundle)
|
94
|
-
run_command
|
95
|
-
end
|
96
|
-
|
97
|
-
it "creates a command" do
|
98
|
-
Commands::SatoshiWalletCommand.should_receive(:new).with(stream_bundle, satoshi_wallet_command_environment)
|
99
|
-
run_command
|
100
|
-
end
|
101
|
-
|
102
|
-
it "runs the command" do
|
103
|
-
wallet_command.should_receive(:run).with(%w[ subcommand-name wallet.dat foo bar ])
|
104
|
-
run_command
|
105
|
-
end
|
106
|
-
|
107
|
-
context "the command succeeds" do
|
108
|
-
before(:each) do
|
109
|
-
wallet_command.stub(run: nil)
|
110
|
-
end
|
111
|
-
|
112
|
-
it "returns 0", because: "the CLI wrapper exits with this value" do
|
113
|
-
run_command.should eq 0
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
context "the command fails" do
|
118
|
-
before(:each) do
|
119
|
-
wallet_command.stub(:run).and_raise(CLI::CommandError.new)
|
120
|
-
end
|
121
|
-
|
122
|
-
it "returns 1", because: "the CLI wrapper exits with this value" do
|
123
|
-
run_command.should eq 1
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
require 'bitcoin/commands/help_command'
|
4
|
-
require 'bitcoin/console/capturing_stream_bundle'
|
5
|
-
|
6
|
-
module Bitcoin
|
7
|
-
module Commands
|
8
|
-
describe HelpCommand do
|
9
|
-
let(:stream_bundle) { Console::CapturingStreamBundle.test_bundle }
|
10
|
-
|
11
|
-
subject { HelpCommand.new(stream_bundle) }
|
12
|
-
|
13
|
-
describe "#show_help" do
|
14
|
-
it "prints the full help" do
|
15
|
-
subject.show_help
|
16
|
-
# Duplicated from the Cucumber feature to get us going
|
17
|
-
stream_bundle.captured_output.should eq(
|
18
|
-
-%{
|
19
|
-
Usage: rbcoin COMMAND ...
|
20
|
-
|
21
|
-
Commands:
|
22
|
-
help Display help about rbcoin and rbcoin commands
|
23
|
-
satoshi-wallet Manipulate the wallet.dat file of the original client
|
24
|
-
|
25
|
-
Use "rbcoin COMMAND --help" or "rbcoin help COMMAND" for help on a single command
|
26
|
-
Use "rbcoin --version" to see the rbcoin version number
|
27
|
-
Use "rbcoin --exact-version" to see the all version details (with dependencies)
|
28
|
-
} + "\n"
|
29
|
-
)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe "#show_unknown_command_help" do
|
34
|
-
it "prints an error message to the output", because: "it's currently not this object that detected the error" do
|
35
|
-
subject.show_unknown_command_help("thiscommanddoesnotexist")
|
36
|
-
# Duplicated from the Cucumber feature
|
37
|
-
stream_bundle.captured_output.should eq(
|
38
|
-
-%{
|
39
|
-
rbcoin failed: No such command "thiscommanddoesnotexist"
|
40
|
-
Try: `rbcoin help`
|
41
|
-
} + "\n"
|
42
|
-
)
|
43
|
-
end
|
44
|
-
|
45
|
-
it "doesn't raise an error", because: "it's currently not this object that detected the error" do
|
46
|
-
expect {
|
47
|
-
subject.show_unknown_command_help("thiscommanddoesnotexist")
|
48
|
-
}.to_not raise_error
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|