bitcoin-ruby 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -1
- data/Gemfile +21 -0
- data/README.rdoc +85 -25
- data/Rakefile +7 -3
- data/bin/bitcoin_node +39 -42
- data/bin/bitcoin_shell +1 -0
- data/bin/bitcoin_wallet +129 -53
- data/bitcoin-ruby.gemspec +4 -7
- data/concept-examples/blockchain-pow.rb +1 -1
- data/doc/CONFIG.rdoc +5 -5
- data/doc/EXAMPLES.rdoc +9 -5
- data/doc/NAMECOIN.rdoc +34 -0
- data/doc/NODE.rdoc +147 -10
- data/examples/balance.rb +10 -4
- data/examples/bbe_verify_tx.rb +7 -2
- data/examples/forwarder.rb +73 -0
- data/examples/generate_tx.rb +34 -0
- data/examples/simple_network_monitor_and_util.rb +187 -0
- data/examples/verify_tx.rb +1 -1
- data/lib/bitcoin.rb +308 -18
- data/lib/bitcoin/builder.rb +62 -36
- data/lib/bitcoin/config.rb +2 -0
- data/lib/bitcoin/connection.rb +11 -8
- data/lib/bitcoin/electrum/mnemonic.rb +162 -0
- data/lib/bitcoin/ffi/openssl.rb +187 -21
- data/lib/bitcoin/gui/addr_view.rb +2 -0
- data/lib/bitcoin/gui/conn_view.rb +2 -0
- data/lib/bitcoin/gui/connection.rb +2 -0
- data/lib/bitcoin/gui/em_gtk.rb +2 -0
- data/lib/bitcoin/gui/gui.rb +2 -0
- data/lib/bitcoin/gui/helpers.rb +2 -0
- data/lib/bitcoin/gui/tree_view.rb +2 -0
- data/lib/bitcoin/gui/tx_view.rb +2 -0
- data/lib/bitcoin/key.rb +77 -11
- data/lib/bitcoin/litecoin.rb +81 -0
- data/lib/bitcoin/logger.rb +20 -1
- data/lib/bitcoin/namecoin.rb +279 -0
- data/lib/bitcoin/network/command_client.rb +7 -6
- data/lib/bitcoin/network/command_handler.rb +229 -43
- data/lib/bitcoin/network/connection_handler.rb +182 -70
- data/lib/bitcoin/network/node.rb +231 -106
- data/lib/bitcoin/protocol.rb +44 -23
- data/lib/bitcoin/protocol/address.rb +5 -3
- data/lib/bitcoin/protocol/alert.rb +3 -4
- data/lib/bitcoin/protocol/aux_pow.rb +123 -0
- data/lib/bitcoin/protocol/block.rb +98 -18
- data/lib/bitcoin/protocol/handler.rb +6 -5
- data/lib/bitcoin/protocol/parser.rb +44 -19
- data/lib/bitcoin/protocol/tx.rb +105 -52
- data/lib/bitcoin/protocol/txin.rb +39 -19
- data/lib/bitcoin/protocol/txout.rb +28 -13
- data/lib/bitcoin/protocol/version.rb +16 -7
- data/lib/bitcoin/script.rb +579 -122
- data/lib/bitcoin/storage/{dummy.rb → dummy/dummy_store.rb} +8 -14
- data/lib/bitcoin/storage/models.rb +20 -7
- data/lib/bitcoin/storage/{sequel_store/sequel_migrations.rb → sequel/migrations.rb} +22 -7
- data/lib/bitcoin/storage/sequel/migrations/001_base_schema.rb +52 -0
- data/lib/bitcoin/storage/sequel/migrations/002_tx.rb +50 -0
- data/lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb +18 -0
- data/lib/bitcoin/storage/sequel/sequel_store.rb +436 -0
- data/lib/bitcoin/storage/storage.rb +233 -28
- data/lib/bitcoin/storage/utxo/migrations/001_base_schema.rb +52 -0
- data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +18 -0
- data/lib/bitcoin/storage/utxo/utxo_store.rb +361 -0
- data/lib/bitcoin/validation.rb +369 -0
- data/lib/bitcoin/version.rb +1 -1
- data/lib/bitcoin/wallet/coinselector.rb +3 -0
- data/lib/bitcoin/wallet/keygenerator.rb +3 -1
- data/lib/bitcoin/wallet/keystore.rb +6 -2
- data/lib/bitcoin/wallet/txdp.rb +6 -4
- data/lib/bitcoin/wallet/wallet.rb +54 -16
- data/spec/bitcoin/bitcoin_spec.rb +48 -3
- data/spec/bitcoin/builder_spec.rb +40 -17
- data/spec/bitcoin/fixtures/000000000000056b1a3d84a1e2b33cde8915a4b61c0cae14fca6d3e1490b4f98.json +3697 -0
- data/spec/bitcoin/fixtures/03d7e1fa4d5fefa169431f24f7798552861b255cd55d377066fedcd088fb0e99.json +23 -0
- data/spec/bitcoin/fixtures/0961c660358478829505e16a1f028757e54b5bbf9758341a7546573738f31429.json +24 -0
- data/spec/bitcoin/fixtures/0f24294a1d23efbb49c1765cf443fba7930702752aba6d765870082fe4f13cae.json +37 -0
- data/spec/bitcoin/fixtures/315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f.json +31 -0
- data/spec/bitcoin/fixtures/35e2001b428891fefa0bfb73167c7360669d3cbd7b3aa78e7cad125ddfc51131.json +27 -0
- data/spec/bitcoin/fixtures/3a17dace09ffb919ed627a93f1873220f4c975c1248558b18d16bce25d38c4b7.json +72 -0
- data/spec/bitcoin/fixtures/3e58b7eed0fdb599019af08578effea25c8666bbe8e200845453cacce6314477.json +27 -0
- data/spec/bitcoin/fixtures/514c46f0b61714092f15c8dfcb576c9f79b3f959989b98de3944b19d98832b58.json +24 -0
- data/spec/bitcoin/fixtures/51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e.json +30 -0
- data/spec/bitcoin/fixtures/69216b8aaa35b76d6613e5f527f4858640d986e1046238583bdad79b35e938dc.json +28 -0
- data/spec/bitcoin/fixtures/7208e5edf525f04e705fb3390194e316205b8f995c8c9fcd8c6093abe04fa27d.json +27 -0
- data/spec/bitcoin/fixtures/761d8c5210fdfd505f6dff38f740ae3728eb93d7d0971fb433f685d40a4c04f6.json +27 -0
- data/spec/bitcoin/fixtures/aea682d68a3ea5e3583e088dcbd699a5d44d4b083f02ad0aaf2598fe1fa4dfd4.json +27 -0
- data/spec/bitcoin/fixtures/bd1715f1abfdc62bea3f605bdb461b3ba1f2cca6ec0d73a18a548b7717ca8531.json +34 -0
- data/spec/bitcoin/fixtures/block-testnet-0000000000ac85bb2530a05a4214a387e6be02b22d3348abc5e7a5d9c4ce8dab.bin +0 -0
- data/spec/bitcoin/fixtures/cd874fa8cb0e2ec2d385735d5e1fd482c4fe648533efb4c50ee53bda58e15ae2.json +24 -0
- data/spec/bitcoin/fixtures/ce5fad9b4ef094d8f4937b0707edaf0a6e6ceeaf67d5edbfd51f660eac8f398b.json +41 -0
- data/spec/bitcoin/fixtures/f003f0c1193019db2497a675fd05d9f2edddf9b67c59e677c48d3dbd4ed5f00b.json +23 -0
- data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.bin +0 -0
- data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.json +43 -0
- data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.bin +0 -0
- data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.json +67 -0
- data/spec/bitcoin/fixtures/litecoin-block-80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f.bin +0 -0
- data/spec/bitcoin/fixtures/litecoin-block-80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f.json +39 -0
- data/spec/bitcoin/fixtures/litecoin-genesis-block-12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2.bin +0 -0
- data/spec/bitcoin/fixtures/litecoin-genesis-block-12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2.json +39 -0
- data/spec/bitcoin/fixtures/rawblock-auxpow.bin +0 -0
- data/spec/bitcoin/fixtures/tx-313897799b1e37e9ecae15010e56156dddde4e683c96b0e713af95272c38aee0.json +30 -0
- data/spec/bitcoin/fixtures/tx-3da75972766f0ad13319b0b461fd16823a731e44f6e9de4eb3c52d6a6fb6c8ae.json +23 -0
- data/spec/bitcoin/fixtures/tx-44b833074e671120ba33106877b49e86ece510824b9af477a3853972bcd8d06a.json +30 -0
- data/spec/bitcoin/fixtures/tx-d3d77d63709e47d9ef58f0b557800115a6b676c6a423012fbb96f45d8fcef830.json +28 -0
- data/spec/bitcoin/key_spec.rb +128 -3
- data/spec/bitcoin/namecoin_spec.rb +182 -0
- data/spec/bitcoin/network_spec.rb +5 -3
- data/spec/bitcoin/node/command_api_spec.rb +376 -0
- data/spec/bitcoin/protocol/addr_spec.rb +2 -0
- data/spec/bitcoin/protocol/alert_spec.rb +2 -0
- data/spec/bitcoin/protocol/aux_pow_spec.rb +44 -0
- data/spec/bitcoin/protocol/block_spec.rb +134 -39
- data/spec/bitcoin/protocol/getblocks_spec.rb +32 -0
- data/spec/bitcoin/protocol/inv_spec.rb +10 -8
- data/spec/bitcoin/protocol/notfound_spec.rb +31 -0
- data/spec/bitcoin/protocol/ping_spec.rb +2 -0
- data/spec/bitcoin/protocol/tx_spec.rb +83 -17
- data/spec/bitcoin/protocol/version_spec.rb +7 -5
- data/spec/bitcoin/script/opcodes_spec.rb +412 -133
- data/spec/bitcoin/script/script_spec.rb +112 -13
- data/spec/bitcoin/spec_helper.rb +68 -0
- data/spec/bitcoin/storage/reorg_spec.rb +199 -0
- data/spec/bitcoin/storage/storage_spec.rb +337 -0
- data/spec/bitcoin/storage/validation_spec.rb +261 -0
- data/spec/bitcoin/wallet/coinselector_spec.rb +10 -7
- data/spec/bitcoin/wallet/keygenerator_spec.rb +2 -0
- data/spec/bitcoin/wallet/keystore_spec.rb +2 -0
- data/spec/bitcoin/wallet/txdp_spec.rb +2 -0
- data/spec/bitcoin/wallet/wallet_spec.rb +91 -58
- metadata +105 -51
- data/lib/bitcoin/storage/sequel.rb +0 -335
- data/spec/bitcoin/fixtures/0d0affb5964abe804ffe85e53f1dbb9f29e406aa3046e2db04fba240e63c7fdd.json +0 -27
- data/spec/bitcoin/fixtures/477fff140b363ec2cc51f3a65c0c58eda38f4d41f04a295bbd62babf25e4c590.json +0 -27
- data/spec/bitcoin/reorg_spec.rb +0 -129
- data/spec/bitcoin/storage_spec.rb +0 -229
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require_relative '../spec_helper.rb'
|
4
|
+
|
5
|
+
include Bitcoin
|
6
|
+
|
7
|
+
describe Bitcoin::Protocol::AuxPow do
|
8
|
+
|
9
|
+
before do
|
10
|
+
@data = fixtures_file("rawblock-auxpow.bin")
|
11
|
+
@blk = P::Block.new(@data)
|
12
|
+
@aux_pow = @blk.aux_pow
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should parse AuxPow" do
|
16
|
+
@aux_pow.should != nil
|
17
|
+
@aux_pow.block_hash.hth.should ==
|
18
|
+
"b42124fd99e67ddabe52ebbfcb30a82b8c74268a320b3c5e2311000000000000"
|
19
|
+
@aux_pow.branch.map(&:hth).should == [
|
20
|
+
"6d4febe909ffec61fb8e7bf24ef4444f070f74b208502285528a9686ba792fc2",
|
21
|
+
"d052728459450cec6ff81072c6bd3ec2fd186eaadb09429da7cab0be73646999",
|
22
|
+
"64c5e7e42a6cde585602fdfda6d7e5d9232db2c176a49278268cec09f3cfcb20",
|
23
|
+
"4e9406d6ce9ef751242bb9a63e7c2009746b3736c356ed5d738dadd6937531e4" ]
|
24
|
+
@aux_pow.mrkl_index.should == 0
|
25
|
+
@aux_pow.aux_branch.should == []
|
26
|
+
@aux_pow.aux_index.should == 0
|
27
|
+
@aux_pow.parent_block.hash.should ==
|
28
|
+
"00000000000011235e3c0b328a26748c2ba830cbbfeb52beda7de699fd2421b4"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "#to_payload" do
|
32
|
+
@blk.to_payload.should == @data
|
33
|
+
P::Block.new(@blk.to_payload).to_payload.should == @data
|
34
|
+
end
|
35
|
+
|
36
|
+
it "#to_hash" do
|
37
|
+
P::Block.from_hash(@blk.to_hash).to_payload.should == @data
|
38
|
+
end
|
39
|
+
|
40
|
+
it "#to_json" do
|
41
|
+
P::Block.from_json(@blk.to_json).to_payload.should == @data
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -1,39 +1,43 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
1
3
|
require_relative '../spec_helper.rb'
|
4
|
+
include Bitcoin::Protocol
|
2
5
|
|
3
6
|
describe 'Bitcoin::Protocol::Block' do
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
8
|
+
before do
|
9
|
+
@blocks = {
|
10
|
+
# block 0: 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
|
11
|
+
'0' => fixtures_file('rawblock-0.bin'),
|
12
|
+
# block 1: 000000006a625f06636b8bb6ac7b960a8d03705d1ace08b1a19da3fdcc99ddbd
|
13
|
+
'1' => fixtures_file('rawblock-1.bin'),
|
14
|
+
# block 9: 000000008d9dc510f23c2657fc4f67bea30078cc05a90eb89e84cc475c080805
|
15
|
+
'9' => fixtures_file('rawblock-9.bin'),
|
16
|
+
# block 170: 00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee
|
17
|
+
'170' => fixtures_file('rawblock-170.bin'),
|
18
|
+
# block 131025: 00000000000007d938dbdd433c5ae12a782de74abf7f566518bc2b2d0a1df145
|
19
|
+
'131025' => fixtures_file('rawblock-131025.bin'),
|
20
|
+
# block 26478: 000000000214a3f06ee99a033a7f2252762d6a18d27c3cd8c8fe2278190da9f3
|
21
|
+
'testnet-26478' => fixtures_file('rawblock-testnet-26478.bin'),
|
22
|
+
}
|
23
|
+
end
|
20
24
|
|
21
25
|
it '#new' do
|
22
26
|
proc{
|
23
|
-
|
24
|
-
@block =
|
27
|
+
Block.new( nil )
|
28
|
+
@block = Block.new( @blocks['0'] )
|
25
29
|
}.should.not.raise Exception
|
26
30
|
|
27
31
|
proc{
|
28
|
-
|
32
|
+
Block.new( @blocks['0'][0..20] )
|
29
33
|
}.should.raise Exception
|
30
34
|
|
31
|
-
block =
|
35
|
+
block = Block.new(nil)
|
32
36
|
block.parse_data(@blocks['0']).should == true
|
33
37
|
block.header_info[7].should == 215
|
34
38
|
block.to_payload.should == @blocks['0']
|
35
39
|
|
36
|
-
block =
|
40
|
+
block = Block.new(nil)
|
37
41
|
block.parse_data(@blocks['0'] + "AAAA").should == "AAAA"
|
38
42
|
block.header_info[7].should == 215
|
39
43
|
block.to_payload.should == @blocks['0']
|
@@ -45,7 +49,7 @@ describe 'Bitcoin::Protocol::Block' do
|
|
45
49
|
|
46
50
|
it '#tx' do
|
47
51
|
@block.tx.size.should == 1
|
48
|
-
@block.tx[0].is_a?(
|
52
|
+
@block.tx[0].is_a?(Tx).should == true
|
49
53
|
@block.tx[0].hash.should == "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"
|
50
54
|
end
|
51
55
|
|
@@ -55,31 +59,100 @@ describe 'Bitcoin::Protocol::Block' do
|
|
55
59
|
|
56
60
|
it '#to_json' do
|
57
61
|
@block.to_json.should == fixtures_file('rawblock-0.json')
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
+
Block.new( @blocks['1'] ).to_json.should == fixtures_file('rawblock-1.json')
|
63
|
+
Block.new( @blocks['131025'] ).to_json.should == fixtures_file('rawblock-131025.json')
|
64
|
+
Block.new( @blocks['testnet-26478'] ).to_json.should == fixtures_file('rawblock-testnet-26478.json')
|
65
|
+
Block.from_json(@block.to_json).tx[0].in[0].sequence.should == "\xff\xff\xff\xff"
|
62
66
|
end
|
63
67
|
|
64
68
|
it '#to_payload' do
|
65
69
|
@block.to_payload.should == @block.payload
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
+
Block.new( @block.to_payload ).to_payload.should == @block.payload
|
71
|
+
Block.new( @blocks['1'] ).to_payload.should == @blocks['1']
|
72
|
+
Block.new( @blocks['131025'] ).to_payload.should == @blocks['131025']
|
73
|
+
Block.new( @blocks['testnet-26478'] ).to_payload.should == @blocks['testnet-26478']
|
70
74
|
end
|
71
75
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
76
|
+
describe "Block.from_json" do
|
77
|
+
|
78
|
+
it 'should load blocks from json' do
|
79
|
+
block = Block.from_json(fixtures_file('rawblock-0.json'))
|
80
|
+
block.to_payload.should == @blocks['0']
|
81
|
+
block.tx[0].in[0].sequence.should == "\xff\xff\xff\xff"
|
82
|
+
Block.from_json(fixtures_file('rawblock-1.json')).to_payload.should == @blocks['1']
|
83
|
+
|
84
|
+
Block.from_json(fixtures_file('rawblock-131025.json'))
|
85
|
+
.to_payload.should == @blocks['131025']
|
86
|
+
|
87
|
+
Block.from_json(fixtures_file('rawblock-testnet-26478.json'))
|
88
|
+
.to_payload.should == @blocks['testnet-26478']
|
89
|
+
|
90
|
+
# testnet3 block 0000000000ac85bb2530a05a4214a387e6be02b22d3348abc5e7a5d9c4ce8dab
|
91
|
+
block_raw = fixtures_file('block-testnet-0000000000ac85bb2530a05a4214a387e6be02b22d3348abc5e7a5d9c4ce8dab.bin')
|
92
|
+
Block.new(block_raw).to_payload.should == block_raw
|
93
|
+
# Block.from_json(Block.new(block_raw).to_json).to_payload.should == block_raw # slow test
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should work with litecoin blocks" do
|
97
|
+
Bitcoin.network = :litecoin # change to litecoin
|
98
|
+
litecoin_block = "litecoin-genesis-block-12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2"
|
99
|
+
Block.from_json(fixtures_file(litecoin_block + '.json'))
|
100
|
+
.to_payload.should == fixtures_file(litecoin_block + '.bin')
|
101
|
+
|
102
|
+
json = Block.new(fixtures_file(litecoin_block + '.bin')).to_json
|
103
|
+
Block.from_json(json)
|
104
|
+
.to_payload.should == fixtures_file(litecoin_block + '.bin')
|
105
|
+
Block.from_json(json).hash == litecoin_block.split("-").last
|
106
|
+
|
107
|
+
litecoin_block = "litecoin-block-80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f"
|
108
|
+
Block.from_json(fixtures_file(litecoin_block + '.json'))
|
109
|
+
.to_payload.should == fixtures_file(litecoin_block + '.bin')
|
110
|
+
|
111
|
+
json = Block.new(fixtures_file(litecoin_block + '.bin')).to_json
|
112
|
+
Block.from_json(json)
|
113
|
+
.to_payload.should == fixtures_file(litecoin_block + '.bin')
|
114
|
+
Block.from_json(json).hash == litecoin_block.split("-").last
|
115
|
+
Bitcoin.network = :bitcoin
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should work with freicoin blocks" do
|
119
|
+
Bitcoin.network = :freicoin # change to freicoin
|
120
|
+
freicoin_block = "freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c"
|
121
|
+
Block.from_json(fixtures_file(freicoin_block + '.json'))
|
122
|
+
.to_payload.should == fixtures_file(freicoin_block + '.bin')
|
123
|
+
|
124
|
+
json = Block.new(fixtures_file(freicoin_block + '.bin')).to_json
|
125
|
+
Block.from_json(json)
|
126
|
+
.to_payload.should == fixtures_file(freicoin_block + '.bin')
|
127
|
+
Block.from_json(json).hash == freicoin_block.split("-").last
|
128
|
+
|
129
|
+
freicoin_block = "freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c"
|
130
|
+
Block.from_json(fixtures_file(freicoin_block + '.json'))
|
131
|
+
.to_payload.should == fixtures_file(freicoin_block + '.bin')
|
132
|
+
|
133
|
+
json = Block.new(fixtures_file(freicoin_block + '.bin')).to_json
|
134
|
+
Block.from_json(json)
|
135
|
+
.to_payload.should == fixtures_file(freicoin_block + '.bin')
|
136
|
+
Block.from_json(json).hash == freicoin_block.split("-").last
|
137
|
+
Bitcoin.network = :bitcoin
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should check block hash' do
|
141
|
+
block = Block.from_json(fixtures_file('rawblock-0.json'))
|
142
|
+
h = block.to_hash
|
143
|
+
h['hash'][0] = "1"
|
144
|
+
-> { Block.from_hash(h) }.should.raise(Exception)
|
145
|
+
.message.should == "Block hash mismatch! Claimed: 10000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048, Actual: 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048"
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should check merkle tree" do
|
149
|
+
block = Block.from_json(fixtures_file('rawblock-0.json'))
|
150
|
+
h = block.to_hash
|
151
|
+
h['tx'][0]['ver'] = 2
|
152
|
+
-> { Block.from_hash(h) }.should.raise(Exception)
|
153
|
+
.message.should.include?("Block merkle root mismatch!")
|
154
|
+
end
|
80
155
|
|
81
|
-
Bitcoin::Protocol::Block.from_json(fixtures_file('rawblock-testnet-26478.json'))
|
82
|
-
.to_payload.should == @blocks['testnet-26478']
|
83
156
|
end
|
84
157
|
|
85
158
|
it '#header_to_json' do
|
@@ -98,4 +171,26 @@ describe 'Bitcoin::Protocol::Block' do
|
|
98
171
|
JSON
|
99
172
|
end
|
100
173
|
|
174
|
+
it '#verify_mrkl_root' do
|
175
|
+
block0 = Block.from_json(fixtures_file('rawblock-0.json'))
|
176
|
+
block1 = Block.from_json(fixtures_file('rawblock-1.json'))
|
177
|
+
block0.tx.size.should == 1
|
178
|
+
block0.verify_mrkl_root.should == true
|
179
|
+
block0.tx << block.tx.last # test against CVE-2012-2459
|
180
|
+
block0.verify_mrkl_root.should == false
|
181
|
+
block0.tx = block1.tx
|
182
|
+
block0.verify_mrkl_root.should == false
|
183
|
+
end
|
184
|
+
|
185
|
+
it '#bip34_block_height' do
|
186
|
+
# block version 1
|
187
|
+
block = Block.from_json(fixtures_file('rawblock-131025.json'))
|
188
|
+
block.ver.should == 1
|
189
|
+
block.bip34_block_height.should == nil
|
190
|
+
# block version 2 (introduced by BIP_0034)
|
191
|
+
block = Block.from_json(fixtures_file('000000000000056b1a3d84a1e2b33cde8915a4b61c0cae14fca6d3e1490b4f98.json'))
|
192
|
+
block.ver.should == 2
|
193
|
+
block.bip34_block_height.should == 197657
|
194
|
+
end
|
195
|
+
|
101
196
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require_relative '../spec_helper.rb'
|
4
|
+
|
5
|
+
describe 'Bitcoin::Protocol::Parser (getblocks)' do
|
6
|
+
|
7
|
+
class Getblocks_Handler < Bitcoin::Protocol::Handler
|
8
|
+
attr_reader :version, :locator, :stop_hash
|
9
|
+
def on_getblocks(version, locator, stop_hash)
|
10
|
+
@version, @locator, @stop_hash = version, locator, stop_hash
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
@parser = Bitcoin::Protocol::Parser.new( @handler = Getblocks_Handler.new )
|
16
|
+
@pkt = "f9beb4d9676574626c6f636b7300000065000000b3b7ad6e71110100026fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d61900000000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000000000000000000000000000000000000000000000000000000000".htb
|
17
|
+
@parser.parse(@pkt + "AAAA").should == "AAAA"
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'parses getblocks' do
|
21
|
+
@handler.version.should == 70001
|
22
|
+
@handler.locator.should == [
|
23
|
+
"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
|
24
|
+
"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f" ]
|
25
|
+
@handler.stop_hash.should == "00"*32
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'builds getblocks' do
|
29
|
+
Bitcoin::Protocol.getblocks_pkt(70001, @handler.locator).hth.should == @pkt.hth
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
1
3
|
require_relative '../spec_helper.rb'
|
2
4
|
|
3
5
|
describe 'Bitcoin::Protocol::Parser - Inventory Vectors' do
|
@@ -5,10 +7,10 @@ describe 'Bitcoin::Protocol::Parser - Inventory Vectors' do
|
|
5
7
|
class Test_Handler < Bitcoin::Protocol::Handler
|
6
8
|
attr_reader :tx_inv
|
7
9
|
attr_reader :block_inv
|
8
|
-
def on_inv_transaction(hash); (@tx_inv ||= []) << hth
|
9
|
-
def on_get_transaction(hash); (@tx_inv ||= []) << hth
|
10
|
-
def on_inv_block(hash); (@block_inv ||= []) << hth
|
11
|
-
def on_get_block(hash); (@block_inv ||= []) << hth
|
10
|
+
def on_inv_transaction(hash); (@tx_inv ||= []) << hash.hth; end
|
11
|
+
def on_get_transaction(hash); (@tx_inv ||= []) << hash.hth; end
|
12
|
+
def on_inv_block(hash); (@block_inv ||= []) << hash.hth; end
|
13
|
+
def on_get_block(hash); (@block_inv ||= []) << hash.hth; end
|
12
14
|
end
|
13
15
|
|
14
16
|
|
@@ -89,13 +91,13 @@ describe 'Bitcoin::Protocol::Parser - Inventory Vectors' do
|
|
89
91
|
|
90
92
|
locator_hashes = ["00000000068866924696f410b778911316f92035e9b69b62afa03573974fd750", "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"]
|
91
93
|
stop_hash = "0000000000000000000000000000000000000000000000000000000000000000"
|
92
|
-
pkt = Bitcoin::Protocol.getblocks_pkt( locator_hashes )
|
94
|
+
pkt = Bitcoin::Protocol.getblocks_pkt( Bitcoin.network[:protocol_version], locator_hashes )
|
93
95
|
|
94
96
|
parser = Bitcoin::Protocol::Parser.new( handler = Test_Handler.new )
|
95
97
|
parser.parse(pkt + "AAAA").should == "AAAA"
|
96
98
|
|
97
99
|
handler.pkt.should == {
|
98
|
-
:version => Bitcoin.network[:
|
100
|
+
:version => Bitcoin.network[:protocol_version],
|
99
101
|
:locator_hashes => locator_hashes,
|
100
102
|
:stop_hash => "0000000000000000000000000000000000000000000000000000000000000000"
|
101
103
|
}
|
@@ -109,13 +111,13 @@ describe 'Bitcoin::Protocol::Parser - Inventory Vectors' do
|
|
109
111
|
|
110
112
|
locator_hashes = ["00000000068866924696f410b778911316f92035e9b69b62afa03573974fd750", "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"]
|
111
113
|
stop_hash = "0000000000000000000000000000000000000000000000000000000000007e57"
|
112
|
-
pkt = Bitcoin::Protocol.getblocks_pkt( locator_hashes, stop_hash )
|
114
|
+
pkt = Bitcoin::Protocol.getblocks_pkt( Bitcoin.network[:protocol_version], locator_hashes, stop_hash )
|
113
115
|
|
114
116
|
parser = Bitcoin::Protocol::Parser.new( handler = Test_Handler.new )
|
115
117
|
parser.parse(pkt + "AAAA").should == "AAAA"
|
116
118
|
|
117
119
|
handler.pkt.should == {
|
118
|
-
:version => Bitcoin.network[:
|
120
|
+
:version => Bitcoin.network[:protocol_version],
|
119
121
|
:locator_hashes => locator_hashes,
|
120
122
|
:stop_hash => "0000000000000000000000000000000000000000000000000000000000007e57"
|
121
123
|
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require_relative '../spec_helper.rb'
|
4
|
+
|
5
|
+
describe 'Bitcoin::Protocol::Parser (notfound)' do
|
6
|
+
|
7
|
+
class Notfound_Handler < Bitcoin::Protocol::Handler
|
8
|
+
attr_reader :notfound
|
9
|
+
def on_notfound(type, hash); (@notfound ||= []) << [type, hash.hth]; end
|
10
|
+
end
|
11
|
+
|
12
|
+
before do
|
13
|
+
@parser = Bitcoin::Protocol::Parser.new( @handler = Notfound_Handler.new )
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'parses notfound block message' do
|
17
|
+
payload = "\x01\x01\x00\x00\x00:\xE2\x93bDJ\x01\xA9|\xDA>0\x8F\a\xA3L\n\xEF\x0E\xD2\xF2\xC6\xCE\xCA(\xD19}\x80*h+"
|
18
|
+
@parser.parse(Bitcoin::Protocol.pkt("notfound", payload) + "AAAA").should == "AAAA"
|
19
|
+
@handler.notfound.should == [
|
20
|
+
[:tx, "2b682a807d39d128cacec6f2d20eef0a4ca3078f303eda7ca9014a446293e23a"]
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'parses notfound tx message' do
|
25
|
+
payload = "\x01\x02\x00\x00\x00:\xE2\x93bDJ\x01\xA9|\xDA>0\x8F\a\xA3L\n\xEF\x0E\xD2\xF2\xC6\xCE\xCA(\xD19}\x80*h+"
|
26
|
+
@parser.parse(Bitcoin::Protocol.pkt("notfound", payload) + "AAAA").should == "AAAA"
|
27
|
+
@handler.notfound.should == [
|
28
|
+
[:block, "2b682a807d39d128cacec6f2d20eef0a4ca3078f303eda7ca9014a446293e23a"]
|
29
|
+
]
|
30
|
+
end
|
31
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
1
3
|
require_relative '../spec_helper.rb'
|
2
4
|
|
3
5
|
include Bitcoin::Protocol
|
@@ -101,6 +103,10 @@ describe 'Tx' do
|
|
101
103
|
tx = Tx.from_json( fixtures_file('rawtx-ba1ff5cd66713133c062a871a8adab92416f1e38d17786b2bf56ac5f6ffdfdf5.json') )
|
102
104
|
Tx.new( tx.to_payload ).to_json.should == tx.to_json
|
103
105
|
tx.hash.should == 'ba1ff5cd66713133c062a871a8adab92416f1e38d17786b2bf56ac5f6ffdfdf5'
|
106
|
+
|
107
|
+
# coinbase tx with non-default sequence
|
108
|
+
tx = Tx.from_json( json=fixtures_file('0961c660358478829505e16a1f028757e54b5bbf9758341a7546573738f31429.json'))
|
109
|
+
Tx.new( tx.to_payload ).to_json.should == json
|
104
110
|
end
|
105
111
|
|
106
112
|
it 'Tx.binary_from_json' do
|
@@ -127,6 +133,49 @@ describe 'Tx' do
|
|
127
133
|
outpoint_tx.hash.should == '406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602'
|
128
134
|
|
129
135
|
tx.verify_input_signature(0, outpoint_tx).should == true
|
136
|
+
|
137
|
+
|
138
|
+
tx = Bitcoin::Protocol::Tx.from_json(fixtures_file('0f24294a1d23efbb49c1765cf443fba7930702752aba6d765870082fe4f13cae.json'))
|
139
|
+
tx.hash.should == '0f24294a1d23efbb49c1765cf443fba7930702752aba6d765870082fe4f13cae'
|
140
|
+
outpoint_tx = Bitcoin::Protocol::Tx.from_json(fixtures_file('aea682d68a3ea5e3583e088dcbd699a5d44d4b083f02ad0aaf2598fe1fa4dfd4.json'))
|
141
|
+
outpoint_tx.hash.should == 'aea682d68a3ea5e3583e088dcbd699a5d44d4b083f02ad0aaf2598fe1fa4dfd4'
|
142
|
+
tx.verify_input_signature(0, outpoint_tx).should == true
|
143
|
+
|
144
|
+
# SIGHASH_ANYONECANPAY transaction
|
145
|
+
tx = Bitcoin::Protocol::Tx.from_json(fixtures_file('51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e.json'))
|
146
|
+
tx.hash.should == '51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e'
|
147
|
+
outpoint_tx = Bitcoin::Protocol::Tx.from_json(fixtures_file('761d8c5210fdfd505f6dff38f740ae3728eb93d7d0971fb433f685d40a4c04f6.json'))
|
148
|
+
outpoint_tx.hash.should == '761d8c5210fdfd505f6dff38f740ae3728eb93d7d0971fb433f685d40a4c04f6'
|
149
|
+
tx.verify_input_signature(0, outpoint_tx).should == true
|
150
|
+
|
151
|
+
# BIP12/OP_EVAL does't exist.
|
152
|
+
tx = Bitcoin::Protocol::Tx.from_json(fixtures_file('03d7e1fa4d5fefa169431f24f7798552861b255cd55d377066fedcd088fb0e99.json'))
|
153
|
+
tx.hash.should == '03d7e1fa4d5fefa169431f24f7798552861b255cd55d377066fedcd088fb0e99'
|
154
|
+
outpoint_tx = Bitcoin::Protocol::Tx.from_json(fixtures_file('f003f0c1193019db2497a675fd05d9f2edddf9b67c59e677c48d3dbd4ed5f00b.json'))
|
155
|
+
outpoint_tx.hash.should == 'f003f0c1193019db2497a675fd05d9f2edddf9b67c59e677c48d3dbd4ed5f00b'
|
156
|
+
tx.verify_input_signature(0, outpoint_tx).should == true
|
157
|
+
|
158
|
+
# (SIGHASH_ANYONECANPAY | SIGHASH_SINGLE) p2sh transaction
|
159
|
+
tx = Bitcoin::P::Tx.from_json(fixtures_file('7208e5edf525f04e705fb3390194e316205b8f995c8c9fcd8c6093abe04fa27d.json'))
|
160
|
+
tx.hash.should == "7208e5edf525f04e705fb3390194e316205b8f995c8c9fcd8c6093abe04fa27d"
|
161
|
+
outpoint_tx = Bitcoin::P::Tx.from_json(fixtures_file('3e58b7eed0fdb599019af08578effea25c8666bbe8e200845453cacce6314477.json'))
|
162
|
+
outpoint_tx.hash.should == "3e58b7eed0fdb599019af08578effea25c8666bbe8e200845453cacce6314477"
|
163
|
+
tx.verify_input_signature(0, outpoint_tx).should == true
|
164
|
+
|
165
|
+
# SIGHHASH_SINGLE - https://bitcointalk.org/index.php?topic=260595.0
|
166
|
+
tx = Bitcoin::P::Tx.from_json(fixtures_file('315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f.json'))
|
167
|
+
tx.hash.should == "315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f"
|
168
|
+
outpoint_tx = Bitcoin::P::Tx.from_json(fixtures_file('69216b8aaa35b76d6613e5f527f4858640d986e1046238583bdad79b35e938dc.json'))
|
169
|
+
outpoint_tx.hash.should == "69216b8aaa35b76d6613e5f527f4858640d986e1046238583bdad79b35e938dc"
|
170
|
+
tx.verify_input_signature(0, outpoint_tx).should == true
|
171
|
+
tx.verify_input_signature(1, outpoint_tx).should == true
|
172
|
+
|
173
|
+
# 0:1:01 <signature> 0:1:01 0:1:00 <pubkey> OP_SWAP OP_1ADD OP_CHECKMULTISIG
|
174
|
+
tx = Bitcoin::P::Tx.from_json(fixtures_file('cd874fa8cb0e2ec2d385735d5e1fd482c4fe648533efb4c50ee53bda58e15ae2.json'))
|
175
|
+
tx.hash.should == "cd874fa8cb0e2ec2d385735d5e1fd482c4fe648533efb4c50ee53bda58e15ae2"
|
176
|
+
outpoint_tx = Bitcoin::P::Tx.from_json(fixtures_file('514c46f0b61714092f15c8dfcb576c9f79b3f959989b98de3944b19d98832b58.json'))
|
177
|
+
outpoint_tx.hash.should == "514c46f0b61714092f15c8dfcb576c9f79b3f959989b98de3944b19d98832b58"
|
178
|
+
tx.verify_input_signature(0, outpoint_tx).should == true
|
130
179
|
end
|
131
180
|
|
132
181
|
it '#sign_input_signature' do
|
@@ -189,26 +238,17 @@ describe 'Tx' do
|
|
189
238
|
#File.open("rawtx-#{prev_tx.hash}.json",'wb'){|f| f.print prev_tx.to_json }
|
190
239
|
end
|
191
240
|
|
241
|
+
it '#calculate_minimum_fee' do
|
242
|
+
tx = Tx.new( fixtures_file('rawtx-b5d4e8883533f99e5903ea2cf001a133a322fa6b1370b18a16c57c946a40823d.bin') )
|
243
|
+
tx.minimum_relay_fee.should == 0
|
244
|
+
tx.minimum_block_fee.should == 0
|
245
|
+
tx = Tx.from_json(fixtures_file('bc179baab547b7d7c1d5d8d6f8b0cc6318eaa4b0dd0a093ad6ac7f5a1cb6b3ba.json'))
|
246
|
+
tx.minimum_relay_fee.should == 10_000
|
247
|
+
tx.minimum_block_fee.should == 50_000
|
248
|
+
end
|
192
249
|
|
193
250
|
describe "Tx - BIP Scripts" do
|
194
251
|
|
195
|
-
it "should do OP_CHECKHASHVERIFY (BIP_0017)" do # https://en.bitcoin.it/wiki/BIP_0017
|
196
|
-
# scriptSig: [signatures...] OP_CODESEPARATOR 1 [pubkey1] [pubkey2] 2 OP_CHECKMULTISIG
|
197
|
-
# scriptPubKey: [20-byte-hash of {1 [pubkey1] [pubkey2] 2 OP_CHECKMULTISIG} ] OP_CHECKHASHVERIFY OP_DROP
|
198
|
-
|
199
|
-
tx = Tx.from_json(fixtures_file('bc179baab547b7d7c1d5d8d6f8b0cc6318eaa4b0dd0a093ad6ac7f5a1cb6b3ba.json'))
|
200
|
-
tx.hash.should == "bc179baab547b7d7c1d5d8d6f8b0cc6318eaa4b0dd0a093ad6ac7f5a1cb6b3ba"
|
201
|
-
|
202
|
-
prev_tx1 = Tx.from_json(fixtures_file('477fff140b363ec2cc51f3a65c0c58eda38f4d41f04a295bbd62babf25e4c590.json'))
|
203
|
-
prev_tx1.hash.should == "477fff140b363ec2cc51f3a65c0c58eda38f4d41f04a295bbd62babf25e4c590"
|
204
|
-
|
205
|
-
prev_tx2 = Tx.from_json(fixtures_file('0d0affb5964abe804ffe85e53f1dbb9f29e406aa3046e2db04fba240e63c7fdd.json'))
|
206
|
-
prev_tx2.hash.should == "0d0affb5964abe804ffe85e53f1dbb9f29e406aa3046e2db04fba240e63c7fdd"
|
207
|
-
|
208
|
-
tx.verify_input_signature(0, prev_tx1).should == true
|
209
|
-
tx.verify_input_signature(1, prev_tx2).should == true
|
210
|
-
end
|
211
|
-
|
212
252
|
it "should do OP_CHECKMULTISIG" do
|
213
253
|
# checkmultisig without checkhashverify
|
214
254
|
tx = Tx.from_json(fixtures_file('23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63.json'))
|
@@ -221,6 +261,32 @@ describe 'Tx' do
|
|
221
261
|
tx.verify_input_signature(0, prev_tx).should == true
|
222
262
|
end
|
223
263
|
|
264
|
+
it "should do P2SH with inner OP_CHECKMULTISIG (BIP 0016)" do
|
265
|
+
tx = Tx.from_json(fixtures_file('3a17dace09ffb919ed627a93f1873220f4c975c1248558b18d16bce25d38c4b7.json'))
|
266
|
+
prev_tx = Tx.from_json(fixtures_file('35e2001b428891fefa0bfb73167c7360669d3cbd7b3aa78e7cad125ddfc51131.json'))
|
267
|
+
tx.verify_input_signature(0, prev_tx).should == true
|
268
|
+
|
269
|
+
tx = Tx.from_json(fixtures_file('bd1715f1abfdc62bea3f605bdb461b3ba1f2cca6ec0d73a18a548b7717ca8531.json'))
|
270
|
+
prev_tx = Tx.from_json(fixtures_file('ce5fad9b4ef094d8f4937b0707edaf0a6e6ceeaf67d5edbfd51f660eac8f398b.json'))
|
271
|
+
tx.verify_input_signature(1, prev_tx).should == true
|
272
|
+
|
273
|
+
# p2sh transaction with non-standard OP_CHECKMULTISIG inside found in testnet3 tx: d3d77d63709e47d9ef58f0b557800115a6b676c6a423012fbb96f45d8fcef830
|
274
|
+
tx = Bitcoin::P::Tx.from_json(fixtures_file('tx-d3d77d63709e47d9ef58f0b557800115a6b676c6a423012fbb96f45d8fcef830.json'))
|
275
|
+
tx.hash.should == "d3d77d63709e47d9ef58f0b557800115a6b676c6a423012fbb96f45d8fcef830"
|
276
|
+
prev_tx = Bitcoin::P::Tx.from_json(fixtures_file('tx-313897799b1e37e9ecae15010e56156dddde4e683c96b0e713af95272c38aee0.json'))
|
277
|
+
prev_tx.hash.should == "313897799b1e37e9ecae15010e56156dddde4e683c96b0e713af95272c38aee0"
|
278
|
+
tx.verify_input_signature(0, prev_tx).should == true
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should do P2SH with inner OP_CHECKSIG" do
|
282
|
+
# p2sh transaction with non-standard OP_CHECKSIG inside found in testnet3 tx: 3da75972766f0ad13319b0b461fd16823a731e44f6e9de4eb3c52d6a6fb6c8ae
|
283
|
+
tx = Bitcoin::P::Tx.from_json(fixtures_file('tx-3da75972766f0ad13319b0b461fd16823a731e44f6e9de4eb3c52d6a6fb6c8ae.json'))
|
284
|
+
tx.hash.should == "3da75972766f0ad13319b0b461fd16823a731e44f6e9de4eb3c52d6a6fb6c8ae"
|
285
|
+
prev_tx = Bitcoin::P::Tx.from_json(fixtures_file('tx-44b833074e671120ba33106877b49e86ece510824b9af477a3853972bcd8d06a.json'))
|
286
|
+
prev_tx.hash.should == "44b833074e671120ba33106877b49e86ece510824b9af477a3853972bcd8d06a"
|
287
|
+
tx.verify_input_signature(0, prev_tx).should == true
|
288
|
+
end
|
289
|
+
|
224
290
|
end
|
225
291
|
|
226
292
|
end
|