bitcoin-ruby 0.0.3 → 0.0.4
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.
- data/.travis.yml +7 -1
- data/README.rdoc +5 -0
- data/lib/bitcoin/script.rb +19 -11
- data/lib/bitcoin/storage/sequel/migrations/001_base_schema.rb +1 -1
- data/lib/bitcoin/storage/sequel/migrations/002_tx.rb +1 -6
- data/lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb +1 -1
- data/lib/bitcoin/storage/sequel/migrations/004_change_txin_prev_out_to_blob.rb +18 -0
- data/lib/bitcoin/storage/storage.rb +1 -0
- data/lib/bitcoin/storage/utxo/migrations/001_base_schema.rb +1 -1
- data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +1 -1
- data/lib/bitcoin/version.rb +1 -1
- data/spec/bitcoin/script/opcodes_spec.rb +6 -0
- data/spec/bitcoin/spec_helper.rb +21 -0
- data/spec/bitcoin/storage/reorg_spec.rb +14 -8
- data/spec/bitcoin/storage/storage_spec.rb +15 -8
- data/spec/bitcoin/storage/validation_spec.rb +17 -8
- metadata +3 -2
data/.travis.yml
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
3
|
- 1.9.3
|
4
|
-
- 2.0.0
|
4
|
+
- 2.0.0
|
5
|
+
before_script:
|
6
|
+
- psql -c 'create database bitcoin_test;' -U postgres
|
7
|
+
- mysql -e 'create database bitcoin_test;'
|
8
|
+
env:
|
9
|
+
- TEST_DB_POSTGRES="postgres://postgres@localhost/bitcoin_test"
|
10
|
+
- TEST_DB_MYSQL="mysql:/bitcoin_test"
|
data/README.rdoc
CHANGED
@@ -240,6 +240,11 @@ or, if you want to run a single spec
|
|
240
240
|
|
241
241
|
ruby spec/bitcoin/bitcoin_spec.rb
|
242
242
|
|
243
|
+
To test the postgres/mysql storage backend, create a database and set it as an environment variable:
|
244
|
+
|
245
|
+
echo "create database bitcoin_test" | psql
|
246
|
+
TEST_DB_POSTGRES="postgres:/bitcoin_test" rake bacon
|
247
|
+
|
243
248
|
If you make changes to the code or add functionality, please also add specs.
|
244
249
|
|
245
250
|
== Development
|
data/lib/bitcoin/script.rb
CHANGED
@@ -1035,15 +1035,17 @@ class Bitcoin::Script
|
|
1035
1035
|
# TODO: validate signature order
|
1036
1036
|
# TODO: take global opcode count
|
1037
1037
|
def op_checkmultisig(check_callback)
|
1038
|
+
return invalid if @stack.size < 1
|
1038
1039
|
n_pubkeys = pop_int
|
1039
1040
|
return invalid unless (0..20).include?(n_pubkeys)
|
1040
|
-
return invalid
|
1041
|
-
|
1041
|
+
#return invalid if (nOpCount += n_pubkeys) > 201
|
1042
|
+
return invalid if @stack.size < n_pubkeys
|
1042
1043
|
pubkeys = pop_string(n_pubkeys)
|
1043
1044
|
|
1045
|
+
return invalid if @stack.size < 1
|
1044
1046
|
n_sigs = pop_int
|
1045
|
-
return invalid
|
1046
|
-
return invalid
|
1047
|
+
return invalid if n_sigs < 0 || n_sigs > n_pubkeys
|
1048
|
+
return invalid if @stack.size < n_sigs
|
1047
1049
|
sigs = drop_sigs = pop_string(n_sigs)
|
1048
1050
|
|
1049
1051
|
@stack.pop if @stack[-1] && cast_to_bignum(@stack[-1]) == 0 # remove OP_0 from stack
|
@@ -1055,14 +1057,20 @@ class Bitcoin::Script
|
|
1055
1057
|
script_code, drop_sigs = nil, nil
|
1056
1058
|
end
|
1057
1059
|
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1060
|
+
success = true
|
1061
|
+
while success && n_sigs > 0
|
1062
|
+
sig, pub = sigs.pop, pubkeys.pop
|
1063
|
+
signature, hash_type = parse_sig(sig)
|
1064
|
+
if check_callback.call(pub, signature, hash_type, drop_sigs, script_code)
|
1065
|
+
n_sigs -= 1
|
1066
|
+
else
|
1067
|
+
sigs << sig
|
1068
|
+
end
|
1069
|
+
n_pubkeys -= 1
|
1070
|
+
success = false if n_sigs > n_pubkeys
|
1071
|
+
end
|
1064
1072
|
|
1065
|
-
@stack << (
|
1073
|
+
@stack << (success ? 1 : (invalid; 0))
|
1066
1074
|
end
|
1067
1075
|
|
1068
1076
|
# op_eval: https://en.bitcoin.it/wiki/BIP_0012
|
@@ -2,7 +2,7 @@ Sequel.migration do
|
|
2
2
|
|
3
3
|
up do
|
4
4
|
|
5
|
-
|
5
|
+
@log.info { "Running migration #{__FILE__}" }
|
6
6
|
|
7
7
|
next if tables.include?(:tx)
|
8
8
|
|
@@ -40,11 +40,6 @@ Sequel.migration do
|
|
40
40
|
column :type, :int, :null => false, :index => true
|
41
41
|
end
|
42
42
|
|
43
|
-
create_view(:unconfirmed,
|
44
|
-
"SELECT * FROM tx WHERE NOT EXISTS " +
|
45
|
-
"(SELECT 1 FROM blk_tx WHERE blk_tx.tx_id = tx.id)" +
|
46
|
-
"ORDER BY tx.id DESC")
|
47
|
-
|
48
43
|
end
|
49
44
|
|
50
45
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Sequel.migration do
|
2
|
+
|
3
|
+
up do
|
4
|
+
|
5
|
+
@log.info { "Running migration #{__FILE__}" }
|
6
|
+
|
7
|
+
if adapter_scheme == :postgres
|
8
|
+
add_column :txin, :tmp_prev_out, :bytea
|
9
|
+
self[:txin].where.update("tmp_prev_out = prev_out::bytea")
|
10
|
+
drop_column :txin, :prev_out
|
11
|
+
add_column :txin, :prev_out, :bytea, index: true
|
12
|
+
self[:txin].where.update("prev_out = tmp_prev_out")
|
13
|
+
drop_column :txin, :tmp_prev_out
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -101,6 +101,7 @@ module Bitcoin::Storage
|
|
101
101
|
migrations_path = File.join(File.dirname(__FILE__), "#{backend_name}/migrations")
|
102
102
|
Sequel.extension :migration
|
103
103
|
unless Sequel::Migrator.is_current?(@db, migrations_path)
|
104
|
+
log = @log; @db.instance_eval { @log = log }
|
104
105
|
Sequel::Migrator.run(@db, migrations_path)
|
105
106
|
unless (v = @db[:schema_info].first) && v[:magic] && v[:backend]
|
106
107
|
@db[:schema_info].update(
|
data/lib/bitcoin/version.rb
CHANGED
@@ -542,6 +542,12 @@ describe "Bitcoin::Script OPCODES" do
|
|
542
542
|
script = "0 #{sig1} #{sig2} 2 #{k1.pub} #{k2.pub} 2 OP_CHECKMULTISIG"
|
543
543
|
run_script(script, "foobar").should == true
|
544
544
|
|
545
|
+
script = "0 #{sig2} #{sig1} 2 #{k1.pub} #{k2.pub} 2 OP_CHECKMULTISIG"
|
546
|
+
run_script(script, "foobar").should == false
|
547
|
+
|
548
|
+
script = "0 #{sig1} #{sig2} 2 #{k2.pub} #{k1.pub} 2 OP_CHECKMULTISIG"
|
549
|
+
run_script(script, "foobar").should == false
|
550
|
+
|
545
551
|
script = "0 #{sig1} #{sig2} 2 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG"
|
546
552
|
run_script(script, "foobar").should == true
|
547
553
|
|
data/spec/bitcoin/spec_helper.rb
CHANGED
@@ -102,3 +102,24 @@ rescue LoadError
|
|
102
102
|
end
|
103
103
|
Bacon.summary_on_exit
|
104
104
|
require 'minitest/mock'
|
105
|
+
|
106
|
+
require 'sequel'
|
107
|
+
def setup_db backend, db = nil, conf = {}
|
108
|
+
uri = case db
|
109
|
+
when :sqlite
|
110
|
+
"sqlite:/"
|
111
|
+
when :postgres
|
112
|
+
ENV["TEST_DB_POSTGRES"].dup rescue nil
|
113
|
+
when :mysql
|
114
|
+
ENV["TEST_DB_MYSQL"].dup rescue nil
|
115
|
+
end
|
116
|
+
if [:postgres, :mysql].include?(db)
|
117
|
+
unless uri
|
118
|
+
puts "Skipping #{db} tests"
|
119
|
+
return nil
|
120
|
+
end
|
121
|
+
db = Sequel.connect(uri)
|
122
|
+
db.drop_table(*db.tables, cascade: true)
|
123
|
+
end
|
124
|
+
Bitcoin::Storage.send(backend, conf.merge(db: uri, log_level: :warn))
|
125
|
+
end
|
@@ -4,23 +4,30 @@ require_relative '../spec_helper'
|
|
4
4
|
|
5
5
|
include Bitcoin::Builder
|
6
6
|
|
7
|
+
Bitcoin.network = :testnet
|
7
8
|
|
9
|
+
Bitcoin::Validation::Block::RETARGET = 10
|
8
10
|
|
9
|
-
[
|
10
|
-
|
11
|
+
[
|
12
|
+
[:utxo, :sqlite, index_all_addrs: true],
|
13
|
+
[:sequel, :sqlite], # [:sequel, :postgres],
|
14
|
+
[:utxo, :postgres, index_all_addrs: true],
|
15
|
+
[:sequel, :mysql],
|
16
|
+
[:utxo, :mysql, index_all_addrs: true],
|
17
|
+
].compact.each do |options|
|
11
18
|
|
12
|
-
|
19
|
+
next unless storage = setup_db(*options)
|
20
|
+
|
21
|
+
describe "reorg (#{options[0]} - #{options[1]})" do
|
13
22
|
|
14
23
|
def balance addr
|
15
24
|
@store.get_balance(Bitcoin.hash160_from_address(addr))
|
16
25
|
end
|
17
26
|
|
18
27
|
before do
|
19
|
-
|
20
|
-
@store = Bitcoin::Storage.send(configuration[:name], configuration)
|
28
|
+
@store = storage
|
21
29
|
@store.reset
|
22
30
|
def @store.in_sync?; true; end
|
23
|
-
@store.log.level = :warn
|
24
31
|
Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("ff"*32)
|
25
32
|
@key = Bitcoin::Key.generate
|
26
33
|
@block0 = create_block "00"*32, false, [], @key
|
@@ -33,8 +40,6 @@ include Bitcoin::Builder
|
|
33
40
|
@store.reset
|
34
41
|
time = Time.now.to_i - 3000*600
|
35
42
|
|
36
|
-
Bitcoin::Validation::Block::RETARGET = 10
|
37
|
-
|
38
43
|
# create genesis block
|
39
44
|
block = create_block "00"*32, false, [], @key, 50e8, {time: time}
|
40
45
|
Bitcoin.network[:genesis_hash] = block.hash
|
@@ -187,6 +192,7 @@ include Bitcoin::Builder
|
|
187
192
|
balance("1NiEGXeURREqqMjCvjCeZn6SwEBZ9AdVet").should == 1000000000
|
188
193
|
balance("1KXFNhNtrRMfgbdiQeuJqnfD7dR4PhniyJ").should == 0
|
189
194
|
balance("1JyMKvPHkrCQd8jQrqTR1rBsAd1VpRhTiE").should == 14000000000
|
195
|
+
Bitcoin.network = :testnet
|
190
196
|
class Bitcoin::Validation::Block
|
191
197
|
def difficulty
|
192
198
|
return true if Bitcoin.network_name == :testnet3
|
@@ -8,21 +8,28 @@ include Bitcoin::Storage::Backends
|
|
8
8
|
include Bitcoin::Builder
|
9
9
|
include Bitcoin::Validation
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
Bitcoin::network = :testnet
|
12
|
+
[
|
13
|
+
[:dummy],
|
14
|
+
[:sequel, :sqlite],
|
15
|
+
[:utxo, :sqlite, index_all_addrs: true],
|
16
|
+
[:sequel, :postgres],
|
17
|
+
[:utxo, :postgres, index_all_addrs: true],
|
18
|
+
[:sequel, :mysql],
|
19
|
+
[:utxo, :mysql, index_all_addrs: true],
|
20
|
+
].compact.each do |options|
|
14
21
|
|
15
|
-
|
22
|
+
next unless storage = setup_db(*options)
|
23
|
+
|
24
|
+
describe "Storage::Backends::#{options[0].to_s.capitalize}Store (#{options[1]})" do
|
16
25
|
|
17
26
|
before do
|
18
27
|
class Bitcoin::Validation::Block; def difficulty; true; end; end
|
19
28
|
Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("ff"*32)
|
20
29
|
|
21
|
-
|
22
|
-
@store = Bitcoin::Storage.send(configuration[:name], configuration)
|
30
|
+
@store = storage
|
23
31
|
def @store.in_sync?; true; end
|
24
32
|
@store.reset
|
25
|
-
@store.log.level = 4
|
26
33
|
|
27
34
|
@store.store_block(P::Block.new(fixtures_file('testnet/block_0.bin')))
|
28
35
|
@store.store_block(P::Block.new(fixtures_file('testnet/block_1.bin')))
|
@@ -48,7 +55,7 @@ include Bitcoin::Validation
|
|
48
55
|
end
|
49
56
|
|
50
57
|
it "should get backend name" do
|
51
|
-
@store.backend_name.should ==
|
58
|
+
@store.backend_name.should == options[0].to_s
|
52
59
|
end
|
53
60
|
|
54
61
|
it "should get depth" do
|
@@ -6,18 +6,27 @@ include Bitcoin::Builder
|
|
6
6
|
include Bitcoin::Storage
|
7
7
|
include Bitcoin::Validation
|
8
8
|
|
9
|
-
|
10
|
-
{ :name => :sequel, :db => 'sqlite:/' } ].each do |configuration|
|
9
|
+
Bitcoin.network = :spec
|
11
10
|
|
12
|
-
|
11
|
+
[
|
12
|
+
[:sequel, :sqlite],
|
13
|
+
[:utxo, :sqlite, index_all_addrs: true],
|
14
|
+
[:sequel, :postgres],
|
15
|
+
[:utxo, :postgres, index_all_addrs: true],
|
16
|
+
[:sequel, :mysql],
|
17
|
+
[:utxo, :mysql, index_all_addrs: true],
|
18
|
+
].compact.each do |options|
|
19
|
+
|
20
|
+
next unless storage = setup_db(*options)
|
21
|
+
|
22
|
+
describe "block rules (#{options[0]} - #{options[1]})" do
|
13
23
|
|
14
24
|
def balance addr
|
15
25
|
@store.get_balance(Bitcoin.hash160_from_address(addr))
|
16
26
|
end
|
17
27
|
|
18
28
|
before do
|
19
|
-
|
20
|
-
@store = Bitcoin::Storage.send(configuration[:name], configuration)
|
29
|
+
@store = storage
|
21
30
|
@store.reset
|
22
31
|
@store.log.level = :warn
|
23
32
|
Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("f"*64)
|
@@ -147,11 +156,11 @@ include Bitcoin::Validation
|
|
147
156
|
|
148
157
|
end
|
149
158
|
|
150
|
-
describe "transaction rules (#{
|
159
|
+
describe "transaction rules (#{options[0]} - #{options[1]})" do
|
151
160
|
|
152
161
|
before do
|
153
162
|
Bitcoin.network = :spec
|
154
|
-
@store =
|
163
|
+
@store = storage
|
155
164
|
@store.reset
|
156
165
|
@store.log.level = :warn
|
157
166
|
|
@@ -247,7 +256,7 @@ describe "transaction rules (#{configuration[:name].capitalize}Store)" do
|
|
247
256
|
end
|
248
257
|
|
249
258
|
it "15. Using the referenced output transactions to get input values, check that each input value, as well as the sum, are in legal money range" do
|
250
|
-
@store.db[@store.class.name =~ /Utxo/ ? :utxo : :txout].
|
259
|
+
@store.db[@store.class.name =~ /Utxo/ ? :utxo : :txout].order(:id).reverse.limit(1).update(value: 22e14)
|
251
260
|
check_tx(@tx, [:input_values, [22e14, 21e14]])
|
252
261
|
end
|
253
262
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitcoin-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-10 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: This is a ruby library for interacting with the bitcoin protocol/network
|
15
15
|
email:
|
@@ -93,6 +93,7 @@ files:
|
|
93
93
|
- lib/bitcoin/storage/sequel/migrations/001_base_schema.rb
|
94
94
|
- lib/bitcoin/storage/sequel/migrations/002_tx.rb
|
95
95
|
- lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb
|
96
|
+
- lib/bitcoin/storage/sequel/migrations/004_change_txin_prev_out_to_blob.rb
|
96
97
|
- lib/bitcoin/storage/sequel/sequel_store.rb
|
97
98
|
- lib/bitcoin/storage/storage.rb
|
98
99
|
- lib/bitcoin/storage/utxo/migrations/001_base_schema.rb
|