bitcoin-ruby 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/.travis.yml +2 -7
- data/COPYING +1 -1
- data/Gemfile +2 -6
- data/Gemfile.lock +34 -0
- data/README.rdoc +16 -68
- data/Rakefile +3 -6
- data/bin/bitcoin_shell +0 -1
- data/{concept-examples/blockchain-pow.rb → examples/concept-blockchain-pow.rb} +0 -0
- data/lib/bitcoin.rb +350 -296
- data/lib/bitcoin/builder.rb +3 -1
- data/lib/bitcoin/connection.rb +2 -1
- data/lib/bitcoin/contracthash.rb +76 -0
- data/lib/bitcoin/dogecoin.rb +97 -0
- data/lib/bitcoin/ffi/bitcoinconsensus.rb +74 -0
- data/lib/bitcoin/ffi/openssl.rb +98 -2
- data/lib/bitcoin/ffi/secp256k1.rb +144 -0
- data/lib/bitcoin/key.rb +12 -2
- data/lib/bitcoin/logger.rb +3 -12
- data/lib/bitcoin/protocol/block.rb +3 -9
- data/lib/bitcoin/protocol/parser.rb +6 -2
- data/lib/bitcoin/protocol/tx.rb +44 -13
- data/lib/bitcoin/protocol/txin.rb +4 -2
- data/lib/bitcoin/protocol/txout.rb +2 -2
- data/lib/bitcoin/script.rb +212 -37
- data/lib/bitcoin/trezor/mnemonic.rb +130 -0
- data/lib/bitcoin/version.rb +1 -1
- data/spec/bitcoin/bitcoin_spec.rb +32 -3
- data/spec/bitcoin/builder_spec.rb +18 -0
- data/spec/bitcoin/contracthash_spec.rb +45 -0
- data/spec/bitcoin/dogecoin_spec.rb +176 -0
- data/spec/bitcoin/ffi_openssl.rb +45 -0
- data/spec/bitcoin/fixtures/156e6e1b84c5c3bd3a0927b25e4119fadce6e6d5186f363317511d1d680fae9a.json +24 -0
- data/spec/bitcoin/fixtures/8d0b238a06b5a70be75d543902d02d7a514d68d3252a949a513865ac3538874c.json +24 -0
- data/spec/bitcoin/fixtures/coinbase-toshi.json +33 -0
- data/spec/bitcoin/fixtures/coinbase.json +24 -0
- data/spec/bitcoin/fixtures/dogecoin-block-60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-01-toshi.json +46 -0
- data/spec/bitcoin/fixtures/rawtx-02-toshi.json +46 -0
- data/spec/bitcoin/fixtures/rawtx-03-toshi.json +73 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-04fdc38d6722ab4b12d79113fc4b2896bdcc5169710690ee4e78541b98e467b4.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-0b294c7d11dd21bcccb8393e6744fed7d4d1981a08c00e3e88838cc421f33c9f.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-3bc52ac063291ad92d95ddda5fd776a342083b95607ad32ed8bc6f8f7d30449e.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-6f0bbdd4e71a8af4305018d738184df32dbb6f27284fdebd5b56d16947f7c181.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-a7c9b06e275e8674cc19a5f7d3e557c72c6d93576e635b33212dbe08ab7cdb60.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-f80acbd2f594d04ddb0e1cacba662132104909157dff526935a3c88abe9201a5.bin +0 -0
- data/spec/bitcoin/protocol/block_spec.rb +0 -22
- data/spec/bitcoin/protocol/tx_spec.rb +145 -2
- data/spec/bitcoin/script/script_spec.rb +282 -0
- data/spec/bitcoin/secp256k1_spec.rb +48 -0
- data/spec/bitcoin/spec_helper.rb +0 -51
- data/spec/bitcoin/trezor/mnemonic_spec.rb +161 -0
- metadata +48 -98
- data/bin/bitcoin_dns_seed +0 -130
- data/bin/bitcoin_gui +0 -80
- data/bin/bitcoin_node +0 -153
- data/bin/bitcoin_node_cli +0 -81
- data/bin/bitcoin_wallet +0 -402
- data/doc/CONFIG.rdoc +0 -66
- data/doc/EXAMPLES.rdoc +0 -13
- data/doc/NAMECOIN.rdoc +0 -34
- data/doc/NODE.rdoc +0 -225
- data/doc/STORAGE.rdoc +0 -33
- data/doc/WALLET.rdoc +0 -102
- data/examples/balance.rb +0 -66
- data/examples/forwarder.rb +0 -73
- data/examples/index_nhash.rb +0 -24
- data/examples/reindex_p2sh_addrs.rb +0 -44
- data/examples/relay_tx.rb +0 -22
- data/examples/verify_tx.rb +0 -57
- data/lib/bitcoin/config.rb +0 -58
- data/lib/bitcoin/gui/addr_view.rb +0 -44
- data/lib/bitcoin/gui/bitcoin-ruby.png +0 -0
- data/lib/bitcoin/gui/bitcoin-ruby.svg +0 -80
- data/lib/bitcoin/gui/conn_view.rb +0 -38
- data/lib/bitcoin/gui/connection.rb +0 -70
- data/lib/bitcoin/gui/em_gtk.rb +0 -30
- data/lib/bitcoin/gui/gui.builder +0 -1643
- data/lib/bitcoin/gui/gui.rb +0 -292
- data/lib/bitcoin/gui/helpers.rb +0 -115
- data/lib/bitcoin/gui/tree_view.rb +0 -84
- data/lib/bitcoin/gui/tx_view.rb +0 -69
- data/lib/bitcoin/namecoin.rb +0 -280
- data/lib/bitcoin/network/command_client.rb +0 -104
- data/lib/bitcoin/network/command_handler.rb +0 -570
- data/lib/bitcoin/network/connection_handler.rb +0 -387
- data/lib/bitcoin/network/node.rb +0 -565
- data/lib/bitcoin/storage/dummy/dummy_store.rb +0 -179
- data/lib/bitcoin/storage/models.rb +0 -171
- data/lib/bitcoin/storage/sequel/migrations.rb +0 -99
- data/lib/bitcoin/storage/sequel/migrations/001_base_schema.rb +0 -52
- data/lib/bitcoin/storage/sequel/migrations/002_tx.rb +0 -45
- data/lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb +0 -18
- data/lib/bitcoin/storage/sequel/migrations/004_change_txin_prev_out_to_blob.rb +0 -18
- data/lib/bitcoin/storage/sequel/migrations/005_change_tx_hash_to_bytea.rb +0 -14
- data/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb +0 -31
- data/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb +0 -16
- data/lib/bitcoin/storage/sequel/migrations/008_add_txin_p2sh_type.rb +0 -31
- data/lib/bitcoin/storage/sequel/migrations/009_add_addrs_type.rb +0 -56
- data/lib/bitcoin/storage/sequel/sequel_store.rb +0 -551
- data/lib/bitcoin/storage/storage.rb +0 -517
- data/lib/bitcoin/storage/utxo/migrations/001_base_schema.rb +0 -52
- data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +0 -18
- data/lib/bitcoin/storage/utxo/migrations/003_update_indices.rb +0 -14
- data/lib/bitcoin/storage/utxo/migrations/004_add_addrs_type.rb +0 -14
- data/lib/bitcoin/storage/utxo/utxo_store.rb +0 -374
- data/lib/bitcoin/validation.rb +0 -400
- data/lib/bitcoin/wallet/coinselector.rb +0 -33
- data/lib/bitcoin/wallet/keygenerator.rb +0 -77
- data/lib/bitcoin/wallet/keystore.rb +0 -207
- data/lib/bitcoin/wallet/txdp.rb +0 -118
- data/lib/bitcoin/wallet/wallet.rb +0 -281
- data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.bin +0 -0
- data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.json +0 -43
- data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.bin +0 -0
- data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.json +0 -67
- data/spec/bitcoin/namecoin_spec.rb +0 -182
- data/spec/bitcoin/node/command_api_spec.rb +0 -663
- data/spec/bitcoin/storage/models_spec.rb +0 -104
- data/spec/bitcoin/storage/reorg_spec.rb +0 -236
- data/spec/bitcoin/storage/storage_spec.rb +0 -387
- data/spec/bitcoin/storage/validation_spec.rb +0 -300
- data/spec/bitcoin/wallet/coinselector_spec.rb +0 -38
- data/spec/bitcoin/wallet/keygenerator_spec.rb +0 -69
- data/spec/bitcoin/wallet/keystore_spec.rb +0 -190
- data/spec/bitcoin/wallet/txdp_spec.rb +0 -76
- data/spec/bitcoin/wallet/wallet_spec.rb +0 -238
Binary file
|
@@ -1,43 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"hash":"000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c",
|
3
|
-
"ver":2,
|
4
|
-
"prev_block":"000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c",
|
5
|
-
"mrkl_root":"a0b9ec1d860e0786b0be7380eac76fe6180ca98b20aa03c08097bda1fbbce895",
|
6
|
-
"time":1356123634,
|
7
|
-
"bits":486604799,
|
8
|
-
"nonce":2536343301,
|
9
|
-
"n_tx":1,
|
10
|
-
"size":220,
|
11
|
-
"tx":[
|
12
|
-
{
|
13
|
-
"hash":"898cf5a16a1a40342fb193d0ec5dd9de13951c6121b95be96d88042d1e7fcc66",
|
14
|
-
"ver":2,
|
15
|
-
"vin_sz":1,
|
16
|
-
"vout_sz":2,
|
17
|
-
"lock_time":0,
|
18
|
-
"size":139,
|
19
|
-
"in":[
|
20
|
-
{
|
21
|
-
"prev_out":{
|
22
|
-
"hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
23
|
-
"n":4294967295
|
24
|
-
},
|
25
|
-
"coinbase":"51010f062f503253482f"
|
26
|
-
}
|
27
|
-
],
|
28
|
-
"out":[
|
29
|
-
{
|
30
|
-
"value":"254.53572875",
|
31
|
-
"scriptPubKey":"036c370a402c3e50063d3abd46d49ad174aae679bdc25f2a4ce5a3a4ca15b8b86e OP_CHECKSIG"
|
32
|
-
},
|
33
|
-
{
|
34
|
-
"value":"496.03174604",
|
35
|
-
"scriptPubKey":"OP_DUP OP_HASH160 85e54144c4020a65fa0a8fdbac8bba75dbc2fd00 OP_EQUALVERIFY OP_CHECKSIG"
|
36
|
-
}
|
37
|
-
]
|
38
|
-
}
|
39
|
-
],
|
40
|
-
"mrkl_tree":[
|
41
|
-
"898cf5a16a1a40342fb193d0ec5dd9de13951c6121b95be96d88042d1e7fcc66"
|
42
|
-
]
|
43
|
-
}
|
Binary file
|
@@ -1,67 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"hash":"000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c",
|
3
|
-
"ver":1,
|
4
|
-
"prev_block":"0000000000000000000000000000000000000000000000000000000000000000",
|
5
|
-
"mrkl_root":"f53b1baa971ea40be88cf51288aabd700dfec96c486bf7155a53a4919af4c8bd",
|
6
|
-
"time":1356123600,
|
7
|
-
"bits":486604799,
|
8
|
-
"nonce":278229610,
|
9
|
-
"n_tx":1,
|
10
|
-
"size":1374,
|
11
|
-
"tx":[
|
12
|
-
{
|
13
|
-
"hash":"cfc428c86c94c63341d5466b214afd01f3fa4db9471831c233138a257601b102",
|
14
|
-
"ver":2,
|
15
|
-
"vin_sz":1,
|
16
|
-
"vout_sz":8,
|
17
|
-
"lock_time":0,
|
18
|
-
"size":1293,
|
19
|
-
"in":[
|
20
|
-
{
|
21
|
-
"prev_out":{
|
22
|
-
"hash":"0000000000000000000000000000000000000000000000000000000000000000",
|
23
|
-
"n":4294967295
|
24
|
-
},
|
25
|
-
"coinbase":"04ffff001d01044554656c6567726170682032372f4a756e2f3230313220426172636c61797320686974207769746820c2a33239306d2066696e65206f766572204c69626f7220666978696e67"
|
26
|
-
}
|
27
|
-
],
|
28
|
-
"out":[
|
29
|
-
{
|
30
|
-
"value":"254.53671561",
|
31
|
-
"scriptPubKey":"04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG"
|
32
|
-
},
|
33
|
-
{
|
34
|
-
"value":"0.00000001",
|
35
|
-
"scriptPubKey":"5029d180e0c5ed798d877b1ada99772986c1422ca932c41b2d04000000000000 OP_DROP 0"
|
36
|
-
},
|
37
|
-
{
|
38
|
-
"value":"0.00000001",
|
39
|
-
"scriptPubKey":"202020 OP_DROP 4d6574616c73207765726520616e20696d706c696369746c7920616275736976652061677265656d656e742e0a4d6f6465726e2022706170657222206973206120666c6177656420746f6f6c2c2069747320656e67696e656572696e672069732061206e657374206f66206c6565636865732e0a546865206f6c64206d6f6e6579206973206f62736f6c6574652e0a4c65742074686520696e646976696475616c206d6f6e6574697a65206974732063726564697420776974686f75742063617274656c20696e7465726d65646961726965732e0a4769766520757320612072656e742d6c657373206361736820736f2077652063616e206265206672656520666f72207468652066697273742074696d652e0a4c65742074686973206265207468652061776169746564206461776e2e OP_DROP OP_DUP OP_HASH160 0ef0f9d19a653023554146a866238b8822bc84df OP_EQUALVERIFY OP_CHECKSIG"
|
40
|
-
},
|
41
|
-
{
|
42
|
-
"value":"0.00000001",
|
43
|
-
"scriptPubKey":"2020202020202020 OP_DROP 224c65742075732063616c63756c6174652c20776974686f757420667572746865722061646f2c20696e206f7264657220746f207365652077686f2069732072696768742e22202d2d476f747466726965642057696c68656c6d204c6569626e697a0acebec2b4efbda5e28880efbda560efbc89e38080e38080e38080e3808020206e0aefbfa3e38080e38080e380802020efbcbce38080e380802020efbc882045efbc8920676f6f64206a6f622c206d61616b75210aefbe8ce38080e38080e3808020202fe383bd20e383bd5fefbc8fefbc8f OP_DROP OP_DUP OP_HASH160 c26be5ec809aa4bf6b30aa89823cff7cedc3679a OP_EQUALVERIFY OP_CHECKSIG"
|
44
|
-
},
|
45
|
-
{
|
46
|
-
"value":"0.00000001",
|
47
|
-
"scriptPubKey":"202020202020 OP_DROP 4963682077c3bc6e736368652046726569636f696e207669656c204572666f6c67207a756d204e75747a656e206465722039392050726f7a656e7421 OP_DROP OP_DUP OP_HASH160 2939acd60037281a708eb11e4e9eda452c029eca OP_EQUALVERIFY OP_CHECKSIG"
|
48
|
-
},
|
49
|
-
{
|
50
|
-
"value":"0.00000001",
|
51
|
-
"scriptPubKey":"20202020202020202020202020 OP_DROP 225468652076616c7565206f662061206d616e2073686f756c64206265207365656e20696e207768617420686520676976657320616e64206e6f7420696e20776861742068652069732061626c6520746f20726563656976652e22202d2d416c626572742045696e737465696e OP_DROP OP_DUP OP_HASH160 f9ca5caab4bda4dc28b5556aa79a2eec0447f0bf OP_EQUALVERIFY OP_CHECKSIG"
|
52
|
-
},
|
53
|
-
{
|
54
|
-
"value":"0.00000001",
|
55
|
-
"scriptPubKey":"202020202020202020202020 OP_DROP 22416e2061726d79206f66207072696e6369706c65732063616e2070656e65747261746520776865726520616e2061726d79206f6620736f6c64696572732063616e6e6f742e22202d2d54686f6d6173205061696e65 OP_DROP OP_DUP OP_HASH160 08f320cbb41a1ae25b794f6175f96080681989f3 OP_EQUALVERIFY OP_CHECKSIG"
|
56
|
-
},
|
57
|
-
{
|
58
|
-
"value":"496.03174604",
|
59
|
-
"scriptPubKey":"OP_DUP OP_HASH160 85e54144c4020a65fa0a8fdbac8bba75dbc2fd00 OP_EQUALVERIFY OP_CHECKSIG"
|
60
|
-
}
|
61
|
-
]
|
62
|
-
}
|
63
|
-
],
|
64
|
-
"mrkl_tree":[
|
65
|
-
"cfc428c86c94c63341d5466b214afd01f3fa4db9471831c233138a257601b102"
|
66
|
-
]
|
67
|
-
}
|
@@ -1,182 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
|
3
|
-
require_relative 'spec_helper.rb'
|
4
|
-
require 'bitcoin/script'
|
5
|
-
|
6
|
-
include Bitcoin
|
7
|
-
include Bitcoin::Builder
|
8
|
-
|
9
|
-
describe 'Bitcoin::Namecoin' do
|
10
|
-
|
11
|
-
describe :script do
|
12
|
-
|
13
|
-
before do
|
14
|
-
Bitcoin.network = :namecoin
|
15
|
-
@name_new = Script.from_string("3045022023686b3584247c07f483de4048f3d5136c4faa2f961a6d1e487eb77437422b51022100b1ea62910f2dbb0533d32bd661e8a212d129057d3d71620572278895dbb5c7b501
|
16
|
-
04b656d7be83e73344e298feba41b38c52ea50d4583ead0c947fd8019f75c906e0d810c5d167ee616c46d28d7cb5ca1d7a20a180470c9dad79524118bafe6cf569 1 820fa9c6d252d6773e4ef26a2feffa93f0237641 OP_2DROP OP_DUP OP_HASH160 eb86f8f23909e248d199192d8407881c3435a5db OP_EQUALVERIFY OP_CHECKSIG")
|
17
|
-
@name_firstupdate = Script.from_string("3044022054e1557304c504498f8d40b961373d7401a4e4c1650518db8a9c3a49ee9add7e022061573b2837598c346b21c01969081a309c055d5da23b0ac7e139a6290f2f0a4b01
|
18
|
-
04d2628245cdfc6ccf5a762d303ba8a10bd54d597cfdcbf0ac3823bae666a36bb744ed44a2384f42525e37b5b1150c5321718806c0f941904336588dd624f4ce93 2 642f626974636f696e a8c22832fb0d40e900 7b22696e666f223a7b22726567697374726172223a22687474703a2f2f72656769737465722e646f742d6269742e6f7267227d2c22656d61696c223a2022726567697374657240646f742d6269742e6f7267222c226e73223a5b226e73302e7765622d73776565742d7765622e6e6574222c226e73312e7765622d73776565742d7765622e6e6574225d2c226d6170223a7b22223a7b226e73223a5b226e73302e7765622d73776565742d7765622e6e6574222c226e73312e7765622d73776565742d7765622e6e6574225d7d7d7d OP_2DROP OP_2DROP OP_DUP OP_HASH160 f3f4aee9d80da759a4a3547cf6aa95c09881decb OP_EQUALVERIFY OP_CHECKSIG")
|
19
|
-
@name_update = Script.from_string("304402206a8598a87aadd697732d0a187220023e2b54e542e144d0dee67660c8ca3d66f4022000de36f02afb9162f2d27e947d452d4e28baadfdb21637db2b1f252ad62d7fb201
|
20
|
-
04b61d1529dbe912c84d0de898e88ab8a9d9fa4a13e76e7b60419dd3bd2b72021842bbf0f5eba1001d55f0c6f2c255289bedbe843d0164b545bbc056f150b4c3f2 3 642f626974636f696e 7b22696e666f223a7b22726567697374726172223a22687474703a2f2f72656769737465722e646f742d6269742e6f7267227d2c22656d61696c223a2022726567697374657240646f742d6269742e6f7267222c226e73223a5b226e73302e7765622d73776565742d7765622e6e6574222c226e73312e7765622d73776565742d7765622e6e6574225d2c226d6170223a7b22223a7b226e73223a5b226e73302e7765622d73776565742d7765622e6e6574222c226e73312e7765622d73776565742d7765622e6e6574225d7d7d7d OP_2DROP OP_DROP OP_DUP OP_HASH160 8f29c40b89ceda0b9176819e2bb5a15f592c6548 OP_EQUALVERIFY OP_CHECKSIG")
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'should parse name_new script' do
|
24
|
-
@name_new.is_name_new?.should == true
|
25
|
-
@name_firstupdate.is_name_new?.should == false
|
26
|
-
@name_update.is_name_new?.should == false
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'should parse name_firstupdate script' do
|
30
|
-
@name_new.is_name_firstupdate?.should == false
|
31
|
-
@name_firstupdate.is_name_firstupdate?.should == true
|
32
|
-
@name_update.is_name_firstupdate?.should == false
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'should parse name_update script' do
|
36
|
-
@name_new.is_name_update?.should == false
|
37
|
-
@name_firstupdate.is_name_update?.should == false
|
38
|
-
@name_update.is_name_update?.should == true
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'should run scripts' do
|
42
|
-
@name_new.run { true }.should == true
|
43
|
-
@name_firstupdate.run { true }.should == true
|
44
|
-
@name_update.run { true }.should == true
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'should get name_hash' do
|
48
|
-
@name_new.get_namecoin_hash.should == "820fa9c6d252d6773e4ef26a2feffa93f0237641"
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'should get name' do
|
52
|
-
@name_firstupdate.get_namecoin_name.should == "d/bitcoin"
|
53
|
-
@name_update.get_namecoin_name.should == "d/bitcoin"
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'should get value' do
|
57
|
-
@name_firstupdate.get_namecoin_value.should == '{"info":{"registrar":"http://register.dot-bit.org"},"email": "register@dot-bit.org","ns":["ns0.web-sweet-web.net","ns1.web-sweet-web.net"],"map":{"":{"ns":["ns0.web-sweet-web.net","ns1.web-sweet-web.net"]}}}'
|
58
|
-
@name_update.get_namecoin_value.should == @name_firstupdate.get_namecoin_value
|
59
|
-
end
|
60
|
-
|
61
|
-
def set_rand rand; @rand = rand; end
|
62
|
-
|
63
|
-
it 'should create scripts' do
|
64
|
-
key = Key.generate
|
65
|
-
script = Script.to_name_new_script(self, "test/foo", key.addr)
|
66
|
-
Script.new(script).to_string.should =~
|
67
|
-
/^1 (.*?) OP_2DROP OP_DUP OP_HASH160 #{key.hash160} OP_EQUALVERIFY OP_CHECKSIG$/
|
68
|
-
@rand.should != nil
|
69
|
-
|
70
|
-
script = Script.to_name_firstupdate_script("test/foo", "1234", "testing", key.addr)
|
71
|
-
Script.new(script).to_string.should ==
|
72
|
-
"2 746573742f666f6f 1234 74657374696e67 OP_2DROP OP_2DROP " +
|
73
|
-
"OP_DUP OP_HASH160 #{key.hash160} OP_EQUALVERIFY OP_CHECKSIG"
|
74
|
-
|
75
|
-
script = Script.to_name_update_script("test/foo", "more testing", key.addr)
|
76
|
-
Script.new(script).to_string.should ==
|
77
|
-
"3 746573742f666f6f 6d6f72652074657374696e67 OP_2DROP OP_DROP " +
|
78
|
-
"OP_DUP OP_HASH160 #{key.hash160} OP_EQUALVERIFY OP_CHECKSIG"
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
[
|
84
|
-
{ :name => :utxo, :db => 'sqlite:/', utxo_cache: 0 },
|
85
|
-
{ :name => :sequel, :db => 'sqlite:/' },
|
86
|
-
].each do |configuration|
|
87
|
-
|
88
|
-
describe "Namecoin (#{configuration[:name]} store)" do
|
89
|
-
|
90
|
-
before do
|
91
|
-
Bitcoin.network = :namecoin
|
92
|
-
Bitcoin.network[:no_difficulty] = true
|
93
|
-
class Bitcoin::Validation::Block; def min_timestamp; true; end; end
|
94
|
-
Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("ff"*32)
|
95
|
-
[:name_new, :name_firstupdate, :name_update].each {|type|
|
96
|
-
Bitcoin::Storage::Backends::SequelStore::SCRIPT_TYPES << type }
|
97
|
-
@store = Bitcoin::Storage.send(configuration[:name], configuration)
|
98
|
-
@store.reset
|
99
|
-
@store.log.level = :error
|
100
|
-
@key = Bitcoin::Key.generate
|
101
|
-
@block = create_block "00"*32, false, [], @key
|
102
|
-
Bitcoin.network[:genesis_hash] = @block.hash
|
103
|
-
@store.store_block(@block)
|
104
|
-
end
|
105
|
-
|
106
|
-
def set_rand r; @rand = r; end
|
107
|
-
|
108
|
-
it "should store names" do
|
109
|
-
# create name_new
|
110
|
-
@block = create_block @block.hash, true, [->(t) {
|
111
|
-
t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key }
|
112
|
-
t.output {|o| o.value 50e8; o.script {|s| s.type(:name_new)
|
113
|
-
s.recipient(self, "test", @key.addr) } } }], @key
|
114
|
-
@store.db[:names][hash: Bitcoin.hash160(@rand + "test".hth)].should != nil
|
115
|
-
|
116
|
-
# name_firstupdate should not be valid yet
|
117
|
-
@block = create_block @block.hash, true, [->(t) {
|
118
|
-
t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key }
|
119
|
-
t.output {|o| o.value 50e8; o.script {|s| s.type(:name_firstupdate)
|
120
|
-
s.recipient("test", @rand, "testvalue", @key.addr) } } }], @key
|
121
|
-
@store.name_show("test").should == nil
|
122
|
-
|
123
|
-
# create enough blocks for name_new to become valid
|
124
|
-
Namecoin::FIRSTUPDATE_LIMIT.times {
|
125
|
-
@block = create_block @block.hash, true, [], @key }
|
126
|
-
|
127
|
-
# name_firstupdate should be valid now
|
128
|
-
@block = create_block @block.hash, true, [->(t) {
|
129
|
-
t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key }
|
130
|
-
t.output {|o| o.value 50e8; o.script {|s|; s.type(:name_firstupdate)
|
131
|
-
s.recipient("test", @rand, "testvalue", @key.addr) } } }], @key
|
132
|
-
|
133
|
-
name = @store.name_show("test")
|
134
|
-
name.get_address.should == @key.addr
|
135
|
-
name.name.should == "test"
|
136
|
-
name.value.should == "testvalue"
|
137
|
-
name.hash.should == Bitcoin.hash160(@rand + "test".hth)
|
138
|
-
|
139
|
-
# create name_update
|
140
|
-
@new_key = Bitcoin::Key.generate
|
141
|
-
@block = create_block @block.hash, true, [->(t) {
|
142
|
-
t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key}
|
143
|
-
t.output {|o|o.value 50e8; o.script {|s| s.type(:name_update)
|
144
|
-
s.recipient("test", "testupdate", @new_key.addr) } } }], @new_key
|
145
|
-
|
146
|
-
name = @store.name_show("test")
|
147
|
-
name.get_address.should == @new_key.addr
|
148
|
-
name.value.should == "testupdate"
|
149
|
-
|
150
|
-
h = @store.name_history("test")
|
151
|
-
h.size.should == 2
|
152
|
-
h[0].value.should == "testvalue"
|
153
|
-
h[0].get_address.should == @key.addr
|
154
|
-
h[1].value.should == "testupdate"
|
155
|
-
h[1].get_address.should == @new_key.addr
|
156
|
-
end
|
157
|
-
|
158
|
-
it "should expire names" do
|
159
|
-
@block = create_block @block.hash, true, [->(t) {
|
160
|
-
t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key }
|
161
|
-
t.output {|o| o.value 50e8; o.script {|s| s.type(:name_new)
|
162
|
-
s.recipient(self, "test", @key.addr) } } }], @key
|
163
|
-
@store.db[:names][hash: Bitcoin.hash160(@rand + "test".hth)].should != nil
|
164
|
-
|
165
|
-
# create enough blocks for name_new to become valid
|
166
|
-
Namecoin::FIRSTUPDATE_LIMIT.times {
|
167
|
-
@block = create_block @block.hash, true, [], @key }
|
168
|
-
|
169
|
-
# name_firstupdate should be valid now
|
170
|
-
@block = create_block @block.hash, true, [->(t) {
|
171
|
-
t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key }
|
172
|
-
t.output {|o| o.value 50e8; o.script {|s|; s.type(:name_firstupdate)
|
173
|
-
s.recipient("test", @rand, "testvalue", @key.addr) } } }], @key
|
174
|
-
|
175
|
-
@store.name_show("test").expires_in.should == Namecoin::EXPIRATION_DEPTH
|
176
|
-
@block = create_block @block.hash, true, [], @key
|
177
|
-
@store.name_show("test").expires_in.should == Namecoin::EXPIRATION_DEPTH - 1
|
178
|
-
end
|
179
|
-
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
@@ -1,663 +0,0 @@
|
|
1
|
-
require_relative '../spec_helper.rb'
|
2
|
-
|
3
|
-
include Bitcoin
|
4
|
-
include Builder
|
5
|
-
|
6
|
-
class Array
|
7
|
-
def stringify_keys
|
8
|
-
map do |e|
|
9
|
-
(e.is_a?(Array) || e.is_a?(Hash)) ? e.stringify_keys : e
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class Hash
|
15
|
-
def stringify_keys
|
16
|
-
Hash[map do |k, v|
|
17
|
-
v = v.stringify_keys if v.is_a?(Hash) || v.is_a?(Array)
|
18
|
-
[k.to_s, v]
|
19
|
-
end]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe 'Node Command API' do
|
24
|
-
|
25
|
-
TSLB_TIMEOUT = 3
|
26
|
-
|
27
|
-
def test_command command, params = nil, response = nil, &block
|
28
|
-
$responses = {}
|
29
|
-
EM.run do
|
30
|
-
@client = Bitcoin::Network::CommandClient.connect(*@config[:command]) do
|
31
|
-
on_connected do
|
32
|
-
request(command, params)
|
33
|
-
end
|
34
|
-
on_response do |cmd, data|
|
35
|
-
$responses[cmd] = data
|
36
|
-
EM.stop
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
result = $responses[command]
|
42
|
-
|
43
|
-
return result unless response || block
|
44
|
-
|
45
|
-
if block
|
46
|
-
block.call(result)
|
47
|
-
else
|
48
|
-
raise "ERROR: #{result} != #{response}" unless result.should == response
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
|
53
|
-
before do
|
54
|
-
Bitcoin::Validation::Block::RULES.merge({
|
55
|
-
syntax: [:hash, :tx_list, :bits, :max_timestamp, :coinbase, :coinbase_scriptsig, :transactions_syntax],
|
56
|
-
context: [:prev_hash, :coinbase_value, :min_timestamp, :transactions_context]
|
57
|
-
})
|
58
|
-
|
59
|
-
Bitcoin.network = :spec
|
60
|
-
@config = {
|
61
|
-
listen: ["127.0.0.1", 38333],
|
62
|
-
command: ["127.0.0.1", 38332],
|
63
|
-
storage: "sequel::sqlite:/",
|
64
|
-
dns: false,
|
65
|
-
intervals: { queue: 0.01 },
|
66
|
-
log: { network: :warn, storage: :warn },
|
67
|
-
}
|
68
|
-
|
69
|
-
@node = Bitcoin::Network::Node.new(@config)
|
70
|
-
@pid = fork do
|
71
|
-
# $stdout = StringIO.new
|
72
|
-
SimpleCov.running = false if defined?(SimpleCov)
|
73
|
-
@node.run
|
74
|
-
end
|
75
|
-
|
76
|
-
@genesis = P::Block.new("0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".htb)
|
77
|
-
|
78
|
-
Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("ff"*32)
|
79
|
-
@key = Bitcoin::Key.generate
|
80
|
-
@block = create_block @genesis.hash, false, [], @key
|
81
|
-
|
82
|
-
test_command "store_block", hex: @genesis.to_payload.hth
|
83
|
-
sleep 0.1
|
84
|
-
|
85
|
-
@id = 0
|
86
|
-
end
|
87
|
-
|
88
|
-
after do
|
89
|
-
Process.kill("TERM", @pid)
|
90
|
-
end
|
91
|
-
|
92
|
-
it "should return error for unknown command" do
|
93
|
-
test_command("foo", nil, {"error" => "unknown command: foo. send 'help' for help."})
|
94
|
-
end
|
95
|
-
|
96
|
-
# it "should return error for wrong parameters" do
|
97
|
-
# test_command("info", "foo", {"error" => "wrong number of arguments (1 for 0)"})
|
98
|
-
# end
|
99
|
-
|
100
|
-
it "should query tslb" do
|
101
|
-
test_command("tslb") {|r| (0..TSLB_TIMEOUT).include?(r['tslb']).should == true }
|
102
|
-
end
|
103
|
-
|
104
|
-
it "should query info" do
|
105
|
-
info = test_command "info"
|
106
|
-
info.is_a?(Hash).should == true
|
107
|
-
info["blocks"].should == { "depth" => 0, "peers" => "?", "sync" => false }
|
108
|
-
info["addrs"].should == { "alive" => 0, "total" => 0 }
|
109
|
-
info["connections"].should == {
|
110
|
-
"established" => 0, "outgoing" => 0, "incoming" => 0, "connecting" => 0 }
|
111
|
-
info["queue"].should == 0
|
112
|
-
info["inv_queue"].should == 0
|
113
|
-
info["inv_cache"].should == 0
|
114
|
-
info["network"].should == "bitcoin"
|
115
|
-
info["storage"].should == "sequel::sqlite:/"
|
116
|
-
info["version"].should == 70001
|
117
|
-
info["external_ip"].should == "127.0.0.1"
|
118
|
-
info["uptime"].between?(0, 1).should == true
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should query config" do
|
122
|
-
test_command("config").should == JSON.load(@node.config.to_json)
|
123
|
-
end
|
124
|
-
|
125
|
-
# TODO
|
126
|
-
it "should query connections" do
|
127
|
-
test_command("connections").should == []
|
128
|
-
end
|
129
|
-
|
130
|
-
# TODO
|
131
|
-
it "should connect" do
|
132
|
-
test_command("connect", {host: "127.0.0.1", port: 1234})["state"].should == "connecting"
|
133
|
-
end
|
134
|
-
|
135
|
-
# TODO
|
136
|
-
it "should disconnect" do
|
137
|
-
test_command("disconnect", ["127.0.0.1:1234"])["state"].should == "disconnected"
|
138
|
-
end
|
139
|
-
|
140
|
-
it "should store block" do
|
141
|
-
test_command("info")["blocks"].should == {"depth" => 0, "peers" => "?", "sync" => false}
|
142
|
-
res = test_command("store_block", { hex: @block.to_payload.hth })
|
143
|
-
res.should == { "queued" => @block.hash }
|
144
|
-
sleep 0.1
|
145
|
-
test_command("info")["blocks"]["depth"].should == 1
|
146
|
-
test_command("info")["blocks"]["sync"].should == true
|
147
|
-
end
|
148
|
-
|
149
|
-
# TODO
|
150
|
-
# it "should store tx" do
|
151
|
-
# @tx = @block.tx[1]
|
152
|
-
# res = test_command("store_tx", { hex: @tx.to_payload.htb })
|
153
|
-
# res.should == { "queued" => @tx.hash }
|
154
|
-
# end
|
155
|
-
|
156
|
-
describe :create_tx do
|
157
|
-
|
158
|
-
before do
|
159
|
-
@key2 = Key.generate
|
160
|
-
test_command("store_block", hex: @block.to_payload.hth)
|
161
|
-
sleep 0.1
|
162
|
-
end
|
163
|
-
|
164
|
-
it "should create transaction from given private keys" do
|
165
|
-
res = test_command("create_tx", {
|
166
|
-
keys: [ @key.to_base58 ],
|
167
|
-
recipients: [[@key2.addr, 10e8], [@key.addr, 40e8]]
|
168
|
-
})
|
169
|
-
tx = P::Tx.new(res["hex"].htb)
|
170
|
-
tx.hash.should == res["hash"]
|
171
|
-
tx.verify_input_signature(0, @block.tx[0]).should == true
|
172
|
-
end
|
173
|
-
|
174
|
-
it "should create unsigned transaction from given addresses" do
|
175
|
-
res = test_command("create_tx", {
|
176
|
-
keys: [ @key.addr ],
|
177
|
-
recipients: [[@key2.addr, 10e8], [@key.addr, 40e8]]
|
178
|
-
})
|
179
|
-
tx = P::Tx.new(res["hex"].htb)
|
180
|
-
tx.hash.should == res["hash"]
|
181
|
-
tx.in[0].script_sig.should == ""
|
182
|
-
#-> { tx.verify_input_signature(0, @block.tx[0]) }.should.raise(TypeError)
|
183
|
-
tx.verify_input_signature(0, @block.tx[0]).should == false
|
184
|
-
|
185
|
-
res["missing_sigs"].each.with_index do |sig_data, idx|
|
186
|
-
sig_hash, sig_addr = *sig_data
|
187
|
-
sig_addr.should == @key.addr
|
188
|
-
sig = @key.sign(sig_hash.htb)
|
189
|
-
script_sig = Script.to_signature_pubkey_script(sig, @key.pub.htb)
|
190
|
-
tx.in[idx].script_sig_length = script_sig.bytesize
|
191
|
-
tx.in[idx].script_sig = script_sig
|
192
|
-
end
|
193
|
-
|
194
|
-
tx.verify_input_signature(0, @block.tx[0]).should == true
|
195
|
-
end
|
196
|
-
|
197
|
-
it "should create transaction from given pubkeys" do
|
198
|
-
res = test_command("create_tx", {
|
199
|
-
keys: [@key.pub],
|
200
|
-
recipients: [[@key2.addr, 10e8], [@key.addr, 40e8]]
|
201
|
-
})
|
202
|
-
tx = P::Tx.new(res["hex"].htb)
|
203
|
-
tx.hash.should == res["hash"]
|
204
|
-
#-> { tx.verify_input_signature(0, @block.tx[0]) }.should.raise(TypeError)
|
205
|
-
tx.verify_input_signature(0, @block.tx[0]).should == false
|
206
|
-
|
207
|
-
res["missing_sigs"].each.with_index do |sig_data, idx|
|
208
|
-
sig_hash, sig_addr = *sig_data
|
209
|
-
sig_addr.should == @key.addr
|
210
|
-
sig = @key.sign(sig_hash.htb)
|
211
|
-
script_sig = Script.to_signature_pubkey_script(sig, @key.pub.htb)
|
212
|
-
tx.in[idx].script_sig_length = script_sig.bytesize
|
213
|
-
tx.in[idx].script_sig = script_sig
|
214
|
-
end
|
215
|
-
|
216
|
-
tx.verify_input_signature(0, @block.tx[0]).should == true
|
217
|
-
end
|
218
|
-
|
219
|
-
end
|
220
|
-
|
221
|
-
describe :assemble_tx do
|
222
|
-
|
223
|
-
it "should assemble tx from unsigned tx structure, signatures and pubkeys" do
|
224
|
-
tx = build_tx do |t|
|
225
|
-
t.input do |i|
|
226
|
-
i.prev_out @block.tx[0]
|
227
|
-
i.prev_out_index 0
|
228
|
-
end
|
229
|
-
t.output {|o| o.value 50e8; o.script {|s| s.recipient @key.addr } }
|
230
|
-
end
|
231
|
-
sig = @key.sign(tx.in[0].sig_hash)
|
232
|
-
test_command("store_block", hex: @block.to_payload.hth)
|
233
|
-
sleep 0.1
|
234
|
-
res = test_command("assemble_tx", {tx: tx.to_payload.hth, sig_pubs: [[sig.hth, @key.pub]]})
|
235
|
-
tx = Bitcoin::P::Tx.new(res["hex"].htb)
|
236
|
-
tx.hash.should == res["hash"]
|
237
|
-
tx.verify_input_signature(0, @block.tx[0]).should == true
|
238
|
-
end
|
239
|
-
|
240
|
-
end
|
241
|
-
|
242
|
-
describe :relay_tx do
|
243
|
-
|
244
|
-
it "should handle decoding error" do
|
245
|
-
res = test_command("relay_tx", hex: "foobar")
|
246
|
-
res["error"].should == "Error decoding transaction."
|
247
|
-
end
|
248
|
-
|
249
|
-
it "should handle syntax error" do
|
250
|
-
# create transaction with invalid output size
|
251
|
-
block = create_block(@block.hash, false, [->(t) {
|
252
|
-
create_tx(t, @block.tx[0], 0, [[22e14, @key]]) }], @key)
|
253
|
-
tx = block.tx[1]
|
254
|
-
|
255
|
-
error = test_command("relay_tx", hex: tx.to_payload.hth)
|
256
|
-
error["error"].should == "Transaction syntax invalid."
|
257
|
-
error["details"].should == ["output_values", [22e14, 21e14]]
|
258
|
-
end
|
259
|
-
|
260
|
-
it "should handle context error" do
|
261
|
-
# create transaction with invalid input
|
262
|
-
block = create_block(@block.hash, false, [->(t) {
|
263
|
-
create_tx(t, @block.tx[0], 0, [[25e8, @key]]) }], @key)
|
264
|
-
tx = block.tx[1]
|
265
|
-
|
266
|
-
error = test_command("relay_tx", hex: tx.to_payload.hth)
|
267
|
-
error["error"].should == "Transaction context invalid."
|
268
|
-
error["details"].should == ["prev_out", [[@block.tx[0].hash, 0]]]
|
269
|
-
end
|
270
|
-
|
271
|
-
it "should relay transaction" do
|
272
|
-
block = create_block(@block.hash, false, [->(t) {
|
273
|
-
create_tx(t, @block.tx[0], 0, [[25e8, @key]]) }], @key)
|
274
|
-
tx = block.tx[1]
|
275
|
-
|
276
|
-
test_command("store_block", hex: @block.to_payload.hth)
|
277
|
-
sleep 0.1
|
278
|
-
res = test_command("relay_tx", hex: tx.to_payload.hth, send: 1, wait: 0)
|
279
|
-
res["success"].should == true
|
280
|
-
res["hash"].should == tx.hash
|
281
|
-
res["propagation"].should == { "sent" => 1, "received" => 0, "percent" => 0.0 }
|
282
|
-
end
|
283
|
-
|
284
|
-
end
|
285
|
-
|
286
|
-
describe :monitor do
|
287
|
-
|
288
|
-
before do
|
289
|
-
@client = TCPSocket.new(*@config[:command])
|
290
|
-
|
291
|
-
def send method, params = nil, client = @client
|
292
|
-
request = { id: @id += 1, method: method, params: params }
|
293
|
-
client.write(request.to_json + "\x00")
|
294
|
-
request.stringify_keys
|
295
|
-
end
|
296
|
-
|
297
|
-
def should_receive request, expected, client = @client
|
298
|
-
expected = expected.stringify_keys if expected.is_a?(Hash)
|
299
|
-
begin
|
300
|
-
Timeout.timeout(100) do
|
301
|
-
buf = ""
|
302
|
-
while b = client.read(1)
|
303
|
-
break if b == "\x00"
|
304
|
-
buf << b
|
305
|
-
end
|
306
|
-
resp = JSON.load(buf)
|
307
|
-
expected = request.merge(result: expected).stringify_keys
|
308
|
-
expected.delete("params")
|
309
|
-
raise "ERROR: #{resp} != #{expected}" unless resp.should == expected
|
310
|
-
end
|
311
|
-
rescue Timeout::Error
|
312
|
-
print " [TIMEOUT]"
|
313
|
-
:timeout.should == nil
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
def should_receive_block request, block, depth, client = @client
|
318
|
-
expected = { hash: block.hash, hex: block.to_payload.hth, depth: depth }
|
319
|
-
should_receive(request, expected, client)
|
320
|
-
end
|
321
|
-
|
322
|
-
def should_receive_tx request, tx, conf, client = @client
|
323
|
-
expected = { hash: tx.hash, nhash: tx.nhash, hex: tx.to_payload.hth, conf: conf }
|
324
|
-
should_receive(request, expected, client)
|
325
|
-
end
|
326
|
-
|
327
|
-
def should_receive_output request, tx, idx, conf, client = @client
|
328
|
-
expected = { hash: tx.hash, nhash: tx.nhash, idx: idx,
|
329
|
-
address: tx.out[idx].parsed_script.get_address, value: tx.out[idx].value, conf: conf }
|
330
|
-
should_receive(request, expected, client)
|
331
|
-
end
|
332
|
-
|
333
|
-
def store_block block
|
334
|
-
request = send("store_block", hex: block.to_payload.hth)
|
335
|
-
should_receive(request, {"queued" => block.hash })
|
336
|
-
end
|
337
|
-
|
338
|
-
end
|
339
|
-
|
340
|
-
describe :channels do
|
341
|
-
|
342
|
-
it "should combine multiple channels" do
|
343
|
-
should_receive r1 = send("monitor", channel: "block"), id: 0
|
344
|
-
should_receive r2 = send("monitor", channel: "tx", conf: 1), id: 1
|
345
|
-
store_block @block
|
346
|
-
should_receive_block(r1, @block, 1)
|
347
|
-
should_receive_tx(r2, @block.tx[0], 1)
|
348
|
-
end
|
349
|
-
|
350
|
-
it "should handle multiple clients" do
|
351
|
-
@client2 = TCPSocket.new(*@config[:command])
|
352
|
-
should_receive r1_1 = send("monitor", channel: "tx", conf: 1), id: 0
|
353
|
-
r1_2 = send("monitor", { channel: "block" }, @client2)
|
354
|
-
should_receive r1_2, { id: 0 }, @client2
|
355
|
-
|
356
|
-
store_block @block
|
357
|
-
|
358
|
-
should_receive_block(r1_2, @block, 1, @client2)
|
359
|
-
should_receive_tx(r1_1, @block.tx[0], 1)
|
360
|
-
|
361
|
-
block = create_block @block.hash, false
|
362
|
-
store_block block
|
363
|
-
|
364
|
-
should_receive_block(r1_2, block, 2, @client2)
|
365
|
-
should_receive_tx(r1_1, block.tx[0], 1)
|
366
|
-
|
367
|
-
r2_2 = send "monitor", { channel: "tx", conf: 1 }, @client2
|
368
|
-
should_receive r2_2, { id: 1 }, @client2
|
369
|
-
should_receive r2_1 = send("monitor", channel: "block"), id: 1
|
370
|
-
|
371
|
-
block = create_block block.hash, false
|
372
|
-
store_block block
|
373
|
-
|
374
|
-
should_receive_block(r1_2, block, 3, @client2)
|
375
|
-
should_receive_tx(r2_2, block.tx[0], 1, @client2)
|
376
|
-
|
377
|
-
should_receive_tx(r1_1, block.tx[0], 1)
|
378
|
-
|
379
|
-
# if something was wrong, we would now receive the last tx again
|
380
|
-
|
381
|
-
should_receive_block(r2_1, block, 3)
|
382
|
-
|
383
|
-
block = create_block block.hash, false
|
384
|
-
store_block block
|
385
|
-
|
386
|
-
should_receive_tx(r1_1, block.tx[0], 1)
|
387
|
-
|
388
|
-
should_receive_block(r2_1, block, 4)
|
389
|
-
should_receive_block(r1_2, block, 4, @client2)
|
390
|
-
should_receive_tx(r2_2, block.tx[0], 1, @client2)
|
391
|
-
end
|
392
|
-
|
393
|
-
end
|
394
|
-
|
395
|
-
describe :block do
|
396
|
-
|
397
|
-
before do
|
398
|
-
@request = send "monitor", channel: "block"
|
399
|
-
|
400
|
-
should_receive(@request, id: 0)
|
401
|
-
store_block @block
|
402
|
-
should_receive_block(@request, @block, 1)
|
403
|
-
end
|
404
|
-
|
405
|
-
it "should monitor block" do
|
406
|
-
@block = create_block @block.hash, false
|
407
|
-
store_block @block
|
408
|
-
should_receive_block(@request, @block, 2)
|
409
|
-
end
|
410
|
-
|
411
|
-
it "should unmonitor block" do
|
412
|
-
@request = send "unmonitor", id: 0
|
413
|
-
should_receive @request, id: 0
|
414
|
-
store_block create_block(@block.hash, false)
|
415
|
-
|
416
|
-
test_command("tslb") {|r| (0..TSLB_TIMEOUT).include?(r['tslb']).should == true }
|
417
|
-
end
|
418
|
-
|
419
|
-
it "should not monitor side or orphan blocks" do
|
420
|
-
@side = create_block @genesis.hash, false
|
421
|
-
store_block @side
|
422
|
-
|
423
|
-
@orphan = create_block "00" * 32, false
|
424
|
-
store_block @orphan
|
425
|
-
|
426
|
-
# should not send side or orphan block only the next main block
|
427
|
-
@block = create_block @block.hash, false
|
428
|
-
store_block @block
|
429
|
-
|
430
|
-
should_receive_block(@request, @block, 2)
|
431
|
-
end
|
432
|
-
|
433
|
-
it "should received missed blocks when last block hash is given" do
|
434
|
-
@client = TCPSocket.new(*@config[:command])
|
435
|
-
blocks = [@block]
|
436
|
-
3.times do
|
437
|
-
blocks << create_block(blocks.last.hash, false)
|
438
|
-
store_block blocks.last
|
439
|
-
end
|
440
|
-
sleep 0.1
|
441
|
-
|
442
|
-
r = send "monitor", channel: "block", last: blocks[1].hash
|
443
|
-
|
444
|
-
should_receive_block(r, blocks[1], 2)
|
445
|
-
should_receive_block(r, blocks[2], 3)
|
446
|
-
should_receive_block(r, blocks[3], 4)
|
447
|
-
end
|
448
|
-
|
449
|
-
end
|
450
|
-
|
451
|
-
describe :reorg do
|
452
|
-
|
453
|
-
before do
|
454
|
-
@request = send "monitor", channel: "reorg"
|
455
|
-
should_receive @request, id: 0
|
456
|
-
store_block @block
|
457
|
-
end
|
458
|
-
|
459
|
-
it "should monitor reorg" do
|
460
|
-
@block1 = create_block @genesis.hash, false
|
461
|
-
store_block @block1
|
462
|
-
@block2 = create_block @block1.hash, false
|
463
|
-
store_block @block2
|
464
|
-
should_receive @request, { new_main: [ @block1.hash ], new_side: [ @block.hash ] }
|
465
|
-
end
|
466
|
-
|
467
|
-
it "should unmonitor reorg" do
|
468
|
-
r = send "unmonitor", id: 0
|
469
|
-
should_receive r, id: 0
|
470
|
-
@block1 = create_block @genesis.hash, false
|
471
|
-
store_block @block1
|
472
|
-
@block2 = create_block @block1.hash, false
|
473
|
-
store_block @block2
|
474
|
-
|
475
|
-
test_command("tslb") {|r| (0..TSLB_TIMEOUT).include?(r['tslb']).should == true }
|
476
|
-
end
|
477
|
-
|
478
|
-
end
|
479
|
-
|
480
|
-
describe :tx do
|
481
|
-
|
482
|
-
|
483
|
-
it "should monitor unconfirmed tx" do
|
484
|
-
r1 = send "monitor", channel: "tx"
|
485
|
-
should_receive r1, id: 0
|
486
|
-
tx = @block.tx[0]
|
487
|
-
r2 = send "store_tx", hex: tx.to_payload.hth
|
488
|
-
should_receive r2, { "queued" => tx.hash }
|
489
|
-
|
490
|
-
should_receive_tx(r1, tx, 0)
|
491
|
-
end
|
492
|
-
|
493
|
-
it "should unmonitor tx" do
|
494
|
-
r1 = send "monitor", channel: "tx"
|
495
|
-
should_receive r1, id: 0
|
496
|
-
|
497
|
-
r2 = send "unmonitor", id: 0
|
498
|
-
should_receive r2, id: 0
|
499
|
-
|
500
|
-
tx = @block.tx[0]
|
501
|
-
r3 = send "store_tx", hex: tx.to_payload.hth
|
502
|
-
should_receive r3, { "queued" => tx.hash }
|
503
|
-
|
504
|
-
test_command("tslb") {|r| (0..TSLB_TIMEOUT).include?(r['tslb']).should == true }
|
505
|
-
end
|
506
|
-
|
507
|
-
it "should monitor confirmed tx" do
|
508
|
-
r = send "monitor", channel: "tx", conf: 1
|
509
|
-
should_receive r, id: 0
|
510
|
-
store_block @block
|
511
|
-
|
512
|
-
should_receive_tx(r, @block.tx[0], 1)
|
513
|
-
end
|
514
|
-
|
515
|
-
it "should monitor tx for given confirmation level" do
|
516
|
-
r = send "monitor", channel: "tx", conf: 3
|
517
|
-
should_receive r, id: 0
|
518
|
-
|
519
|
-
@tx = @block.tx[0]
|
520
|
-
store_block @block
|
521
|
-
@block = create_block @block.hash, false
|
522
|
-
store_block @block
|
523
|
-
|
524
|
-
should_receive_tx(r, @genesis.tx[0], 3)
|
525
|
-
|
526
|
-
@block = create_block @block.hash, false
|
527
|
-
store_block @block
|
528
|
-
|
529
|
-
should_receive_tx(r, @tx, 3)
|
530
|
-
end
|
531
|
-
|
532
|
-
it "should receive missed txs when last txhash is given" do
|
533
|
-
@client = TCPSocket.new(*@config[:command])
|
534
|
-
blocks = [@block]; store_block @block
|
535
|
-
3.times do
|
536
|
-
blocks << create_block(blocks.last.hash, false)
|
537
|
-
store_block blocks.last
|
538
|
-
end
|
539
|
-
sleep 0.1
|
540
|
-
|
541
|
-
r = send "monitor", channel: "tx", conf: 1, last: blocks[0].tx[0].hash
|
542
|
-
|
543
|
-
should_receive_tx(r, blocks[1].tx[0], 3)
|
544
|
-
should_receive_tx(r, blocks[2].tx[0], 2)
|
545
|
-
should_receive_tx(r, blocks[3].tx[0], 1)
|
546
|
-
|
547
|
-
should_receive r, id: 0
|
548
|
-
end
|
549
|
-
|
550
|
-
|
551
|
-
it "should filter txs for given addresses" do
|
552
|
-
@key2 = Bitcoin::Key.generate
|
553
|
-
block = create_block(@block.hash, false, [->(t) {
|
554
|
-
create_tx(t, @block.tx[0], 0, [[50e8, @key2]]) }], @key)
|
555
|
-
@addr = @block.tx[0].out[0].parsed_script.get_address
|
556
|
-
r = send "monitor", channel: "tx", conf: 1, addresses: [ @key2.addr ]
|
557
|
-
should_receive r, id: 0
|
558
|
-
store_block @block
|
559
|
-
store_block block
|
560
|
-
should_receive_tx(r, block.tx[1], 1)
|
561
|
-
end
|
562
|
-
|
563
|
-
end
|
564
|
-
|
565
|
-
describe :output do
|
566
|
-
|
567
|
-
before do
|
568
|
-
@tx = @block.tx[0]; @out = @tx.out[0]
|
569
|
-
end
|
570
|
-
|
571
|
-
it "should monitor unconfirmed outputs" do
|
572
|
-
r1 = send "monitor", channel: "output"
|
573
|
-
should_receive r1, id: 0
|
574
|
-
tx = @block.tx[0]
|
575
|
-
r2 = send "store_tx", hex: tx.to_payload.hth
|
576
|
-
should_receive r2, { "queued" => tx.hash }
|
577
|
-
should_receive_output(r1, tx, 0, 0)
|
578
|
-
end
|
579
|
-
|
580
|
-
it "should unmonitor outputs" do
|
581
|
-
should_receive send("monitor", channel: "output"), id: 0
|
582
|
-
should_receive send("unmonitor", id: 0), id: 0
|
583
|
-
|
584
|
-
tx = @block.tx[0]
|
585
|
-
r2 = send "store_tx", hex: tx.to_payload.hth
|
586
|
-
should_receive r2, { "queued" => tx.hash }
|
587
|
-
|
588
|
-
test_command("tslb") {|r| (0..TSLB_TIMEOUT).include?(r['tslb']).should == true }
|
589
|
-
end
|
590
|
-
|
591
|
-
it "should monitor confirmed output" do
|
592
|
-
r = send "monitor", channel: "output", conf: 1
|
593
|
-
should_receive r, id: 0
|
594
|
-
store_block @block
|
595
|
-
should_receive_output(r, @tx, 0, 1)
|
596
|
-
end
|
597
|
-
|
598
|
-
it "should monitor output for given confirmation level" do
|
599
|
-
r = send "monitor", channel: "output", conf: 3
|
600
|
-
should_receive r, id: 0
|
601
|
-
store_block @block
|
602
|
-
@block = create_block @block.hash, false
|
603
|
-
store_block @block
|
604
|
-
tx = @genesis.tx[0]; out = tx.out[0]
|
605
|
-
should_receive_output(r, tx, 0, 3)
|
606
|
-
|
607
|
-
@block = create_block @block.hash, false
|
608
|
-
store_block @block
|
609
|
-
should_receive_output(r, @tx, 0, 3)
|
610
|
-
end
|
611
|
-
|
612
|
-
it "should receive missed outputs when last txhash:idx is given" do
|
613
|
-
@key = Bitcoin::Key.generate
|
614
|
-
@client = TCPSocket.new(*@config[:command])
|
615
|
-
blocks = [@block]; store_block @block
|
616
|
-
3.times do
|
617
|
-
blocks << create_block(blocks.last.hash, false, [], @key)
|
618
|
-
store_block blocks.last
|
619
|
-
end
|
620
|
-
sleep 0.1
|
621
|
-
|
622
|
-
r = send "monitor", channel: "output", conf: 1, last: "#{blocks[0].tx[0].hash}:0"
|
623
|
-
|
624
|
-
should_receive_output(r, blocks[1].tx[0], 0, 3)
|
625
|
-
should_receive_output(r, blocks[2].tx[0], 0, 2)
|
626
|
-
should_receive_output(r, blocks[3].tx[0], 0, 1)
|
627
|
-
|
628
|
-
should_receive r, id: 0
|
629
|
-
end
|
630
|
-
|
631
|
-
it "should filter outputs for given addresses" do
|
632
|
-
@key2 = Bitcoin::Key.generate
|
633
|
-
block = create_block(@block.hash, false, [->(t) {
|
634
|
-
create_tx(t, @block.tx[0], 0, [[50e8, @key2]]) }], @key)
|
635
|
-
|
636
|
-
r = send "monitor", channel: "output", conf: 1, addresses: [ @key2.addr ]
|
637
|
-
should_receive r, id: 0
|
638
|
-
store_block @block
|
639
|
-
store_block block
|
640
|
-
should_receive_output(r, block.tx[1], 0, 1)
|
641
|
-
end
|
642
|
-
|
643
|
-
it "should add filter address to output monitor params" do
|
644
|
-
@key2 = Bitcoin::Key.generate
|
645
|
-
block = create_block(@block.hash, false, [->(t) {
|
646
|
-
create_tx(t, @block.tx[0], 0, [[50e8, @key2]]) }], @key)
|
647
|
-
|
648
|
-
r1 = send "monitor", channel: "output", conf: 1, addresses: [ ]
|
649
|
-
should_receive r1, id: 0
|
650
|
-
|
651
|
-
r2 = send "filter_monitor_output", id: 0, address: @key2.addr
|
652
|
-
should_receive r2, id: 0
|
653
|
-
|
654
|
-
store_block @block
|
655
|
-
store_block block
|
656
|
-
should_receive_output(r1, block.tx[1], 0, 1)
|
657
|
-
end
|
658
|
-
|
659
|
-
end
|
660
|
-
|
661
|
-
end
|
662
|
-
|
663
|
-
end
|