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
Binary file
|
Binary file
|
@@ -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
|
data/features/support/env.rb
DELETED
@@ -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'
|
data/lib/bitcoin.rb
DELETED
data/lib/bitcoin/cli.rb
DELETED
@@ -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
|
data/lib/bitcoin/commands.rb
DELETED
@@ -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,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
|