bitcoin-ruby 0.0.6 → 0.0.7
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.
- 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
|