Browse Source
0.15019c492
qa: Fix lcov for out-of-tree builds (MarcoFalke)e169349
qa: Restore bitcoin-util-test py2 compatibility (MarcoFalke)806c78f
add functional test for mempoolreplacement command line arg (Gregory Sanders)a825d4a
Fix bip68-sequence rpc test (Johnson Lau)a36f332
Verify DBWrapper iterators are taking snapshots (Matt Corallo)8d2e51d
qa: Fix bug introduced in p2p-segwit.py (Suhas Daftuar)2f0b30a
qa: Treat mininode p2p exceptions as fatal (Suhas Daftuar)e4605d9
Tests for zmqpubrawtx and zmqpubrawblock (Andrew Chow)2c4ff35
[script] Unit tests for IsMine (Jim Posen)794a80e
[script] Unit tests for script/standard functions (Jim Posen)f9cf7b5
[tests] Check connectivity before sending in assumevalid.py (John Newbery)f1ced0d
[tests] Make p2p-leaktests.py more robust (John Newbery)2e1ac70
[qa] zapwallettxes: Wait up to 3s for mempool reload (MarcoFalke)b6468d3
Add listwallets RPC test to multiwallet.py (Cristian Mircea Messel)d8dd8e7
[tests] fixup dbcrash interaction with add_nodes() (John Newbery)2b97b36
[test] Replace check_output with low level version (João Barbosa)e38211f
[test] Add assert_raises_process_error to assert process errors (João Barbosa)e0bfd28
[test] Add support for custom arguments to TestNodeCLI (João Barbosa)812c870
[test] Improve assert_raises_jsonrpc docstring (João Barbosa)eeb24a3
[qa] TestNode: Add wait_until_stopped helper method (MarcoFalke)f3f7891
Stop test_bitcoin-qt touching ~/.bitcoin (MeshCollider)f0b6795
Remove redundant testutil files (MeshCollider)4424176
Improve signmessages functional test (Cristian Mircea Messel)cef0319
[tests] fixups from set_test_params() (John Newbery)82bf6fc
[tests] Functional tests must explicitly set num_nodes (John Newbery)801d2ae
[tests] don't override __init__() in individual tests (John Newbery)bb5e7cb
[tests] Avoid passing around member variables in test_framework (John Newbery)4d3ba18
[tests] TestNode: separate add_node from start_node (John Newbery)11a5992
[tests] fix - use rpc_timeout as rpc timeout (John Newbery)847c75e
Add getmininginfo functional test (Cristian Mircea Messel)2a5d099
RPC: gettxout: Slightly improve doc and tests (Jorge Timón)716066d
[tests] Add bitcoin_cli.py test script (John Newbery)016b9ad
[tests] add TestNodeCLI class for calling bitcoin-cli for a node (John Newbery)5398f20
qa: Move wait_until to util (MarcoFalke)1d80d1e
[tests] fix timeout issues from TestNode (John Newbery)c276c1e
test: Increase initial RPC timeout to 60 seconds (Wladimir J. van der Laan)fc2aa09
[tests] Introduce TestNode (John Newbery) Pull request description: This includes test related backports for 0.15.1. The motivation is twofold: * Make backporting new tests written for current master easier * Fix the most common test issues that happen(ed) frequently on travis Even though this includes the new TestNode class, which comes with a lot of refactoring, I believe that the issues caused by refactoring are found and fixed by now. Tree-SHA512: 6a0c4e5246da83ff0b3f7d2cb8df358d105ed548fb3857e5d882f26cc336553aa07b39e38c281879bf82f95078298b775334f9a60c0b23140f77c50174bd8347
Wladimir J. van der Laan
7 years ago
102 changed files with 1658 additions and 880 deletions
@ -0,0 +1,740 @@
@@ -0,0 +1,740 @@
|
||||
// Copyright (c) 2017 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "key.h" |
||||
#include "keystore.h" |
||||
#include "script/ismine.h" |
||||
#include "script/script.h" |
||||
#include "script/script_error.h" |
||||
#include "script/standard.h" |
||||
#include "test/test_bitcoin.h" |
||||
|
||||
#include <boost/test/unit_test.hpp> |
||||
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(script_standard_tests, BasicTestingSetup) |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_Solver_success) |
||||
{ |
||||
CKey keys[3]; |
||||
CPubKey pubkeys[3]; |
||||
for (int i = 0; i < 3; i++) { |
||||
keys[i].MakeNewKey(true); |
||||
pubkeys[i] = keys[i].GetPubKey(); |
||||
} |
||||
|
||||
CScript s; |
||||
txnouttype whichType; |
||||
std::vector<std::vector<unsigned char> > solutions; |
||||
|
||||
// TX_PUBKEY
|
||||
s.clear(); |
||||
s << ToByteVector(pubkeys[0]) << OP_CHECKSIG; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_PUBKEY); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 1); |
||||
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0])); |
||||
|
||||
// TX_PUBKEYHASH
|
||||
s.clear(); |
||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 1); |
||||
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID())); |
||||
|
||||
// TX_SCRIPTHASH
|
||||
CScript redeemScript(s); // initialize with leftover P2PKH script
|
||||
s.clear(); |
||||
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 1); |
||||
BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript))); |
||||
|
||||
// TX_MULTISIG
|
||||
s.clear(); |
||||
s << OP_1 << |
||||
ToByteVector(pubkeys[0]) << |
||||
ToByteVector(pubkeys[1]) << |
||||
OP_2 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_MULTISIG); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 4); |
||||
BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1})); |
||||
BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0])); |
||||
BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1])); |
||||
BOOST_CHECK(solutions[3] == std::vector<unsigned char>({2})); |
||||
|
||||
s.clear(); |
||||
s << OP_2 << |
||||
ToByteVector(pubkeys[0]) << |
||||
ToByteVector(pubkeys[1]) << |
||||
ToByteVector(pubkeys[2]) << |
||||
OP_3 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_MULTISIG); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 5); |
||||
BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2})); |
||||
BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0])); |
||||
BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1])); |
||||
BOOST_CHECK(solutions[3] == ToByteVector(pubkeys[2])); |
||||
BOOST_CHECK(solutions[4] == std::vector<unsigned char>({3})); |
||||
|
||||
// TX_NULL_DATA
|
||||
s.clear(); |
||||
s << OP_RETURN << |
||||
std::vector<unsigned char>({0}) << |
||||
std::vector<unsigned char>({75}) << |
||||
std::vector<unsigned char>({255}); |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_NULL_DATA); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 0); |
||||
|
||||
// TX_WITNESS_V0_KEYHASH
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(pubkeys[0].GetID()); |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_KEYHASH); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 1); |
||||
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID())); |
||||
|
||||
// TX_WITNESS_V0_SCRIPTHASH
|
||||
uint256 scriptHash; |
||||
CSHA256().Write(&redeemScript[0], redeemScript.size()) |
||||
.Finalize(scriptHash.begin()); |
||||
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(scriptHash); |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_SCRIPTHASH); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 1); |
||||
BOOST_CHECK(solutions[0] == ToByteVector(scriptHash)); |
||||
|
||||
// TX_NONSTANDARD
|
||||
s.clear(); |
||||
s << OP_9 << OP_ADD << OP_11 << OP_EQUAL; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_NONSTANDARD); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_Solver_failure) |
||||
{ |
||||
CKey key; |
||||
CPubKey pubkey; |
||||
key.MakeNewKey(true); |
||||
pubkey = key.GetPubKey(); |
||||
|
||||
CScript s; |
||||
txnouttype whichType; |
||||
std::vector<std::vector<unsigned char> > solutions; |
||||
|
||||
// TX_PUBKEY with incorrectly sized pubkey
|
||||
s.clear(); |
||||
s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_PUBKEYHASH with incorrectly sized key hash
|
||||
s.clear(); |
||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_SCRIPTHASH with incorrectly sized script hash
|
||||
s.clear(); |
||||
s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_MULTISIG 0/2
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_MULTISIG 2/1
|
||||
s.clear(); |
||||
s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_MULTISIG n = 2 with 1 pubkey
|
||||
s.clear(); |
||||
s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_MULTISIG n = 1 with 0 pubkeys
|
||||
s.clear(); |
||||
s << OP_1 << OP_1 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_NULL_DATA with other opcodes
|
||||
s.clear(); |
||||
s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_WITNESS with unknown version
|
||||
s.clear(); |
||||
s << OP_1 << ToByteVector(pubkey); |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_WITNESS with incorrect program size
|
||||
s.clear(); |
||||
s << OP_0 << std::vector<unsigned char>(19, 0x01); |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination) |
||||
{ |
||||
CKey key; |
||||
CPubKey pubkey; |
||||
key.MakeNewKey(true); |
||||
pubkey = key.GetPubKey(); |
||||
|
||||
CScript s; |
||||
CTxDestination address; |
||||
|
||||
// TX_PUBKEY
|
||||
s.clear(); |
||||
s << ToByteVector(pubkey) << OP_CHECKSIG; |
||||
BOOST_CHECK(ExtractDestination(s, address)); |
||||
BOOST_CHECK(boost::get<CKeyID>(&address) && |
||||
*boost::get<CKeyID>(&address) == pubkey.GetID()); |
||||
|
||||
// TX_PUBKEYHASH
|
||||
s.clear(); |
||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
BOOST_CHECK(ExtractDestination(s, address)); |
||||
BOOST_CHECK(boost::get<CKeyID>(&address) && |
||||
*boost::get<CKeyID>(&address) == pubkey.GetID()); |
||||
|
||||
// TX_SCRIPTHASH
|
||||
CScript redeemScript(s); // initialize with leftover P2PKH script
|
||||
s.clear(); |
||||
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; |
||||
BOOST_CHECK(ExtractDestination(s, address)); |
||||
BOOST_CHECK(boost::get<CScriptID>(&address) && |
||||
*boost::get<CScriptID>(&address) == CScriptID(redeemScript)); |
||||
|
||||
// TX_MULTISIG
|
||||
s.clear(); |
||||
s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(!ExtractDestination(s, address)); |
||||
|
||||
// TX_NULL_DATA
|
||||
s.clear(); |
||||
s << OP_RETURN << std::vector<unsigned char>({75}); |
||||
BOOST_CHECK(!ExtractDestination(s, address)); |
||||
|
||||
// TX_WITNESS_V0_KEYHASH
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(pubkey); |
||||
BOOST_CHECK(!ExtractDestination(s, address)); |
||||
|
||||
// TX_WITNESS_V0_SCRIPTHASH
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(CScriptID(redeemScript)); |
||||
BOOST_CHECK(!ExtractDestination(s, address)); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations) |
||||
{ |
||||
CKey keys[3]; |
||||
CPubKey pubkeys[3]; |
||||
for (int i = 0; i < 3; i++) { |
||||
keys[i].MakeNewKey(true); |
||||
pubkeys[i] = keys[i].GetPubKey(); |
||||
} |
||||
|
||||
CScript s; |
||||
txnouttype whichType; |
||||
std::vector<CTxDestination> addresses; |
||||
int nRequired; |
||||
|
||||
// TX_PUBKEY
|
||||
s.clear(); |
||||
s << ToByteVector(pubkeys[0]) << OP_CHECKSIG; |
||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_PUBKEY); |
||||
BOOST_CHECK_EQUAL(addresses.size(), 1); |
||||
BOOST_CHECK_EQUAL(nRequired, 1); |
||||
BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) && |
||||
*boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID()); |
||||
|
||||
// TX_PUBKEYHASH
|
||||
s.clear(); |
||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH); |
||||
BOOST_CHECK_EQUAL(addresses.size(), 1); |
||||
BOOST_CHECK_EQUAL(nRequired, 1); |
||||
BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) && |
||||
*boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID()); |
||||
|
||||
// TX_SCRIPTHASH
|
||||
CScript redeemScript(s); // initialize with leftover P2PKH script
|
||||
s.clear(); |
||||
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; |
||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH); |
||||
BOOST_CHECK_EQUAL(addresses.size(), 1); |
||||
BOOST_CHECK_EQUAL(nRequired, 1); |
||||
BOOST_CHECK(boost::get<CScriptID>(&addresses[0]) && |
||||
*boost::get<CScriptID>(&addresses[0]) == CScriptID(redeemScript)); |
||||
|
||||
// TX_MULTISIG
|
||||
s.clear(); |
||||
s << OP_2 << |
||||
ToByteVector(pubkeys[0]) << |
||||
ToByteVector(pubkeys[1]) << |
||||
OP_2 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_MULTISIG); |
||||
BOOST_CHECK_EQUAL(addresses.size(), 2); |
||||
BOOST_CHECK_EQUAL(nRequired, 2); |
||||
BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) && |
||||
*boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID()); |
||||
BOOST_CHECK(boost::get<CKeyID>(&addresses[1]) && |
||||
*boost::get<CKeyID>(&addresses[1]) == pubkeys[1].GetID()); |
||||
|
||||
// TX_NULL_DATA
|
||||
s.clear(); |
||||
s << OP_RETURN << std::vector<unsigned char>({75}); |
||||
BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
|
||||
// TX_WITNESS_V0_KEYHASH
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(pubkeys[0].GetID()); |
||||
BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
|
||||
// TX_WITNESS_V0_SCRIPTHASH
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(CScriptID(redeemScript)); |
||||
BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_GetScriptFor_) |
||||
{ |
||||
CKey keys[3]; |
||||
CPubKey pubkeys[3]; |
||||
for (int i = 0; i < 3; i++) { |
||||
keys[i].MakeNewKey(true); |
||||
pubkeys[i] = keys[i].GetPubKey(); |
||||
} |
||||
|
||||
CScript expected, result; |
||||
|
||||
// CKeyID
|
||||
expected.clear(); |
||||
expected << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
result = GetScriptForDestination(pubkeys[0].GetID()); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
// CScriptID
|
||||
CScript redeemScript(result); |
||||
expected.clear(); |
||||
expected << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; |
||||
result = GetScriptForDestination(CScriptID(redeemScript)); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
// CNoDestination
|
||||
expected.clear(); |
||||
result = GetScriptForDestination(CNoDestination()); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
// GetScriptForRawPubKey
|
||||
expected.clear(); |
||||
expected << ToByteVector(pubkeys[0]) << OP_CHECKSIG; |
||||
result = GetScriptForRawPubKey(pubkeys[0]); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
// GetScriptForMultisig
|
||||
expected.clear(); |
||||
expected << OP_2 << |
||||
ToByteVector(pubkeys[0]) << |
||||
ToByteVector(pubkeys[1]) << |
||||
ToByteVector(pubkeys[2]) << |
||||
OP_3 << OP_CHECKMULTISIG; |
||||
result = GetScriptForMultisig(2, std::vector<CPubKey>(pubkeys, pubkeys + 3)); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
// GetScriptForWitness
|
||||
CScript witnessScript; |
||||
|
||||
witnessScript << ToByteVector(pubkeys[0]) << OP_CHECKSIG; |
||||
expected.clear(); |
||||
expected << OP_0 << ToByteVector(pubkeys[0].GetID()); |
||||
result = GetScriptForWitness(witnessScript); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
witnessScript.clear(); |
||||
witnessScript << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
result = GetScriptForWitness(witnessScript); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
witnessScript.clear(); |
||||
witnessScript << OP_1 << ToByteVector(pubkeys[0]) << OP_1 << OP_CHECKMULTISIG; |
||||
|
||||
uint256 scriptHash; |
||||
CSHA256().Write(&witnessScript[0], witnessScript.size()) |
||||
.Finalize(scriptHash.begin()); |
||||
|
||||
expected.clear(); |
||||
expected << OP_0 << ToByteVector(scriptHash); |
||||
result = GetScriptForWitness(witnessScript); |
||||
BOOST_CHECK(result == expected); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_IsMine) |
||||
{ |
||||
CKey keys[2]; |
||||
CPubKey pubkeys[2]; |
||||
for (int i = 0; i < 2; i++) { |
||||
keys[i].MakeNewKey(true); |
||||
pubkeys[i] = keys[i].GetPubKey(); |
||||
} |
||||
|
||||
CKey uncompressedKey; |
||||
uncompressedKey.MakeNewKey(false); |
||||
CPubKey uncompressedPubkey = uncompressedKey.GetPubKey(); |
||||
|
||||
CScript scriptPubKey; |
||||
isminetype result; |
||||
bool isInvalid; |
||||
|
||||
// P2PK compressed
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
scriptPubKey.clear(); |
||||
scriptPubKey << ToByteVector(pubkeys[0]) << OP_CHECKSIG; |
||||
|
||||
// Keystore does not have key
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has key
|
||||
keystore.AddKey(keys[0]); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
|
||||
// P2PK uncompressed
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
scriptPubKey.clear(); |
||||
scriptPubKey << ToByteVector(uncompressedPubkey) << OP_CHECKSIG; |
||||
|
||||
// Keystore does not have key
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has key
|
||||
keystore.AddKey(uncompressedKey); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
|
||||
// P2PKH compressed
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
|
||||
// Keystore does not have key
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has key
|
||||
keystore.AddKey(keys[0]); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
|
||||
// P2PKH uncompressed
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(uncompressedPubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
|
||||
// Keystore does not have key
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has key
|
||||
keystore.AddKey(uncompressedKey); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
|
||||
// P2SH
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
|
||||
CScript redeemScript; |
||||
redeemScript << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
|
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; |
||||
|
||||
// Keystore does not have redeemScript or key
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has redeemScript but no key
|
||||
keystore.AddCScript(redeemScript); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has redeemScript and key
|
||||
keystore.AddKey(keys[0]); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
|
||||
// P2WPKH compressed
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
keystore.AddKey(keys[0]); |
||||
|
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_0 << ToByteVector(pubkeys[0].GetID()); |
||||
|
||||
// Keystore has key, but no P2SH redeemScript
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has key and P2SH redeemScript
|
||||
keystore.AddCScript(scriptPubKey); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
|
||||
// P2WPKH uncompressed
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
keystore.AddKey(uncompressedKey); |
||||
|
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_0 << ToByteVector(uncompressedPubkey.GetID()); |
||||
|
||||
// Keystore has key, but no P2SH redeemScript
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has key and P2SH redeemScript
|
||||
keystore.AddCScript(scriptPubKey); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(isInvalid); |
||||
} |
||||
|
||||
// scriptPubKey multisig
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
|
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_2 << |
||||
ToByteVector(uncompressedPubkey) << |
||||
ToByteVector(pubkeys[1]) << |
||||
OP_2 << OP_CHECKMULTISIG; |
||||
|
||||
// Keystore does not have any keys
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has 1/2 keys
|
||||
keystore.AddKey(uncompressedKey); |
||||
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has 2/2 keys
|
||||
keystore.AddKey(keys[1]); |
||||
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
|
||||
// P2SH multisig
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
keystore.AddKey(uncompressedKey); |
||||
keystore.AddKey(keys[1]); |
||||
|
||||
CScript redeemScript; |
||||
redeemScript << OP_2 << |
||||
ToByteVector(uncompressedPubkey) << |
||||
ToByteVector(pubkeys[1]) << |
||||
OP_2 << OP_CHECKMULTISIG; |
||||
|
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; |
||||
|
||||
// Keystore has no redeemScript
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has redeemScript
|
||||
keystore.AddCScript(redeemScript); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
|
||||
// P2WSH multisig with compressed keys
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
keystore.AddKey(keys[0]); |
||||
keystore.AddKey(keys[1]); |
||||
|
||||
CScript witnessScript; |
||||
witnessScript << OP_2 << |
||||
ToByteVector(pubkeys[0]) << |
||||
ToByteVector(pubkeys[1]) << |
||||
OP_2 << OP_CHECKMULTISIG; |
||||
|
||||
uint256 scriptHash; |
||||
CSHA256().Write(&witnessScript[0], witnessScript.size()) |
||||
.Finalize(scriptHash.begin()); |
||||
|
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_0 << ToByteVector(scriptHash); |
||||
|
||||
// Keystore has keys, but no witnessScript or P2SH redeemScript
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has keys and witnessScript, but no P2SH redeemScript
|
||||
keystore.AddCScript(witnessScript); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has keys, witnessScript, P2SH redeemScript
|
||||
keystore.AddCScript(scriptPubKey); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
|
||||
// P2WSH multisig with uncompressed key
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
keystore.AddKey(uncompressedKey); |
||||
keystore.AddKey(keys[1]); |
||||
|
||||
CScript witnessScript; |
||||
witnessScript << OP_2 << |
||||
ToByteVector(uncompressedPubkey) << |
||||
ToByteVector(pubkeys[1]) << |
||||
OP_2 << OP_CHECKMULTISIG; |
||||
|
||||
uint256 scriptHash; |
||||
CSHA256().Write(&witnessScript[0], witnessScript.size()) |
||||
.Finalize(scriptHash.begin()); |
||||
|
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_0 << ToByteVector(scriptHash); |
||||
|
||||
// Keystore has keys, but no witnessScript or P2SH redeemScript
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has keys and witnessScript, but no P2SH redeemScript
|
||||
keystore.AddCScript(witnessScript); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has keys, witnessScript, P2SH redeemScript
|
||||
keystore.AddCScript(scriptPubKey); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(isInvalid); |
||||
} |
||||
|
||||
// P2WSH multisig wrapped in P2SH
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
|
||||
CScript witnessScript; |
||||
witnessScript << OP_2 << |
||||
ToByteVector(pubkeys[0]) << |
||||
ToByteVector(pubkeys[1]) << |
||||
OP_2 << OP_CHECKMULTISIG; |
||||
|
||||
uint256 scriptHash; |
||||
CSHA256().Write(&witnessScript[0], witnessScript.size()) |
||||
.Finalize(scriptHash.begin()); |
||||
|
||||
CScript redeemScript; |
||||
redeemScript << OP_0 << ToByteVector(scriptHash); |
||||
|
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; |
||||
|
||||
// Keystore has no witnessScript, P2SH redeemScript, or keys
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has witnessScript and P2SH redeemScript, but no keys
|
||||
keystore.AddCScript(redeemScript); |
||||
keystore.AddCScript(witnessScript); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
|
||||
// Keystore has keys, witnessScript, P2SH redeemScript
|
||||
keystore.AddKey(keys[0]); |
||||
keystore.AddKey(keys[1]); |
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
|
||||
// OP_RETURN
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
keystore.AddKey(keys[0]); |
||||
|
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]); |
||||
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
|
||||
// Nonstandard
|
||||
{ |
||||
CBasicKeyStore keystore; |
||||
keystore.AddKey(keys[0]); |
||||
|
||||
scriptPubKey.clear(); |
||||
scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL; |
||||
|
||||
result = IsMine(keystore, scriptPubKey, isInvalid); |
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO); |
||||
BOOST_CHECK(!isInvalid); |
||||
} |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() |
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) 2009-2016 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "testutil.h" |
||||
|
||||
#ifdef WIN32 |
||||
#include <shlobj.h> |
||||
#endif |
||||
|
||||
#include "fs.h" |
||||
|
||||
fs::path GetTempPath() { |
||||
return fs::temp_directory_path(); |
||||
} |
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) 2009-2016 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
/**
|
||||
* Utility functions shared by unit tests |
||||
*/ |
||||
#ifndef BITCOIN_TEST_TESTUTIL_H |
||||
#define BITCOIN_TEST_TESTUTIL_H |
||||
|
||||
#include "fs.h" |
||||
|
||||
fs::path GetTempPath(); |
||||
|
||||
#endif // BITCOIN_TEST_TESTUTIL_H
|
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python3 |
||||
# Copyright (c) 2017 The Bitcoin Core developers |
||||
# Distributed under the MIT software license, see the accompanying |
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. |
||||
"""Test bitcoin-cli""" |
||||
from test_framework.test_framework import BitcoinTestFramework |
||||
from test_framework.util import assert_equal |
||||
|
||||
class TestBitcoinCli(BitcoinTestFramework): |
||||
|
||||
def set_test_params(self): |
||||
self.setup_clean_chain = True |
||||
self.num_nodes = 1 |
||||
|
||||
def run_test(self): |
||||
"""Main test logic""" |
||||
|
||||
self.log.info("Compare responses from getinfo RPC and `bitcoin-cli getinfo`") |
||||
cli_get_info = self.nodes[0].cli.getinfo() |
||||
rpc_get_info = self.nodes[0].getinfo() |
||||
|
||||
assert_equal(cli_get_info, rpc_get_info) |
||||
|
||||
if __name__ == '__main__': |
||||
TestBitcoinCli().main() |
@ -0,0 +1,190 @@
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env python3 |
||||
# Copyright (c) 2017 The Bitcoin Core developers |
||||
# Distributed under the MIT software license, see the accompanying |
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. |
||||
"""Class for bitcoind node under test""" |
||||
|
||||
import decimal |
||||
import errno |
||||
import http.client |
||||
import json |
||||
import logging |
||||
import os |
||||
import subprocess |
||||
import time |
||||
|
||||
from .util import ( |
||||
assert_equal, |
||||
get_rpc_proxy, |
||||
rpc_url, |
||||
wait_until, |
||||
) |
||||
from .authproxy import JSONRPCException |
||||
|
||||
BITCOIND_PROC_WAIT_TIMEOUT = 60 |
||||
|
||||
class TestNode(): |
||||
"""A class for representing a bitcoind node under test. |
||||
|
||||
This class contains: |
||||
|
||||
- state about the node (whether it's running, etc) |
||||
- a Python subprocess.Popen object representing the running process |
||||
- an RPC connection to the node |
||||
|
||||
To make things easier for the test writer, a bit of magic is happening under the covers. |
||||
Any unrecognised messages will be dispatched to the RPC connection.""" |
||||
|
||||
def __init__(self, i, dirname, extra_args, rpchost, timewait, binary, stderr, mocktime, coverage_dir): |
||||
self.index = i |
||||
self.datadir = os.path.join(dirname, "node" + str(i)) |
||||
self.rpchost = rpchost |
||||
if timewait: |
||||
self.rpc_timeout = timewait |
||||
else: |
||||
# Wait for up to 60 seconds for the RPC server to respond |
||||
self.rpc_timeout = 60 |
||||
if binary is None: |
||||
self.binary = os.getenv("BITCOIND", "bitcoind") |
||||
else: |
||||
self.binary = binary |
||||
self.stderr = stderr |
||||
self.coverage_dir = coverage_dir |
||||
# Most callers will just need to add extra args to the standard list below. For those callers that need more flexibity, they can just set the args property directly. |
||||
self.extra_args = extra_args |
||||
self.args = [self.binary, "-datadir=" + self.datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(mocktime), "-uacomment=testnode%d" % i] |
||||
|
||||
self.cli = TestNodeCLI(os.getenv("BITCOINCLI", "bitcoin-cli"), self.datadir) |
||||
|
||||
self.running = False |
||||
self.process = None |
||||
self.rpc_connected = False |
||||
self.rpc = None |
||||
self.url = None |
||||
self.log = logging.getLogger('TestFramework.node%d' % i) |
||||
|
||||
def __getattr__(self, *args, **kwargs): |
||||
"""Dispatches any unrecognised messages to the RPC connection.""" |
||||
assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection" |
||||
return self.rpc.__getattr__(*args, **kwargs) |
||||
|
||||
def start(self, extra_args=None, stderr=None): |
||||
"""Start the node.""" |
||||
if extra_args is None: |
||||
extra_args = self.extra_args |
||||
if stderr is None: |
||||
stderr = self.stderr |
||||
self.process = subprocess.Popen(self.args + extra_args, stderr=stderr) |
||||
self.running = True |
||||
self.log.debug("bitcoind started, waiting for RPC to come up") |
||||
|
||||
def wait_for_rpc_connection(self): |
||||
"""Sets up an RPC connection to the bitcoind process. Returns False if unable to connect.""" |
||||
# Poll at a rate of four times per second |
||||
poll_per_s = 4 |
||||
for _ in range(poll_per_s * self.rpc_timeout): |
||||
assert self.process.poll() is None, "bitcoind exited with status %i during initialization" % self.process.returncode |
||||
try: |
||||
self.rpc = get_rpc_proxy(rpc_url(self.datadir, self.index, self.rpchost), self.index, timeout=self.rpc_timeout, coveragedir=self.coverage_dir) |
||||
self.rpc.getblockcount() |
||||
# If the call to getblockcount() succeeds then the RPC connection is up |
||||
self.rpc_connected = True |
||||
self.url = self.rpc.url |
||||
self.log.debug("RPC successfully started") |
||||
return |
||||
except IOError as e: |
||||
if e.errno != errno.ECONNREFUSED: # Port not yet open? |
||||
raise # unknown IO error |
||||
except JSONRPCException as e: # Initialization phase |
||||
if e.error['code'] != -28: # RPC in warmup? |
||||
raise # unknown JSON RPC exception |
||||
except ValueError as e: # cookie file not found and no rpcuser or rpcassword. bitcoind still starting |
||||
if "No RPC credentials" not in str(e): |
||||
raise |
||||
time.sleep(1.0 / poll_per_s) |
||||
raise AssertionError("Unable to connect to bitcoind") |
||||
|
||||
def get_wallet_rpc(self, wallet_name): |
||||
assert self.rpc_connected |
||||
assert self.rpc |
||||
wallet_path = "wallet/%s" % wallet_name |
||||
return self.rpc / wallet_path |
||||
|
||||
def stop_node(self): |
||||
"""Stop the node.""" |
||||
if not self.running: |
||||
return |
||||
self.log.debug("Stopping node") |
||||
try: |
||||
self.stop() |
||||
except http.client.CannotSendRequest: |
||||
self.log.exception("Unable to stop node.") |
||||
|
||||
def is_node_stopped(self): |
||||
"""Checks whether the node has stopped. |
||||
|
||||
Returns True if the node has stopped. False otherwise. |
||||
This method is responsible for freeing resources (self.process).""" |
||||
if not self.running: |
||||
return True |
||||
return_code = self.process.poll() |
||||
if return_code is None: |
||||
return False |
||||
|
||||
# process has stopped. Assert that it didn't return an error code. |
||||
assert_equal(return_code, 0) |
||||
self.running = False |
||||
self.process = None |
||||
self.rpc_connected = False |
||||
self.rpc = None |
||||
self.log.debug("Node stopped") |
||||
return True |
||||
|
||||
def wait_until_stopped(self, timeout=BITCOIND_PROC_WAIT_TIMEOUT): |
||||
wait_until(self.is_node_stopped, timeout=timeout) |
||||
|
||||
def node_encrypt_wallet(self, passphrase): |
||||
""""Encrypts the wallet. |
||||
|
||||
This causes bitcoind to shutdown, so this method takes |
||||
care of cleaning up resources.""" |
||||
self.encryptwallet(passphrase) |
||||
self.wait_until_stopped() |
||||
|
||||
class TestNodeCLI(): |
||||
"""Interface to bitcoin-cli for an individual node""" |
||||
|
||||
def __init__(self, binary, datadir): |
||||
self.args = [] |
||||
self.binary = binary |
||||
self.datadir = datadir |
||||
self.input = None |
||||
|
||||
def __call__(self, *args, input=None): |
||||
# TestNodeCLI is callable with bitcoin-cli command-line args |
||||
self.args = [str(arg) for arg in args] |
||||
self.input = input |
||||
return self |
||||
|
||||
def __getattr__(self, command): |
||||
def dispatcher(*args, **kwargs): |
||||
return self.send_cli(command, *args, **kwargs) |
||||
return dispatcher |
||||
|
||||
def send_cli(self, command, *args, **kwargs): |
||||
"""Run bitcoin-cli command. Deserializes returned string as python object.""" |
||||
|
||||
pos_args = [str(arg) for arg in args] |
||||
named_args = [str(key) + "=" + str(value) for (key, value) in kwargs.items()] |
||||
assert not (pos_args and named_args), "Cannot use positional arguments and named arguments in the same bitcoin-cli call" |
||||
p_args = [self.binary, "-datadir=" + self.datadir] + self.args |
||||
if named_args: |
||||
p_args += ["-named"] |
||||
p_args += [command] + pos_args + named_args |
||||
process = subprocess.Popen(p_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) |
||||
cli_stdout, cli_stderr = process.communicate(input=self.input) |
||||
returncode = process.poll() |
||||
if returncode: |
||||
# Ignore cli_stdout, raise with cli_stderr |
||||
raise subprocess.CalledProcessError(returncode, self.binary, output=cli_stderr) |
||||
return json.loads(cli_stdout, parse_float=decimal.Decimal) |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue