mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
Merge pull request #4610 from vijaydasmp/bp196
merge bitcoin #16953 #16918 #16917 #16898 #14696 #16888 #16737 #16404 #15687 #16294 : Backport
This commit is contained in:
commit
8489da58e6
@ -9,6 +9,7 @@ task:
|
|||||||
MAKEJOBS: "-j9"
|
MAKEJOBS: "-j9"
|
||||||
CONFIGURE_OPTS: "--disable-dependency-tracking"
|
CONFIGURE_OPTS: "--disable-dependency-tracking"
|
||||||
GOAL: "install"
|
GOAL: "install"
|
||||||
|
TEST_RUNNER_PORT_MIN: "14000" # Must be larger than 12321, which is used for the http cache. See https://cirrus-ci.org/guide/writing-tasks/#http-cache
|
||||||
CCACHE_SIZE: "200M"
|
CCACHE_SIZE: "200M"
|
||||||
CCACHE_COMPRESS: 1
|
CCACHE_COMPRESS: 1
|
||||||
CCACHE_DIR: "/tmp/ccache_dir"
|
CCACHE_DIR: "/tmp/ccache_dir"
|
||||||
|
@ -154,7 +154,9 @@ using other means such as firewalling.
|
|||||||
|
|
||||||
Note that when the block chain tip changes, a reorganisation may occur
|
Note that when the block chain tip changes, a reorganisation may occur
|
||||||
and just the tip will be notified. It is up to the subscriber to
|
and just the tip will be notified. It is up to the subscriber to
|
||||||
retrieve the chain from the last known block to the new tip.
|
retrieve the chain from the last known block to the new tip. Also note
|
||||||
|
that no notification occurs if the tip was in the active chain - this
|
||||||
|
is the case after calling invalidateblock RPC.
|
||||||
|
|
||||||
There are several possibilities that ZMQ notification can get lost
|
There are several possibilities that ZMQ notification can get lost
|
||||||
during transmission depending on the communication type you are
|
during transmission depending on the communication type you are
|
||||||
|
@ -28,7 +28,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state)
|
|||||||
if (tx.vExtraPayload.size() > MAX_TX_EXTRA_PAYLOAD)
|
if (tx.vExtraPayload.size() > MAX_TX_EXTRA_PAYLOAD)
|
||||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-payload-oversize");
|
return state.DoS(100, false, REJECT_INVALID, "bad-txns-payload-oversize");
|
||||||
|
|
||||||
// Check for negative or overflow output values
|
// Check for negative or overflow output values (see CVE-2010-5139)
|
||||||
CAmount nValueOut = 0;
|
CAmount nValueOut = 0;
|
||||||
for (const auto& txout : tx.vout) {
|
for (const auto& txout : tx.vout) {
|
||||||
if (txout.nValue < 0)
|
if (txout.nValue < 0)
|
||||||
|
@ -3220,7 +3220,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||||||
}
|
}
|
||||||
AddOrphanTx(ptx, pfrom->GetId());
|
AddOrphanTx(ptx, pfrom->GetId());
|
||||||
|
|
||||||
// DoS prevention: do not allow mapOrphanTransactions to grow unbounded
|
// DoS prevention: do not allow mapOrphanTransactions to grow unbounded (see CVE-2012-3789)
|
||||||
unsigned int nMaxOrphanTxSize = (unsigned int)std::max((int64_t)0, gArgs.GetArg("-maxorphantxsize", DEFAULT_MAX_ORPHAN_TRANSACTIONS_SIZE)) * 1000000;
|
unsigned int nMaxOrphanTxSize = (unsigned int)std::max((int64_t)0, gArgs.GetArg("-maxorphantxsize", DEFAULT_MAX_ORPHAN_TRANSACTIONS_SIZE)) * 1000000;
|
||||||
unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTxSize);
|
unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTxSize);
|
||||||
if (nEvicted > 0) {
|
if (nEvicted > 0) {
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include <qt/networkstyle.h>
|
#include <qt/networkstyle.h>
|
||||||
#include <qt/rpcconsole.h>
|
#include <qt/rpcconsole.h>
|
||||||
#include <shutdown.h>
|
#include <shutdown.h>
|
||||||
|
#include <test/setup_common.h>
|
||||||
|
#include <univalue.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
|
||||||
#if defined(HAVE_CONFIG_H)
|
#if defined(HAVE_CONFIG_H)
|
||||||
@ -31,8 +33,6 @@
|
|||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QtTest/QtTestWidgets>
|
#include <QtTest/QtTestWidgets>
|
||||||
#include <QtTest/QtTestGui>
|
#include <QtTest/QtTestGui>
|
||||||
#include <string>
|
|
||||||
#include <univalue.h>
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
//! Call getblockchaininfo RPC and check first field of JSON output.
|
//! Call getblockchaininfo RPC and check first field of JSON output.
|
||||||
@ -67,6 +67,7 @@ void AppTests::appTests()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
BasicTestingSetup test{CBaseChainParams::REGTEST}; // Create a temp data directory to backup the gui settings to
|
||||||
ECC_Stop(); // Already started by the common test setup, so stop it to avoid interference
|
ECC_Stop(); // Already started by the common test setup, so stop it to avoid interference
|
||||||
LogInstance().DisconnectTestLogger();
|
LogInstance().DisconnectTestLogger();
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include <random.h>
|
#include <random.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
#include <script/standard.h>
|
#include <script/standard.h>
|
||||||
#include <util/system.h>
|
#include <test/setup_common.h>
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
|
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
@ -66,7 +66,7 @@ static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsig
|
|||||||
|
|
||||||
void PaymentServerTests::paymentServerTests()
|
void PaymentServerTests::paymentServerTests()
|
||||||
{
|
{
|
||||||
SelectParams(CBaseChainParams::MAIN);
|
BasicTestingSetup testing_setup(CBaseChainParams::MAIN);
|
||||||
auto node = interfaces::MakeNode();
|
auto node = interfaces::MakeNode();
|
||||||
OptionsModel optionsModel(*node);
|
OptionsModel optionsModel(*node);
|
||||||
PaymentServer* server = new PaymentServer(nullptr, false);
|
PaymentServer* server = new PaymentServer(nullptr, false);
|
||||||
|
@ -40,9 +40,6 @@ void RPCNestedTests::rpcNestedTests()
|
|||||||
tableRPC.appendCommand("rpcNestedTest", &vRPCCommands[0]);
|
tableRPC.appendCommand("rpcNestedTest", &vRPCCommands[0]);
|
||||||
//mempool.setSanityCheck(1.0);
|
//mempool.setSanityCheck(1.0);
|
||||||
|
|
||||||
ECC_Stop(); // Already started by the common test setup, so stop it to avoid interference
|
|
||||||
LogInstance().DisconnectTestLogger();
|
|
||||||
|
|
||||||
TestingSetup test;
|
TestingSetup test;
|
||||||
|
|
||||||
if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished();
|
if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished();
|
||||||
|
@ -44,12 +44,18 @@ Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void noui_connect();
|
|
||||||
|
|
||||||
// This is all you need to run all the tests
|
// This is all you need to run all the tests
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
BasicTestingSetup test{CBaseChainParams::REGTEST};
|
// Initialize persistent globals with the testing setup state for sanity.
|
||||||
|
// E.g. -datadir in gArgs is set to a temp directory dummy value (instead
|
||||||
|
// of defaulting to the default datadir), or globalChainParams is set to
|
||||||
|
// regtest params.
|
||||||
|
//
|
||||||
|
// All tests must use their own testing setup (if needed).
|
||||||
|
{
|
||||||
|
BasicTestingSetup dummy{CBaseChainParams::REGTEST};
|
||||||
|
}
|
||||||
|
|
||||||
auto node = interfaces::MakeNode();
|
auto node = interfaces::MakeNode();
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
|
|||||||
opcode == OP_MUL ||
|
opcode == OP_MUL ||
|
||||||
opcode == OP_LSHIFT ||
|
opcode == OP_LSHIFT ||
|
||||||
opcode == OP_RSHIFT)
|
opcode == OP_RSHIFT)
|
||||||
return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes.
|
return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes (CVE-2010-5137).
|
||||||
|
|
||||||
// With SCRIPT_VERIFY_CONST_SCRIPTCODE, OP_CODESEPARATOR is rejected even in an unexecuted branch
|
// With SCRIPT_VERIFY_CONST_SCRIPTCODE, OP_CODESEPARATOR is rejected even in an unexecuted branch
|
||||||
if (opcode == OP_CODESEPARATOR && sigversion == SigVersion::BASE && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE))
|
if (opcode == OP_CODESEPARATOR && sigversion == SigVersion::BASE && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE))
|
||||||
@ -1599,6 +1599,8 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
|
|||||||
return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
|
return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scriptSig and scriptPubKey must be evaluated sequentially on the same stack
|
||||||
|
// rather than being simply concatenated (see CVE-2010-5141)
|
||||||
std::vector<std::vector<unsigned char> > stack, stackCopy;
|
std::vector<std::vector<unsigned char> > stack, stackCopy;
|
||||||
if (!EvalScript(stack, scriptSig, flags, checker, SigVersion::BASE, serror))
|
if (!EvalScript(stack, scriptSig, flags, checker, SigVersion::BASE, serror))
|
||||||
// serror is set
|
// serror is set
|
||||||
|
@ -1,3 +1,15 @@
|
|||||||
|
# Unit tests
|
||||||
|
|
||||||
|
The sources in this directory are unit test cases. Boost includes a
|
||||||
|
unit testing framework, and since Dash Core already uses Boost, it makes
|
||||||
|
sense to simply use this framework rather than require developers to
|
||||||
|
configure some other framework (we want as few impediments to creating
|
||||||
|
unit tests as possible).
|
||||||
|
|
||||||
|
The build system is set up to compile an executable called `test_dash`
|
||||||
|
that runs all of the unit tests. The main source file is called
|
||||||
|
`setup_common.cpp`.
|
||||||
|
|
||||||
### Compiling/running unit tests
|
### Compiling/running unit tests
|
||||||
|
|
||||||
Unit tests will be automatically compiled if dependencies were met in `./configure`
|
Unit tests will be automatically compiled if dependencies were met in `./configure`
|
||||||
@ -12,7 +24,7 @@ to run the dashd tests.
|
|||||||
|
|
||||||
To add more dashd tests, add `BOOST_AUTO_TEST_CASE` functions to the existing
|
To add more dashd tests, add `BOOST_AUTO_TEST_CASE` functions to the existing
|
||||||
.cpp files in the `test/` directory or add new .cpp files that
|
.cpp files in the `test/` directory or add new .cpp files that
|
||||||
implement new BOOST_AUTO_TEST_SUITE sections.
|
implement new `BOOST_AUTO_TEST_SUITE` sections.
|
||||||
|
|
||||||
To run the dash-qt tests manually, launch `src/qt/test/test_dash-qt`
|
To run the dash-qt tests manually, launch `src/qt/test/test_dash-qt`
|
||||||
|
|
||||||
@ -32,20 +44,24 @@ example, to run just the getarg_tests verbosely:
|
|||||||
|
|
||||||
Run `test_dash --help` for the full list.
|
Run `test_dash --help` for the full list.
|
||||||
|
|
||||||
### Note on adding test cases
|
### Adding test cases
|
||||||
|
|
||||||
The sources in this directory are unit test cases. Boost includes a
|
To add a new unit test file to our test suite you need
|
||||||
unit testing framework, and since Dash Core already uses boost, it makes
|
|
||||||
sense to simply use this framework rather than require developers to
|
|
||||||
configure some other framework (we want as few impediments to creating
|
|
||||||
unit tests as possible).
|
|
||||||
|
|
||||||
The build system is setup to compile an executable called `test_dash`
|
|
||||||
that runs all of the unit tests. The main source file is called
|
|
||||||
setup_common.cpp. To add a new unit test file to our test suite you need
|
|
||||||
to add the file to `src/Makefile.test.include`. The pattern is to create
|
to add the file to `src/Makefile.test.include`. The pattern is to create
|
||||||
one test file for each class or source file for which you want to create
|
one test file for each class or source file for which you want to create
|
||||||
unit tests. The file naming convention is `<source_filename>_tests.cpp`
|
unit tests. The file naming convention is `<source_filename>_tests.cpp`
|
||||||
and such files should wrap their tests in a test suite
|
and such files should wrap their tests in a test suite
|
||||||
called `<source_filename>_tests`. For an example of this pattern,
|
called `<source_filename>_tests`. For an example of this pattern,
|
||||||
examine `uint256_tests.cpp`.
|
see `uint256_tests.cpp`.
|
||||||
|
|
||||||
|
### Logging and debugging in unit tests
|
||||||
|
|
||||||
|
To write to logs from unit tests you need to use specific message methods
|
||||||
|
provided by Boost. The simplest is `BOOST_TEST_MESSAGE`.
|
||||||
|
|
||||||
|
For debugging you can launch the test_dash executable with `gdb`or `lldb` and
|
||||||
|
start debugging, just like you would with dashd:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gdb src/test/test_dash
|
||||||
|
```
|
||||||
|
@ -827,6 +827,9 @@
|
|||||||
["NOP", "2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
|
["NOP", "2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
|
||||||
["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
|
["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
|
||||||
|
|
||||||
|
["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
|
||||||
|
|
||||||
|
["TEST DISABLED OP CODES (CVE-2010-5137)"],
|
||||||
["'a' 'bc'", "CAT", "P2SH,STRICTENC", "DISABLED_OPCODE"],
|
["'a' 'bc'", "CAT", "P2SH,STRICTENC", "DISABLED_OPCODE"],
|
||||||
["'abc' 'a' 'bc'", "CAT EQUAL", "P2SH,STRICTENC,DIP0020_OPCODES", "OK"],
|
["'abc' 'a' 'bc'", "CAT EQUAL", "P2SH,STRICTENC,DIP0020_OPCODES", "OK"],
|
||||||
["'' '' ''", "CAT EQUAL", "P2SH,STRICTENC,DIP0020_OPCODES", "OK"],
|
["'' '' ''", "CAT EQUAL", "P2SH,STRICTENC,DIP0020_OPCODES", "OK"],
|
||||||
@ -909,9 +912,6 @@
|
|||||||
["0x05 0x0100800080", "BIN2NUM -8388609 EQUAL", "P2SH,STRICTENC,DIP0020_OPCODES", "OK", "Ensure significant zero bytes are retained"],
|
["0x05 0x0100800080", "BIN2NUM -8388609 EQUAL", "P2SH,STRICTENC,DIP0020_OPCODES", "OK", "Ensure significant zero bytes are retained"],
|
||||||
["0x05 0x01000f0000", "BIN2NUM 983041 EQUAL", "P2SH,STRICTENC,DIP0020_OPCODES", "OK", "Ensure significant zero bytes are retained"],
|
["0x05 0x01000f0000", "BIN2NUM 983041 EQUAL", "P2SH,STRICTENC,DIP0020_OPCODES", "OK", "Ensure significant zero bytes are retained"],
|
||||||
["0x05 0x01000f0080", "BIN2NUM -983041 EQUAL", "P2SH,STRICTENC,DIP0020_OPCODES", "OK", "Ensure significant zero bytes are retained"],
|
["0x05 0x01000f0080", "BIN2NUM -983041 EQUAL", "P2SH,STRICTENC,DIP0020_OPCODES", "OK", "Ensure significant zero bytes are retained"],
|
||||||
|
|
||||||
["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
|
|
||||||
|
|
||||||
["Disabled opcodes"],
|
["Disabled opcodes"],
|
||||||
["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "INVERT disabled"],
|
["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "INVERT disabled"],
|
||||||
["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2MUL disabled"],
|
["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2MUL disabled"],
|
||||||
|
@ -2068,7 +2068,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||||||
// If such overwrites are allowed, coinbases and transactions depending upon those
|
// If such overwrites are allowed, coinbases and transactions depending upon those
|
||||||
// can be duplicated to remove the ability to spend the first instance -- even after
|
// can be duplicated to remove the ability to spend the first instance -- even after
|
||||||
// being sent to another address.
|
// being sent to another address.
|
||||||
// See BIP30 and http://r6.ca/blog/20120206T005236Z.html for more information.
|
// See BIP30, CVE-2012-1909, and http://r6.ca/blog/20120206T005236Z.html for more information.
|
||||||
// This logic is not necessary for memory pool transactions, as AcceptToMemoryPool
|
// This logic is not necessary for memory pool transactions, as AcceptToMemoryPool
|
||||||
// already refuses previously-known transaction ids entirely.
|
// already refuses previously-known transaction ids entirely.
|
||||||
// This rule was originally applied to all blocks with a timestamp after March 15, 2012, 0:00 UTC.
|
// This rule was originally applied to all blocks with a timestamp after March 15, 2012, 0:00 UTC.
|
||||||
@ -3755,6 +3755,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
|
|||||||
return state.DoS(100, false, REJECT_INVALID, "bad-cb-multiple", false, "more than one coinbase");
|
return state.DoS(100, false, REJECT_INVALID, "bad-cb-multiple", false, "more than one coinbase");
|
||||||
|
|
||||||
// Check transactions
|
// Check transactions
|
||||||
|
// Must check for duplicate inputs (see CVE-2018-17144)
|
||||||
for (const auto& tx : block.vtx)
|
for (const auto& tx : block.vtx)
|
||||||
if (!CheckTransaction(*tx, state))
|
if (!CheckTransaction(*tx, state))
|
||||||
return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(),
|
return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(),
|
||||||
|
@ -141,8 +141,10 @@ killall dashd
|
|||||||
|
|
||||||
##### Test logging
|
##### Test logging
|
||||||
|
|
||||||
The tests contain logging at different levels (debug, info, warning, etc). By
|
The tests contain logging at five different levels (DEBUG, INFO, WARNING, ERROR
|
||||||
default:
|
and CRITICAL). From within your functional tests you can log to these different
|
||||||
|
levels using the logger included in the test_framework, e.g.
|
||||||
|
`self.log.debug(object)`. By default:
|
||||||
|
|
||||||
- when run through the test_runner harness, *all* logs are written to
|
- when run through the test_runner harness, *all* logs are written to
|
||||||
`test_framework.log` and no logs are output to the console.
|
`test_framework.log` and no logs are output to the console.
|
||||||
@ -187,18 +189,32 @@ call methods that interact with the dashd nodes-under-test.
|
|||||||
If further introspection of the dashd instances themselves becomes
|
If further introspection of the dashd instances themselves becomes
|
||||||
necessary, this can be accomplished by first setting a pdb breakpoint
|
necessary, this can be accomplished by first setting a pdb breakpoint
|
||||||
at an appropriate location, running the test to that point, then using
|
at an appropriate location, running the test to that point, then using
|
||||||
`gdb` to attach to the process and debug.
|
`gdb` (or `lldb` on macOS) to attach to the process and debug.
|
||||||
|
|
||||||
For instance, to attach to `self.node[1]` during a run:
|
For instance, to attach to `self.node[1]` during a run you can get
|
||||||
|
the pid of the node within `pdb`.
|
||||||
|
|
||||||
|
```
|
||||||
|
(pdb) self.node[1].process.pid
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can find the pid by inspecting the temp folder for the specific test
|
||||||
|
you are running. The path to that folder is printed at the beginning of every
|
||||||
|
test run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
2017-06-27 14:13:56.686000 TestFramework (INFO): Initializing test directory /tmp/user/1000/testo9vsdjo3
|
2017-06-27 14:13:56.686000 TestFramework (INFO): Initializing test directory /tmp/user/1000/testo9vsdjo3
|
||||||
```
|
```
|
||||||
|
|
||||||
use the directory path to get the pid from the pid file:
|
Use the path to find the pid file in the temp folder:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cat /tmp/user/1000/testo9vsdjo3/node1/regtest/dashd.pid
|
cat /tmp/user/1000/testo9vsdjo3/node1/regtest/dashd.pid
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you can use the pid to start `gdb`:
|
||||||
|
|
||||||
|
```bash
|
||||||
gdb /home/example/dashd <pid>
|
gdb /home/example/dashd <pid>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ from test_framework.messages import (
|
|||||||
CTxIn,
|
CTxIn,
|
||||||
CTxOut,
|
CTxOut,
|
||||||
msg_block,
|
msg_block,
|
||||||
msg_headers
|
msg_headers,
|
||||||
)
|
)
|
||||||
from test_framework.mininode import P2PInterface
|
from test_framework.mininode import P2PInterface
|
||||||
from test_framework.script import (CScript, OP_TRUE)
|
from test_framework.script import (CScript, OP_TRUE)
|
||||||
@ -190,7 +190,7 @@ class AssumeValidTest(BitcoinTestFramework):
|
|||||||
for i in range(200):
|
for i in range(200):
|
||||||
p2p1.send_message(msg_block(self.blocks[i]))
|
p2p1.send_message(msg_block(self.blocks[i]))
|
||||||
# Syncing so many blocks can take a while on slow systems. Give it plenty of time to sync.
|
# Syncing so many blocks can take a while on slow systems. Give it plenty of time to sync.
|
||||||
p2p1.sync_with_ping(300)
|
p2p1.sync_with_ping(960)
|
||||||
assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 200)
|
assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 200)
|
||||||
|
|
||||||
# Send blocks to node2. Block 102 will be rejected.
|
# Send blocks to node2. Block 102 will be rejected.
|
||||||
|
@ -765,7 +765,7 @@ class FullBlockTest(BitcoinTestFramework):
|
|||||||
#
|
#
|
||||||
# Blocks are not allowed to contain a transaction whose id matches that of an earlier,
|
# Blocks are not allowed to contain a transaction whose id matches that of an earlier,
|
||||||
# not-fully-spent transaction in the same chain. To test, make identical coinbases;
|
# not-fully-spent transaction in the same chain. To test, make identical coinbases;
|
||||||
# the second one should be rejected.
|
# the second one should be rejected. See also CVE-2012-1909.
|
||||||
#
|
#
|
||||||
self.log.info("Reject a block with a transaction with a duplicate hash of a previous transaction (BIP30)")
|
self.log.info("Reject a block with a transaction with a duplicate hash of a previous transaction (BIP30)")
|
||||||
self.move_tip(60)
|
self.move_tip(60)
|
||||||
|
@ -50,7 +50,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
|
|||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
self.num_nodes = 4
|
self.num_nodes = 4
|
||||||
self.setup_clean_chain = False
|
self.setup_clean_chain = False
|
||||||
self.rpc_timeout = 180
|
self.rpc_timeout = 480
|
||||||
|
|
||||||
# Set -maxmempool=0 to turn off mempool memory sharing with dbcache
|
# Set -maxmempool=0 to turn off mempool memory sharing with dbcache
|
||||||
# Set -rpcservertimeout=900 to reduce socket disconnects in this
|
# Set -rpcservertimeout=900 to reduce socket disconnects in this
|
||||||
|
@ -7,7 +7,11 @@ import os
|
|||||||
|
|
||||||
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
|
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal, wait_until, connect_nodes_bi
|
from test_framework.util import (
|
||||||
|
assert_equal,
|
||||||
|
wait_until,
|
||||||
|
connect_nodes,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class NotificationsTest(BitcoinTestFramework):
|
class NotificationsTest(BitcoinTestFramework):
|
||||||
@ -59,7 +63,7 @@ class NotificationsTest(BitcoinTestFramework):
|
|||||||
self.log.info("test -walletnotify after rescan")
|
self.log.info("test -walletnotify after rescan")
|
||||||
# restart node to rescan to force wallet notifications
|
# restart node to rescan to force wallet notifications
|
||||||
self.start_node(1)
|
self.start_node(1)
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
|
||||||
wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
|
wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ class PruneTest(BitcoinTestFramework):
|
|||||||
["-dip3params=2000:2000", "-dip8params=2000", "-disablegovernance","-txindex=0","-maxreceivebuffer=20000","-blockmaxsize=999000"],
|
["-dip3params=2000:2000", "-dip8params=2000", "-disablegovernance","-txindex=0","-maxreceivebuffer=20000","-blockmaxsize=999000"],
|
||||||
["-dip3params=2000:2000", "-dip8params=2000", "-disablegovernance","-txindex=0","-prune=550"],
|
["-dip3params=2000:2000", "-dip8params=2000", "-disablegovernance","-txindex=0","-prune=550"],
|
||||||
]
|
]
|
||||||
|
self.rpc_timeout = 120
|
||||||
|
|
||||||
def skip_test_if_missing_module(self):
|
def skip_test_if_missing_module(self):
|
||||||
self.skip_if_no_wallet()
|
self.skip_if_no_wallet()
|
||||||
|
@ -12,11 +12,10 @@ from test_framework.test_framework import BitcoinTestFramework
|
|||||||
from test_framework.messages import dashhash
|
from test_framework.messages import dashhash
|
||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_equal,
|
assert_equal,
|
||||||
|
connect_nodes,
|
||||||
hash256,
|
hash256,
|
||||||
)
|
)
|
||||||
|
|
||||||
ADDRESS = "tcp://127.0.0.1:28332"
|
|
||||||
|
|
||||||
def dashhash_helper(b):
|
def dashhash_helper(b):
|
||||||
return encode(dashhash(b)[::-1], 'hex_codec').decode('ascii')
|
return encode(dashhash(b)[::-1], 'hex_codec').decode('ascii')
|
||||||
|
|
||||||
@ -48,62 +47,59 @@ class ZMQTest (BitcoinTestFramework):
|
|||||||
self.skip_if_no_py3_zmq()
|
self.skip_if_no_py3_zmq()
|
||||||
self.skip_if_no_bitcoind_zmq()
|
self.skip_if_no_bitcoind_zmq()
|
||||||
|
|
||||||
def setup_nodes(self):
|
def run_test(self):
|
||||||
import zmq
|
import zmq
|
||||||
|
self.ctx = zmq.Context()
|
||||||
|
try:
|
||||||
|
self.test_basic()
|
||||||
|
self.test_reorg()
|
||||||
|
finally:
|
||||||
|
# Destroy the ZMQ context.
|
||||||
|
self.log.debug("Destroying ZMQ context")
|
||||||
|
self.ctx.destroy(linger=None)
|
||||||
|
|
||||||
# Initialize ZMQ context and socket.
|
def test_basic(self):
|
||||||
# All messages are received in the same socket which means
|
# All messages are received in the same socket which means
|
||||||
# that this test fails if the publishing order changes.
|
# that this test fails if the publishing order changes.
|
||||||
# Note that the publishing order is not defined in the documentation and
|
# Note that the publishing order is not defined in the documentation and
|
||||||
# is subject to change.
|
# is subject to change.
|
||||||
self.zmq_context = zmq.Context()
|
import zmq
|
||||||
socket = self.zmq_context.socket(zmq.SUB)
|
address = 'tcp://127.0.0.1:28332'
|
||||||
|
socket = self.ctx.socket(zmq.SUB)
|
||||||
socket.set(zmq.RCVTIMEO, 60000)
|
socket.set(zmq.RCVTIMEO, 60000)
|
||||||
socket.connect(ADDRESS)
|
socket.connect(address)
|
||||||
|
|
||||||
# Subscribe to all available topics.
|
# Subscribe to all available topics.
|
||||||
self.hashblock = ZMQSubscriber(socket, b"hashblock")
|
hashblock = ZMQSubscriber(socket, b"hashblock")
|
||||||
self.hashtx = ZMQSubscriber(socket, b"hashtx")
|
hashtx = ZMQSubscriber(socket, b"hashtx")
|
||||||
self.rawblock = ZMQSubscriber(socket, b"rawblock")
|
rawblock = ZMQSubscriber(socket, b"rawblock")
|
||||||
self.rawtx = ZMQSubscriber(socket, b"rawtx")
|
rawtx = ZMQSubscriber(socket, b"rawtx")
|
||||||
|
|
||||||
self.extra_args = [
|
|
||||||
["-zmqpub%s=%s" % (sub.topic.decode(), ADDRESS) for sub in [self.hashblock, self.hashtx, self.rawblock, self.rawtx]],
|
|
||||||
[]
|
|
||||||
]
|
|
||||||
self.add_nodes(self.num_nodes, self.extra_args)
|
|
||||||
self.start_nodes()
|
|
||||||
|
|
||||||
def run_test(self):
|
self.restart_node(0, ["-zmqpub%s=%s" % (sub.topic.decode(), address) for sub in [hashblock, hashtx, rawblock, rawtx]])
|
||||||
try:
|
connect_nodes(self.nodes[0], 1)
|
||||||
self._zmq_test()
|
|
||||||
finally:
|
|
||||||
# Destroy the ZMQ context.
|
|
||||||
self.log.debug("Destroying ZMQ context")
|
|
||||||
self.zmq_context.destroy(linger=None)
|
|
||||||
|
|
||||||
def _zmq_test(self):
|
|
||||||
num_blocks = 5
|
num_blocks = 5
|
||||||
self.log.info("Generate %(n)d blocks (and %(n)d coinbase txes)" % {"n": num_blocks})
|
self.log.info("Generate %(n)d blocks (and %(n)d coinbase txes)" % {"n": num_blocks})
|
||||||
genhashes = self.nodes[0].generatetoaddress(num_blocks, ADDRESS_BCRT1_UNSPENDABLE)
|
genhashes = self.nodes[0].generatetoaddress(num_blocks, ADDRESS_BCRT1_UNSPENDABLE)
|
||||||
|
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
for x in range(num_blocks):
|
for x in range(num_blocks):
|
||||||
# Should receive the coinbase txid.
|
# Should receive the coinbase txid.
|
||||||
txid = self.hashtx.receive()
|
txid = hashtx.receive()
|
||||||
|
|
||||||
# Should receive the coinbase raw transaction.
|
# Should receive the coinbase raw transaction.
|
||||||
hex = self.rawtx.receive()
|
hex = rawtx.receive()
|
||||||
assert_equal(hash256(hex), txid)
|
assert_equal(hash256(hex), txid)
|
||||||
|
|
||||||
# Should receive the generated block hash.
|
# Should receive the generated block hash.
|
||||||
hash = self.hashblock.receive().hex()
|
hash = hashblock.receive().hex()
|
||||||
assert_equal(genhashes[x], hash)
|
assert_equal(genhashes[x], hash)
|
||||||
# The block should only have the coinbase txid.
|
# The block should only have the coinbase txid.
|
||||||
assert_equal([txid.hex()], self.nodes[1].getblock(hash)["tx"])
|
assert_equal([txid.hex()], self.nodes[1].getblock(hash)["tx"])
|
||||||
|
|
||||||
# Should receive the generated raw block.
|
# Should receive the generated raw block.
|
||||||
block = self.rawblock.receive()
|
block = rawblock.receive()
|
||||||
assert_equal(genhashes[x], dashhash_helper(block[:80]))
|
assert_equal(genhashes[x], dashhash_helper(block[:80]))
|
||||||
|
|
||||||
if self.is_wallet_compiled():
|
if self.is_wallet_compiled():
|
||||||
@ -112,23 +108,47 @@ class ZMQTest (BitcoinTestFramework):
|
|||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
# Should receive the broadcasted txid.
|
# Should receive the broadcasted txid.
|
||||||
txid = self.hashtx.receive()
|
txid = hashtx.receive()
|
||||||
assert_equal(payment_txid, txid.hex())
|
assert_equal(payment_txid, txid.hex())
|
||||||
|
|
||||||
# Should receive the broadcasted raw transaction.
|
# Should receive the broadcasted raw transaction.
|
||||||
hex = self.rawtx.receive()
|
hex = rawtx.receive()
|
||||||
assert_equal(payment_txid, hash256(hex).hex())
|
assert_equal(payment_txid, hash256(hex).hex())
|
||||||
|
|
||||||
|
|
||||||
self.log.info("Test the getzmqnotifications RPC")
|
self.log.info("Test the getzmqnotifications RPC")
|
||||||
assert_equal(self.nodes[0].getzmqnotifications(), [
|
assert_equal(self.nodes[0].getzmqnotifications(), [
|
||||||
{"type": "pubhashblock", "address": ADDRESS, "hwm": 1000},
|
{"type": "pubhashblock", "address": address, "hwm": 1000},
|
||||||
{"type": "pubhashtx", "address": ADDRESS, "hwm": 1000},
|
{"type": "pubhashtx", "address": address, "hwm": 1000},
|
||||||
{"type": "pubrawblock", "address": ADDRESS, "hwm": 1000},
|
{"type": "pubrawblock", "address": address, "hwm": 1000},
|
||||||
{"type": "pubrawtx", "address": ADDRESS, "hwm": 1000},
|
{"type": "pubrawtx", "address": address, "hwm": 1000},
|
||||||
])
|
])
|
||||||
|
|
||||||
assert_equal(self.nodes[1].getzmqnotifications(), [])
|
assert_equal(self.nodes[1].getzmqnotifications(), [])
|
||||||
|
|
||||||
|
def test_reorg(self):
|
||||||
|
import zmq
|
||||||
|
address = 'tcp://127.0.0.1:28333'
|
||||||
|
socket = self.ctx.socket(zmq.SUB)
|
||||||
|
socket.set(zmq.RCVTIMEO, 60000)
|
||||||
|
socket.connect(address)
|
||||||
|
hashblock = ZMQSubscriber(socket, b'hashblock')
|
||||||
|
|
||||||
|
# Should only notify the tip if a reorg occurs
|
||||||
|
self.restart_node(0, ['-zmqpub%s=%s' % (hashblock.topic.decode(), address)])
|
||||||
|
|
||||||
|
# Generate 1 block in nodes[0] and receive all notifications
|
||||||
|
self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_UNSPENDABLE)
|
||||||
|
assert_equal(self.nodes[0].getbestblockhash(), hashblock.receive().hex())
|
||||||
|
|
||||||
|
# Generate 2 blocks in nodes[1]
|
||||||
|
self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_UNSPENDABLE)
|
||||||
|
|
||||||
|
# nodes[0] will reorg chain after connecting back nodes[1]
|
||||||
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
|
||||||
|
# Should receive nodes[1] tip
|
||||||
|
assert_equal(self.nodes[1].getbestblockhash(), hashblock.receive().hex())
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
ZMQTest().main()
|
ZMQTest().main()
|
||||||
|
@ -215,6 +215,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
|||||||
rawtxs=[tx.serialize().hex()],
|
rawtxs=[tx.serialize().hex()],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# The following two validations prevent overflow of the output amounts (see CVE-2010-5139).
|
||||||
self.log.info('A transaction with too large output value')
|
self.log.info('A transaction with too large output value')
|
||||||
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference)))
|
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference)))
|
||||||
tx.vout[0].nValue = 21000000 * COIN + 1
|
tx.vout[0].nValue = 21000000 * COIN + 1
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
from test_framework.mininode import P2PInterface
|
from test_framework.mininode import P2PInterface
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal, connect_nodes_bi
|
from test_framework.util import assert_equal, connect_nodes
|
||||||
|
|
||||||
class ConnectDevnetNodes(BitcoinTestFramework):
|
class ConnectDevnetNodes(BitcoinTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
@ -18,13 +18,13 @@ class ConnectDevnetNodes(BitcoinTestFramework):
|
|||||||
self.add_nodes(self.num_nodes)
|
self.add_nodes(self.num_nodes)
|
||||||
self.start_node(0)
|
self.start_node(0)
|
||||||
self.start_node(1)
|
self.start_node(1)
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
self.nodes[0].add_p2p_connection(P2PInterface())
|
self.nodes[0].add_p2p_connection(P2PInterface())
|
||||||
assert_equal(self.nodes[0].getconnectioncount(), 3) # 2 in/out dashd + 1 p2p
|
assert_equal(self.nodes[0].getconnectioncount(), 2) # 1 out dashd + 1 p2p
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -8,7 +8,7 @@ from test_framework.test_framework import BitcoinTestFramework
|
|||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_equal,
|
assert_equal,
|
||||||
assert_raises_rpc_error,
|
assert_raises_rpc_error,
|
||||||
connect_nodes_bi,
|
connect_nodes,
|
||||||
wait_until,
|
wait_until,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,6 +17,10 @@ class DisconnectBanTest(BitcoinTestFramework):
|
|||||||
self.num_nodes = 2
|
self.num_nodes = 2
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
|
self.log.info("Connect nodes both way")
|
||||||
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
connect_nodes(self.nodes[1], 0)
|
||||||
|
|
||||||
self.log.info("Test setban and listbanned RPCs")
|
self.log.info("Test setban and listbanned RPCs")
|
||||||
|
|
||||||
self.log.info("setban: successfully ban single IP address")
|
self.log.info("setban: successfully ban single IP address")
|
||||||
@ -69,7 +73,9 @@ class DisconnectBanTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
# Clear ban lists
|
# Clear ban lists
|
||||||
self.nodes[1].clearbanned()
|
self.nodes[1].clearbanned()
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
self.log.info("Connect nodes both way")
|
||||||
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
connect_nodes(self.nodes[1], 0)
|
||||||
|
|
||||||
self.log.info("Test disconnectnode RPCs")
|
self.log.info("Test disconnectnode RPCs")
|
||||||
|
|
||||||
@ -88,7 +94,7 @@ class DisconnectBanTest(BitcoinTestFramework):
|
|||||||
assert not [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1]
|
assert not [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1]
|
||||||
|
|
||||||
self.log.info("disconnectnode: successfully reconnect node")
|
self.log.info("disconnectnode: successfully reconnect node")
|
||||||
connect_nodes_bi(self.nodes, 0, 1) # reconnect the node
|
connect_nodes(self.nodes[0], 1) # reconnect the node
|
||||||
assert_equal(len(self.nodes[0].getpeerinfo()), 2)
|
assert_equal(len(self.nodes[0].getpeerinfo()), 2)
|
||||||
assert [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1]
|
assert [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1]
|
||||||
|
|
||||||
|
@ -54,10 +54,11 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
|
|||||||
block_time = best_block["time"] + 1
|
block_time = best_block["time"] + 1
|
||||||
|
|
||||||
# Use merkle-root malleability to generate an invalid block with
|
# Use merkle-root malleability to generate an invalid block with
|
||||||
# same blockheader.
|
# same blockheader (CVE-2012-2459).
|
||||||
# Manufacture a block with 3 transactions (coinbase, spend of prior
|
# Manufacture a block with 3 transactions (coinbase, spend of prior
|
||||||
# coinbase, spend of that spend). Duplicate the 3rd transaction to
|
# coinbase, spend of that spend). Duplicate the 3rd transaction to
|
||||||
# leave merkle root and blockheader unchanged but invalidate the block.
|
# leave merkle root and blockheader unchanged but invalidate the block.
|
||||||
|
# For more information on merkle-root malleability see src/consensus/merkle.cpp.
|
||||||
self.log.info("Test merkle root malleability.")
|
self.log.info("Test merkle root malleability.")
|
||||||
|
|
||||||
block2 = create_block(tip, create_coinbase(height), block_time)
|
block2 = create_block(tip, create_coinbase(height), block_time)
|
||||||
@ -81,15 +82,16 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
|
|||||||
assert block2_orig.vtx != block2.vtx
|
assert block2_orig.vtx != block2.vtx
|
||||||
|
|
||||||
node.p2p.send_blocks_and_test([block2], node, success=False, request_block=False, reject_reason='bad-txns-duplicate')
|
node.p2p.send_blocks_and_test([block2], node, success=False, request_block=False, reject_reason='bad-txns-duplicate')
|
||||||
# Check transactions for duplicate inputs
|
# Check transactions for duplicate inputs (CVE-2018-17144)
|
||||||
self.log.info("Test duplicate input block.")
|
self.log.info("Test duplicate input block.")
|
||||||
|
|
||||||
block2_orig.vtx[2].vin.append(block2_orig.vtx[2].vin[0])
|
block2_dup = copy.deepcopy(block2_orig)
|
||||||
block2_orig.vtx[2].rehash()
|
block2_dup.vtx[2].vin.append(block2_dup.vtx[2].vin[0])
|
||||||
block2_orig.hashMerkleRoot = block2_orig.calc_merkle_root()
|
block2_dup.vtx[2].rehash()
|
||||||
block2_orig.rehash()
|
block2_dup.hashMerkleRoot = block2_dup.calc_merkle_root()
|
||||||
block2_orig.solve()
|
block2_dup.rehash()
|
||||||
node.p2p.send_blocks_and_test([block2_orig], node, success=False, request_block=False, reject_reason='bad-txns-inputs-duplicate')
|
block2_dup.solve()
|
||||||
|
node.p2p.send_blocks_and_test([block2_dup], node, success=False, reject_reason='bad-txns-inputs-duplicate')
|
||||||
|
|
||||||
self.log.info("Test very broken block.")
|
self.log.info("Test very broken block.")
|
||||||
|
|
||||||
@ -104,5 +106,31 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
node.p2p.send_blocks_and_test([block3], node, success=False, request_block=False, reject_reason='bad-cb-amount')
|
node.p2p.send_blocks_and_test([block3], node, success=False, request_block=False, reject_reason='bad-cb-amount')
|
||||||
|
|
||||||
|
# Complete testing of CVE-2012-2459 by sending the original block.
|
||||||
|
# It should be accepted even though it has the same hash as the mutated one.
|
||||||
|
|
||||||
|
self.log.info("Test accepting original block after rejecting its mutated version.")
|
||||||
|
node.p2p.send_blocks_and_test([block2_orig], node, success=True, timeout=5)
|
||||||
|
|
||||||
|
# Update tip info
|
||||||
|
height += 1
|
||||||
|
block_time += 1
|
||||||
|
tip = int(block2_orig.hash, 16)
|
||||||
|
|
||||||
|
# Complete testing of CVE-2018-17144, by checking for the inflation bug.
|
||||||
|
# Create a block that spends the output of a tx in a previous block.
|
||||||
|
block4 = create_block(tip, create_coinbase(height), block_time)
|
||||||
|
tx3 = create_tx_with_script(tx2, 0, script_sig=b'\x51', amount=50 * COIN)
|
||||||
|
|
||||||
|
# Duplicates input
|
||||||
|
tx3.vin.append(tx3.vin[0])
|
||||||
|
tx3.rehash()
|
||||||
|
block4.vtx.append(tx3)
|
||||||
|
block4.hashMerkleRoot = block4.calc_merkle_root()
|
||||||
|
block4.rehash()
|
||||||
|
block4.solve()
|
||||||
|
self.log.info("Test inflation by duplicating input")
|
||||||
|
node.p2p.send_blocks_and_test([block4], node, success=False, reject_reason='bad-txns-inputs-duplicate')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
InvalidBlockRequestTest().main()
|
InvalidBlockRequestTest().main()
|
||||||
|
@ -81,7 +81,7 @@ class InvalidMessagesTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
# Peer 1, despite serving up a bunch of nonsense, should still be connected.
|
# Peer 1, despite serving up a bunch of nonsense, should still be connected.
|
||||||
self.log.info("Waiting for node to drop junk messages.")
|
self.log.info("Waiting for node to drop junk messages.")
|
||||||
node.p2p.sync_with_ping(timeout=30)
|
node.p2p.sync_with_ping(timeout=320)
|
||||||
assert node.p2p.is_connected
|
assert node.p2p.is_connected
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -11,7 +11,7 @@ and that it responds to getdata requests for blocks correctly:
|
|||||||
from test_framework.messages import CInv, msg_getdata, NODE_BLOOM, NODE_NETWORK_LIMITED, msg_verack
|
from test_framework.messages import CInv, msg_getdata, NODE_BLOOM, NODE_NETWORK_LIMITED, msg_verack
|
||||||
from test_framework.mininode import P2PInterface, mininode_lock
|
from test_framework.mininode import P2PInterface, mininode_lock
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal, disconnect_nodes, connect_nodes_bi, sync_blocks, wait_until
|
from test_framework.util import assert_equal, disconnect_nodes, connect_nodes, sync_blocks, wait_until
|
||||||
|
|
||||||
class P2PIgnoreInv(P2PInterface):
|
class P2PIgnoreInv(P2PInterface):
|
||||||
firstAddrnServices = 0
|
firstAddrnServices = 0
|
||||||
@ -58,7 +58,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
|
|||||||
assert_equal(int(self.nodes[0].getnetworkinfo()['localservices'], 16), expected_services)
|
assert_equal(int(self.nodes[0].getnetworkinfo()['localservices'], 16), expected_services)
|
||||||
|
|
||||||
self.log.info("Mine enough blocks to reach the NODE_NETWORK_LIMITED range.")
|
self.log.info("Mine enough blocks to reach the NODE_NETWORK_LIMITED range.")
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
blocks = self.nodes[1].generatetoaddress(292, self.nodes[1].get_deterministic_priv_key().address)
|
blocks = self.nodes[1].generatetoaddress(292, self.nodes[1].get_deterministic_priv_key().address)
|
||||||
sync_blocks([self.nodes[0], self.nodes[1]])
|
sync_blocks([self.nodes[0], self.nodes[1]])
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
# connect unsynced node 2 with pruned NODE_NETWORK_LIMITED peer
|
# connect unsynced node 2 with pruned NODE_NETWORK_LIMITED peer
|
||||||
# because node 2 is in IBD and node 0 is a NODE_NETWORK_LIMITED peer, sync must not be possible
|
# because node 2 is in IBD and node 0 is a NODE_NETWORK_LIMITED peer, sync must not be possible
|
||||||
connect_nodes_bi(self.nodes, 0, 2)
|
connect_nodes(self.nodes[0], 2)
|
||||||
try:
|
try:
|
||||||
sync_blocks([self.nodes[0], self.nodes[2]], timeout=5)
|
sync_blocks([self.nodes[0], self.nodes[2]], timeout=5)
|
||||||
except:
|
except:
|
||||||
@ -93,7 +93,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
|
|||||||
assert_equal(self.nodes[2].getblockheader(self.nodes[2].getbestblockhash())['height'], 0)
|
assert_equal(self.nodes[2].getblockheader(self.nodes[2].getbestblockhash())['height'], 0)
|
||||||
|
|
||||||
# now connect also to node 1 (non pruned)
|
# now connect also to node 1 (non pruned)
|
||||||
connect_nodes_bi(self.nodes, 1, 2)
|
connect_nodes(self.nodes[1], 2)
|
||||||
|
|
||||||
# sync must be possible
|
# sync must be possible
|
||||||
sync_blocks(self.nodes)
|
sync_blocks(self.nodes)
|
||||||
@ -105,7 +105,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
|
|||||||
self.nodes[0].generatetoaddress(10, self.nodes[0].get_deterministic_priv_key().address)
|
self.nodes[0].generatetoaddress(10, self.nodes[0].get_deterministic_priv_key().address)
|
||||||
|
|
||||||
# connect node1 (non pruned) with node0 (pruned) and check if the can sync
|
# connect node1 (non pruned) with node0 (pruned) and check if the can sync
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
|
||||||
# sync must be possible, node 1 is no longer in IBD and should therefore connect to node 0 (NODE_NETWORK_LIMITED)
|
# sync must be possible, node 1 is no longer in IBD and should therefore connect to node 0 (NODE_NETWORK_LIMITED)
|
||||||
sync_blocks([self.nodes[0], self.nodes[1]])
|
sync_blocks([self.nodes[0], self.nodes[1]])
|
||||||
|
@ -12,7 +12,7 @@ from test_framework.util import (
|
|||||||
assert_greater_than,
|
assert_greater_than,
|
||||||
assert_greater_than_or_equal,
|
assert_greater_than_or_equal,
|
||||||
assert_raises_rpc_error,
|
assert_raises_rpc_error,
|
||||||
connect_nodes_bi,
|
connect_nodes,
|
||||||
count_bytes,
|
count_bytes,
|
||||||
find_vout_for_address,
|
find_vout_for_address,
|
||||||
)
|
)
|
||||||
@ -36,10 +36,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||||||
def setup_network(self):
|
def setup_network(self):
|
||||||
self.setup_nodes()
|
self.setup_nodes()
|
||||||
|
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
connect_nodes_bi(self.nodes, 1, 2)
|
connect_nodes(self.nodes[1], 2)
|
||||||
connect_nodes_bi(self.nodes, 0, 2)
|
connect_nodes(self.nodes[0], 2)
|
||||||
connect_nodes_bi(self.nodes, 0, 3)
|
connect_nodes(self.nodes[0], 3)
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']
|
min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']
|
||||||
@ -475,10 +475,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||||||
for node in self.nodes:
|
for node in self.nodes:
|
||||||
node.settxfee(min_relay_tx_fee)
|
node.settxfee(min_relay_tx_fee)
|
||||||
|
|
||||||
connect_nodes_bi(self.nodes,0,1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
connect_nodes_bi(self.nodes,1,2)
|
connect_nodes(self.nodes[1], 2)
|
||||||
connect_nodes_bi(self.nodes,0,2)
|
connect_nodes(self.nodes[0], 2)
|
||||||
connect_nodes_bi(self.nodes,0,3)
|
connect_nodes(self.nodes[0], 3)
|
||||||
# Again lock the watchonly UTXO or nodes[0] may spend it, because
|
# Again lock the watchonly UTXO or nodes[0] may spend it, because
|
||||||
# lockunspent is memory-only and thus lost on restart
|
# lockunspent is memory-only and thus lost on restart
|
||||||
self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])
|
self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])
|
||||||
|
@ -7,7 +7,7 @@ from decimal import Decimal
|
|||||||
|
|
||||||
from test_framework.authproxy import JSONRPCException
|
from test_framework.authproxy import JSONRPCException
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal, assert_greater_than, connect_nodes_bi
|
from test_framework.util import assert_equal, assert_greater_than, connect_nodes
|
||||||
|
|
||||||
# Create one-input, one-output, no-fee transaction:
|
# Create one-input, one-output, no-fee transaction:
|
||||||
class RawTransactionsTest(BitcoinTestFramework):
|
class RawTransactionsTest(BitcoinTestFramework):
|
||||||
@ -22,10 +22,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
def setup_network(self):
|
def setup_network(self):
|
||||||
super().setup_network()
|
super().setup_network()
|
||||||
connect_nodes_bi(self.nodes,0,1)
|
connect_nodes(self.nodes[0],1)
|
||||||
connect_nodes_bi(self.nodes,1,2)
|
connect_nodes(self.nodes[1],2)
|
||||||
connect_nodes_bi(self.nodes,0,2)
|
connect_nodes(self.nodes[0],2)
|
||||||
connect_nodes_bi(self.nodes,0,3)
|
connect_nodes(self.nodes[0],3)
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
self.log.info("Mining blocks...")
|
self.log.info("Mining blocks...")
|
||||||
@ -451,10 +451,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||||||
for node in self.nodes:
|
for node in self.nodes:
|
||||||
node.settxfee(min_relay_tx_fee)
|
node.settxfee(min_relay_tx_fee)
|
||||||
|
|
||||||
connect_nodes_bi(self.nodes,0,1)
|
connect_nodes(self.nodes[0],1)
|
||||||
connect_nodes_bi(self.nodes,1,2)
|
connect_nodes(self.nodes[1],2)
|
||||||
connect_nodes_bi(self.nodes,0,2)
|
connect_nodes(self.nodes[0],2)
|
||||||
connect_nodes_bi(self.nodes,0,3)
|
connect_nodes(self.nodes[0],3)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
# drain the keypool
|
# drain the keypool
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal, connect_nodes, connect_nodes_bi, wait_until
|
from test_framework.util import assert_equal, connect_nodes, wait_until
|
||||||
|
|
||||||
class InvalidateTest(BitcoinTestFramework):
|
class InvalidateTest(BitcoinTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
@ -29,7 +29,7 @@ class InvalidateTest(BitcoinTestFramework):
|
|||||||
assert self.nodes[1].getblockcount() == 6
|
assert self.nodes[1].getblockcount() == 6
|
||||||
|
|
||||||
self.log.info("Connect nodes to force a reorg")
|
self.log.info("Connect nodes to force a reorg")
|
||||||
connect_nodes_bi(self.nodes,0,1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
self.sync_blocks(self.nodes[0:2])
|
self.sync_blocks(self.nodes[0:2])
|
||||||
assert self.nodes[0].getblockcount() == 6
|
assert self.nodes[0].getblockcount() == 6
|
||||||
badhash = self.nodes[1].getblockhash(2)
|
badhash = self.nodes[1].getblockhash(2)
|
||||||
@ -42,7 +42,7 @@ class InvalidateTest(BitcoinTestFramework):
|
|||||||
raise AssertionError("Wrong tip for node0, hash %s, height %d"%(newhash,newheight))
|
raise AssertionError("Wrong tip for node0, hash %s, height %d"%(newhash,newheight))
|
||||||
|
|
||||||
self.log.info("Make sure we won't reorg to a lower work chain:")
|
self.log.info("Make sure we won't reorg to a lower work chain:")
|
||||||
connect_nodes_bi(self.nodes,1,2)
|
connect_nodes(self.nodes[1], 2)
|
||||||
self.log.info("Sync node 2 to node 1 so both have 6 blocks")
|
self.log.info("Sync node 2 to node 1 so both have 6 blocks")
|
||||||
self.sync_blocks(self.nodes[1:3])
|
self.sync_blocks(self.nodes[1:3])
|
||||||
assert self.nodes[2].getblockcount() == 6
|
assert self.nodes[2].getblockcount() == 6
|
||||||
@ -65,7 +65,7 @@ class InvalidateTest(BitcoinTestFramework):
|
|||||||
self.log.info("Make sure ResetBlockFailureFlags does the job correctly")
|
self.log.info("Make sure ResetBlockFailureFlags does the job correctly")
|
||||||
self.restart_node(0, extra_args=["-checkblocks=5"])
|
self.restart_node(0, extra_args=["-checkblocks=5"])
|
||||||
self.restart_node(1, extra_args=["-checkblocks=5"])
|
self.restart_node(1, extra_args=["-checkblocks=5"])
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
self.nodes[0].generate(10)
|
self.nodes[0].generate(10)
|
||||||
self.sync_blocks(self.nodes[0:2])
|
self.sync_blocks(self.nodes[0:2])
|
||||||
newheight = self.nodes[0].getblockcount()
|
newheight = self.nodes[0].getblockcount()
|
||||||
|
@ -13,7 +13,7 @@ from test_framework.util import (
|
|||||||
assert_greater_than_or_equal,
|
assert_greater_than_or_equal,
|
||||||
assert_greater_than,
|
assert_greater_than,
|
||||||
assert_raises_rpc_error,
|
assert_raises_rpc_error,
|
||||||
connect_nodes_bi,
|
connect_nodes,
|
||||||
p2p_port,
|
p2p_port,
|
||||||
wait_until,
|
wait_until,
|
||||||
)
|
)
|
||||||
@ -50,13 +50,16 @@ class NetTest(BitcoinTestFramework):
|
|||||||
def setup_network(self):
|
def setup_network(self):
|
||||||
self.disable_mocktime()
|
self.disable_mocktime()
|
||||||
self.setup_nodes()
|
self.setup_nodes()
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
# Wait for one ping/pong to finish so that we can be sure that there is no chatter between nodes for some time
|
# Wait for one ping/pong to finish so that we can be sure that there is no chatter between nodes for some time
|
||||||
# Especially the exchange of messages like getheaders and friends causes test failures here
|
# Especially the exchange of messages like getheaders and friends causes test failures here
|
||||||
self.nodes[0].ping()
|
self.nodes[0].ping()
|
||||||
wait_until(lambda: all(['pingtime' in n for n in self.nodes[0].getpeerinfo()]))
|
wait_until(lambda: all(['pingtime' in n for n in self.nodes[0].getpeerinfo()]))
|
||||||
|
self.log.info('Connect nodes both way')
|
||||||
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
connect_nodes(self.nodes[1], 0)
|
||||||
|
|
||||||
self._test_connection_count()
|
self._test_connection_count()
|
||||||
self._test_getnettotals()
|
self._test_getnettotals()
|
||||||
@ -66,7 +69,7 @@ class NetTest(BitcoinTestFramework):
|
|||||||
self._test_getnodeaddresses()
|
self._test_getnodeaddresses()
|
||||||
|
|
||||||
def _test_connection_count(self):
|
def _test_connection_count(self):
|
||||||
# connect_nodes_bi connects each node to the other
|
# connect_nodes connects each node to the other
|
||||||
assert_equal(self.nodes[0].getconnectioncount(), 2)
|
assert_equal(self.nodes[0].getconnectioncount(), 2)
|
||||||
|
|
||||||
def _test_getnettotals(self):
|
def _test_getnettotals(self):
|
||||||
@ -110,7 +113,10 @@ class NetTest(BitcoinTestFramework):
|
|||||||
wait_until(lambda: self.nodes[1].getnetworkinfo()['connections'] == 0, timeout=3)
|
wait_until(lambda: self.nodes[1].getnetworkinfo()['connections'] == 0, timeout=3)
|
||||||
|
|
||||||
self.nodes[0].setnetworkactive(state=True)
|
self.nodes[0].setnetworkactive(state=True)
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
self.log.info('Connect nodes both way')
|
||||||
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
connect_nodes(self.nodes[1], 0)
|
||||||
|
|
||||||
assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True)
|
assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True)
|
||||||
assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2)
|
assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2)
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_equal,
|
assert_equal,
|
||||||
connect_nodes_bi,
|
connect_nodes,
|
||||||
sync_blocks,
|
sync_blocks,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ class PreciousTest(BitcoinTestFramework):
|
|||||||
self.log.info("Connect nodes and check no reorg occurs")
|
self.log.info("Connect nodes and check no reorg occurs")
|
||||||
# Submit competing blocks via RPC so any reorg should occur before we proceed (no way to wait on inaction for p2p sync)
|
# Submit competing blocks via RPC so any reorg should occur before we proceed (no way to wait on inaction for p2p sync)
|
||||||
node_sync_via_rpc(self.nodes[0:2])
|
node_sync_via_rpc(self.nodes[0:2])
|
||||||
connect_nodes_bi(self.nodes,0,1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
assert_equal(self.nodes[0].getbestblockhash(), hashC)
|
assert_equal(self.nodes[0].getbestblockhash(), hashC)
|
||||||
assert_equal(self.nodes[1].getbestblockhash(), hashG)
|
assert_equal(self.nodes[1].getbestblockhash(), hashG)
|
||||||
self.log.info("Make Node0 prefer block G")
|
self.log.info("Make Node0 prefer block G")
|
||||||
@ -98,8 +98,8 @@ class PreciousTest(BitcoinTestFramework):
|
|||||||
hashL = self.nodes[2].getbestblockhash()
|
hashL = self.nodes[2].getbestblockhash()
|
||||||
self.log.info("Connect nodes and check no reorg occurs")
|
self.log.info("Connect nodes and check no reorg occurs")
|
||||||
node_sync_via_rpc(self.nodes[1:3])
|
node_sync_via_rpc(self.nodes[1:3])
|
||||||
connect_nodes_bi(self.nodes,1,2)
|
connect_nodes(self.nodes[1], 2)
|
||||||
connect_nodes_bi(self.nodes,0,2)
|
connect_nodes(self.nodes[0], 2)
|
||||||
assert_equal(self.nodes[0].getbestblockhash(), hashH)
|
assert_equal(self.nodes[0].getbestblockhash(), hashH)
|
||||||
assert_equal(self.nodes[1].getbestblockhash(), hashH)
|
assert_equal(self.nodes[1].getbestblockhash(), hashH)
|
||||||
assert_equal(self.nodes[2].getbestblockhash(), hashL)
|
assert_equal(self.nodes[2].getbestblockhash(), hashL)
|
||||||
|
@ -17,7 +17,13 @@ from decimal import Decimal
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from test_framework.messages import CTransaction, ToHex
|
from test_framework.messages import CTransaction, ToHex
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal, assert_raises_rpc_error, connect_nodes_bi, hex_str_to_bytes
|
from test_framework.util import (
|
||||||
|
assert_equal,
|
||||||
|
assert_raises_rpc_error,
|
||||||
|
connect_nodes,
|
||||||
|
hex_str_to_bytes,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class multidict(dict):
|
class multidict(dict):
|
||||||
"""Dictionary that allows duplicate keys.
|
"""Dictionary that allows duplicate keys.
|
||||||
@ -53,7 +59,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
def setup_network(self):
|
def setup_network(self):
|
||||||
super().setup_network()
|
super().setup_network()
|
||||||
connect_nodes_bi(self.nodes, 0, 2)
|
connect_nodes(self.nodes[0], 2)
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
self.log.info('prepare some coins for multiple *rawtransaction commands')
|
self.log.info('prepare some coins for multiple *rawtransaction commands')
|
||||||
|
@ -37,7 +37,6 @@ from .util import (
|
|||||||
MAX_NODES,
|
MAX_NODES,
|
||||||
assert_equal,
|
assert_equal,
|
||||||
check_json_precision,
|
check_json_precision,
|
||||||
connect_nodes_bi,
|
|
||||||
connect_nodes,
|
connect_nodes,
|
||||||
copy_datadir,
|
copy_datadir,
|
||||||
disconnect_nodes,
|
disconnect_nodes,
|
||||||
@ -326,8 +325,18 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||||||
# Connect the nodes as a "chain". This allows us
|
# Connect the nodes as a "chain". This allows us
|
||||||
# to split the network between nodes 1 and 2 to get
|
# to split the network between nodes 1 and 2 to get
|
||||||
# two halves that can work on competing chains.
|
# two halves that can work on competing chains.
|
||||||
|
#
|
||||||
|
# Topology looks like this:
|
||||||
|
# node0 <-- node1 <-- node2 <-- node3
|
||||||
|
#
|
||||||
|
# If all nodes are in IBD (clean chain from genesis), node0 is assumed to be the source of blocks (miner). To
|
||||||
|
# ensure block propagation, all nodes will establish outgoing connections toward node0.
|
||||||
|
# See fPreferredDownload in net_processing.
|
||||||
|
#
|
||||||
|
# If further outbound connections are needed, they can be added at the beginning of the test with e.g.
|
||||||
|
# connect_nodes(self.nodes[1], 2)
|
||||||
for i in range(self.num_nodes - 1):
|
for i in range(self.num_nodes - 1):
|
||||||
connect_nodes_bi(self.nodes, i, i + 1)
|
connect_nodes(self.nodes[i + 1], i)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
def setup_nodes(self):
|
def setup_nodes(self):
|
||||||
@ -459,7 +468,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||||||
"""
|
"""
|
||||||
Join the (previously split) network halves together.
|
Join the (previously split) network halves together.
|
||||||
"""
|
"""
|
||||||
connect_nodes_bi(self.nodes, 1, 2)
|
connect_nodes(self.nodes[1], 2)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
def sync_blocks(self, nodes=None, **kwargs):
|
def sync_blocks(self, nodes=None, **kwargs):
|
||||||
|
@ -9,6 +9,7 @@ from base64 import b64encode
|
|||||||
from binascii import unhexlify
|
from binascii import unhexlify
|
||||||
from decimal import Decimal, ROUND_DOWN
|
from decimal import Decimal, ROUND_DOWN
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from subprocess import CalledProcessError
|
||||||
import inspect
|
import inspect
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
@ -16,7 +17,6 @@ import os
|
|||||||
import random
|
import random
|
||||||
import shutil
|
import shutil
|
||||||
import re
|
import re
|
||||||
from subprocess import CalledProcessError
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from . import coverage
|
from . import coverage
|
||||||
@ -37,6 +37,13 @@ def set_timeout_scale(_timeout_scale):
|
|||||||
# Assert functions
|
# Assert functions
|
||||||
##################
|
##################
|
||||||
|
|
||||||
|
def assert_approx(v, vexp, vspan=0.00001):
|
||||||
|
"""Assert that `v` is within `vspan` of `vexp`"""
|
||||||
|
if v < vexp - vspan:
|
||||||
|
raise AssertionError("%s < [%s..%s]" % (str(v), str(vexp - vspan), str(vexp + vspan)))
|
||||||
|
if v > vexp + vspan:
|
||||||
|
raise AssertionError("%s > [%s..%s]" % (str(v), str(vexp - vspan), str(vexp + vspan)))
|
||||||
|
|
||||||
def assert_fee_amount(fee, tx_size, fee_per_kB):
|
def assert_fee_amount(fee, tx_size, fee_per_kB):
|
||||||
"""Assert the fee was in range"""
|
"""Assert the fee was in range"""
|
||||||
target_fee = round(tx_size * fee_per_kB / 1000, 8)
|
target_fee = round(tx_size * fee_per_kB / 1000, 8)
|
||||||
@ -254,10 +261,11 @@ def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), sleep=
|
|||||||
# The maximum number of nodes a single test can spawn
|
# The maximum number of nodes a single test can spawn
|
||||||
MAX_NODES = 15
|
MAX_NODES = 15
|
||||||
# Don't assign rpc or p2p ports lower than this
|
# Don't assign rpc or p2p ports lower than this
|
||||||
PORT_MIN = 11000
|
PORT_MIN = int(os.getenv('TEST_RUNNER_PORT_MIN', default=11000))
|
||||||
# The number of ports to "reserve" for p2p and rpc, each
|
# The number of ports to "reserve" for p2p and rpc, each
|
||||||
PORT_RANGE = 5000
|
PORT_RANGE = 5000
|
||||||
|
|
||||||
|
|
||||||
class PortSeed:
|
class PortSeed:
|
||||||
# Must be initialized with a unique integer for each process
|
# Must be initialized with a unique integer for each process
|
||||||
n = None
|
n = None
|
||||||
@ -445,10 +453,6 @@ def connect_nodes(from_connection, node_num):
|
|||||||
wait_until(lambda: all(peer['version'] != 0 for peer in from_connection.getpeerinfo()))
|
wait_until(lambda: all(peer['version'] != 0 for peer in from_connection.getpeerinfo()))
|
||||||
wait_until(lambda: all(peer['bytesrecv_per_msg'].pop('verack', 0) == 24 for peer in from_connection.getpeerinfo()))
|
wait_until(lambda: all(peer['bytesrecv_per_msg'].pop('verack', 0) == 24 for peer in from_connection.getpeerinfo()))
|
||||||
|
|
||||||
def connect_nodes_bi(nodes, a, b):
|
|
||||||
connect_nodes(nodes[a], b)
|
|
||||||
connect_nodes(nodes[b], a)
|
|
||||||
|
|
||||||
def isolate_node(node, timeout=5):
|
def isolate_node(node, timeout=5):
|
||||||
node.setnetworkactive(False)
|
node.setnetworkactive(False)
|
||||||
st = time.time()
|
st = time.time()
|
||||||
|
@ -1,18 +1,25 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Copyright (c) 2018 The Bitcoin Core developers
|
# Copyright (c) 2018-2019 The Bitcoin Core developers
|
||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
"""Test dash-wallet."""
|
"""Test dash-wallet."""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
import stat
|
||||||
import subprocess
|
import subprocess
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal
|
from test_framework.util import assert_equal
|
||||||
|
|
||||||
|
BUFFER_SIZE = 16 * 1024
|
||||||
|
|
||||||
class ToolWalletTest(BitcoinTestFramework):
|
class ToolWalletTest(BitcoinTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
self.num_nodes = 1
|
self.num_nodes = 1
|
||||||
self.setup_clean_chain = True
|
self.setup_clean_chain = True
|
||||||
|
self.rpc_timeout = 120
|
||||||
|
|
||||||
def skip_test_if_missing_module(self):
|
def skip_test_if_missing_module(self):
|
||||||
self.skip_if_no_wallet()
|
self.skip_if_no_wallet()
|
||||||
@ -32,23 +39,54 @@ class ToolWalletTest(BitcoinTestFramework):
|
|||||||
def assert_tool_output(self, output, *args):
|
def assert_tool_output(self, output, *args):
|
||||||
p = self.dash_wallet_process(*args)
|
p = self.dash_wallet_process(*args)
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
assert_equal(p.poll(), 0)
|
|
||||||
assert_equal(stderr, '')
|
assert_equal(stderr, '')
|
||||||
assert_equal(stdout, output)
|
assert_equal(stdout, output)
|
||||||
|
assert_equal(p.poll(), 0)
|
||||||
|
|
||||||
def run_test(self):
|
def wallet_shasum(self):
|
||||||
|
h = hashlib.sha1()
|
||||||
|
mv = memoryview(bytearray(BUFFER_SIZE))
|
||||||
|
with open(self.wallet_path, 'rb', buffering=0) as f:
|
||||||
|
for n in iter(lambda : f.readinto(mv), 0):
|
||||||
|
h.update(mv[:n])
|
||||||
|
return h.hexdigest()
|
||||||
|
|
||||||
|
def wallet_timestamp(self):
|
||||||
|
return os.path.getmtime(self.wallet_path)
|
||||||
|
|
||||||
|
def wallet_permissions(self):
|
||||||
|
return oct(os.lstat(self.wallet_path).st_mode)[-3:]
|
||||||
|
|
||||||
|
def log_wallet_timestamp_comparison(self, old, new):
|
||||||
|
result = 'unchanged' if new == old else 'increased!'
|
||||||
|
self.log.debug('Wallet file timestamp {}'.format(result))
|
||||||
|
|
||||||
|
def test_invalid_tool_commands_and_args(self):
|
||||||
|
self.log.info('Testing that various invalid commands raise with specific error messages')
|
||||||
self.assert_raises_tool_error('Invalid command: foo', 'foo')
|
self.assert_raises_tool_error('Invalid command: foo', 'foo')
|
||||||
# `dash-wallet help` is an error. Use `dash-wallet -help`
|
# `dash-wallet help` raises an error. Use `dash-wallet -help`.
|
||||||
self.assert_raises_tool_error('Invalid command: help', 'help')
|
self.assert_raises_tool_error('Invalid command: help', 'help')
|
||||||
self.assert_raises_tool_error('Error: two methods provided (info and create). Only one method should be provided.', 'info', 'create')
|
self.assert_raises_tool_error('Error: two methods provided (info and create). Only one method should be provided.', 'info', 'create')
|
||||||
self.assert_raises_tool_error('Error parsing command line arguments: Invalid parameter -foo', '-foo')
|
self.assert_raises_tool_error('Error parsing command line arguments: Invalid parameter -foo', '-foo')
|
||||||
self.assert_raises_tool_error('Error loading wallet.dat. Is wallet being used by other process?', '-wallet=wallet.dat', 'info')
|
self.assert_raises_tool_error('Error loading wallet.dat. Is wallet being used by other process?', '-wallet=wallet.dat', 'info')
|
||||||
self.assert_raises_tool_error('Error: no wallet file at nonexistent.dat', '-wallet=nonexistent.dat', 'info')
|
self.assert_raises_tool_error('Error: no wallet file at nonexistent.dat', '-wallet=nonexistent.dat', 'info')
|
||||||
|
|
||||||
# stop the node to close the wallet to call info command
|
def test_tool_wallet_info(self):
|
||||||
|
# Stop the node to close the wallet to call the info command.
|
||||||
self.stop_node(0)
|
self.stop_node(0)
|
||||||
|
self.log.info('Calling wallet tool info, testing output')
|
||||||
|
#
|
||||||
|
# TODO: Wallet tool info should work with wallet file permissions set to
|
||||||
|
# read-only without raising:
|
||||||
|
# "Error loading wallet.dat. Is wallet being used by another process?"
|
||||||
|
# The following lines should be uncommented and the tests still succeed:
|
||||||
|
#
|
||||||
|
# self.log.debug('Setting wallet file permissions to 400 (read-only)')
|
||||||
|
# os.chmod(self.wallet_path, stat.S_IRUSR)
|
||||||
|
# assert(self.wallet_permissions() in ['400', '666']) # Sanity check. 666 because Appveyor.
|
||||||
|
# shasum_before = self.wallet_shasum()
|
||||||
|
timestamp_before = self.wallet_timestamp()
|
||||||
|
self.log.debug('Wallet file timestamp before calling info: {}'.format(timestamp_before))
|
||||||
out = textwrap.dedent('''\
|
out = textwrap.dedent('''\
|
||||||
Wallet info
|
Wallet info
|
||||||
===========
|
===========
|
||||||
@ -74,12 +112,35 @@ class ToolWalletTest(BitcoinTestFramework):
|
|||||||
Address Book: 0
|
Address Book: 0
|
||||||
''')
|
''')
|
||||||
self.assert_tool_output(out, '-wallet=wallet.dat', 'info')
|
self.assert_tool_output(out, '-wallet=wallet.dat', 'info')
|
||||||
|
timestamp_after = self.wallet_timestamp()
|
||||||
|
self.log.debug('Wallet file timestamp after calling info: {}'.format(timestamp_after))
|
||||||
|
self.log_wallet_timestamp_comparison(timestamp_before, timestamp_after)
|
||||||
|
self.log.debug('Setting wallet file permissions back to 600 (read/write)')
|
||||||
|
os.chmod(self.wallet_path, stat.S_IRUSR | stat.S_IWUSR)
|
||||||
|
assert(self.wallet_permissions() in ['600', '666']) # Sanity check. 666 because Appveyor.
|
||||||
|
#
|
||||||
|
# TODO: Wallet tool info should not write to the wallet file.
|
||||||
|
# The following lines should be uncommented and the tests still succeed:
|
||||||
|
#
|
||||||
|
# assert_equal(timestamp_before, timestamp_after)
|
||||||
|
# shasum_after = self.wallet_shasum()
|
||||||
|
# assert_equal(shasum_before, shasum_after)
|
||||||
|
# self.log.debug('Wallet file shasum unchanged\n')
|
||||||
|
|
||||||
# mutate the wallet to check the info command output changes accordingly
|
def test_tool_wallet_info_after_transaction(self):
|
||||||
|
"""
|
||||||
|
Mutate the wallet with a transaction to verify that the info command
|
||||||
|
output changes accordingly.
|
||||||
|
"""
|
||||||
self.start_node(0)
|
self.start_node(0)
|
||||||
|
self.log.info('Generating transaction to mutate wallet')
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.stop_node(0)
|
self.stop_node(0)
|
||||||
|
|
||||||
|
self.log.info('Calling wallet tool info after generating a transaction, testing output')
|
||||||
|
shasum_before = self.wallet_shasum()
|
||||||
|
timestamp_before = self.wallet_timestamp()
|
||||||
|
self.log.debug('Wallet file timestamp before calling info: {}'.format(timestamp_before))
|
||||||
out = textwrap.dedent('''\
|
out = textwrap.dedent('''\
|
||||||
Wallet info
|
Wallet info
|
||||||
===========
|
===========
|
||||||
@ -90,7 +151,22 @@ class ToolWalletTest(BitcoinTestFramework):
|
|||||||
Address Book: 0
|
Address Book: 0
|
||||||
''')
|
''')
|
||||||
self.assert_tool_output(out, '-wallet=wallet.dat', 'info')
|
self.assert_tool_output(out, '-wallet=wallet.dat', 'info')
|
||||||
|
shasum_after = self.wallet_shasum()
|
||||||
|
timestamp_after = self.wallet_timestamp()
|
||||||
|
self.log.debug('Wallet file timestamp after calling info: {}'.format(timestamp_after))
|
||||||
|
self.log_wallet_timestamp_comparison(timestamp_before, timestamp_after)
|
||||||
|
#
|
||||||
|
# TODO: Wallet tool info should not write to the wallet file.
|
||||||
|
# This assertion should be uncommented and succeed:
|
||||||
|
# assert_equal(timestamp_before, timestamp_after)
|
||||||
|
assert_equal(shasum_before, shasum_after)
|
||||||
|
self.log.debug('Wallet file shasum unchanged\n')
|
||||||
|
|
||||||
|
def test_tool_wallet_create_on_existing_wallet(self):
|
||||||
|
self.log.info('Calling wallet tool create on an existing wallet, testing output')
|
||||||
|
shasum_before = self.wallet_shasum()
|
||||||
|
timestamp_before = self.wallet_timestamp()
|
||||||
|
self.log.debug('Wallet file timestamp before calling create: {}'.format(timestamp_before))
|
||||||
out = textwrap.dedent('''\
|
out = textwrap.dedent('''\
|
||||||
Topping up keypool...
|
Topping up keypool...
|
||||||
Wallet info
|
Wallet info
|
||||||
@ -102,13 +178,46 @@ class ToolWalletTest(BitcoinTestFramework):
|
|||||||
Address Book: 0
|
Address Book: 0
|
||||||
''')
|
''')
|
||||||
self.assert_tool_output(out, '-wallet=foo', 'create')
|
self.assert_tool_output(out, '-wallet=foo', 'create')
|
||||||
|
shasum_after = self.wallet_shasum()
|
||||||
|
timestamp_after = self.wallet_timestamp()
|
||||||
|
self.log.debug('Wallet file timestamp after calling create: {}'.format(timestamp_after))
|
||||||
|
self.log_wallet_timestamp_comparison(timestamp_before, timestamp_after)
|
||||||
|
assert_equal(timestamp_before, timestamp_after)
|
||||||
|
assert_equal(shasum_before, shasum_after)
|
||||||
|
self.log.debug('Wallet file shasum unchanged\n')
|
||||||
|
|
||||||
|
def test_getwalletinfo_on_different_wallet(self):
|
||||||
|
self.log.info('Starting node with arg -wallet=foo')
|
||||||
self.start_node(0, ['-wallet=foo'])
|
self.start_node(0, ['-wallet=foo'])
|
||||||
|
|
||||||
|
self.log.info('Calling getwalletinfo on a different wallet ("foo"), testing output')
|
||||||
|
shasum_before = self.wallet_shasum()
|
||||||
|
timestamp_before = self.wallet_timestamp()
|
||||||
|
self.log.debug('Wallet file timestamp before calling getwalletinfo: {}'.format(timestamp_before))
|
||||||
out = self.nodes[0].getwalletinfo()
|
out = self.nodes[0].getwalletinfo()
|
||||||
self.stop_node(0)
|
self.stop_node(0)
|
||||||
|
|
||||||
|
shasum_after = self.wallet_shasum()
|
||||||
|
timestamp_after = self.wallet_timestamp()
|
||||||
|
self.log.debug('Wallet file timestamp after calling getwalletinfo: {}'.format(timestamp_after))
|
||||||
|
|
||||||
assert_equal(0, out['txcount'])
|
assert_equal(0, out['txcount'])
|
||||||
assert_equal(1000, out['keypoolsize'])
|
assert_equal(1000, out['keypoolsize'])
|
||||||
|
|
||||||
|
self.log_wallet_timestamp_comparison(timestamp_before, timestamp_after)
|
||||||
|
assert_equal(timestamp_before, timestamp_after)
|
||||||
|
assert_equal(shasum_after, shasum_before)
|
||||||
|
self.log.debug('Wallet file shasum unchanged\n')
|
||||||
|
|
||||||
|
def run_test(self):
|
||||||
|
self.wallet_path = os.path.join(self.nodes[0].datadir, 'regtest', 'wallets', 'wallet.dat')
|
||||||
|
self.test_invalid_tool_commands_and_args()
|
||||||
|
# Warning: The following tests are order-dependent.
|
||||||
|
self.test_tool_wallet_info()
|
||||||
|
self.test_tool_wallet_info_after_transaction()
|
||||||
|
self.test_tool_wallet_create_on_existing_wallet()
|
||||||
|
self.test_getwalletinfo_on_different_wallet()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
ToolWalletTest().main()
|
ToolWalletTest().main()
|
||||||
|
@ -44,6 +44,7 @@ class WalletBackupTest(BitcoinTestFramework):
|
|||||||
self.setup_clean_chain = True
|
self.setup_clean_chain = True
|
||||||
# nodes 1, 2,3 are spenders, let's give them a keypool=100
|
# nodes 1, 2,3 are spenders, let's give them a keypool=100
|
||||||
self.extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []]
|
self.extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []]
|
||||||
|
self.rpc_timeout = 120
|
||||||
|
|
||||||
def skip_test_if_missing_module(self):
|
def skip_test_if_missing_module(self):
|
||||||
self.skip_if_no_wallet()
|
self.skip_if_no_wallet()
|
||||||
|
@ -12,7 +12,7 @@ from test_framework.util import (
|
|||||||
assert_equal,
|
assert_equal,
|
||||||
assert_fee_amount,
|
assert_fee_amount,
|
||||||
assert_raises_rpc_error,
|
assert_raises_rpc_error,
|
||||||
connect_nodes_bi,
|
connect_nodes,
|
||||||
count_bytes,
|
count_bytes,
|
||||||
wait_until,
|
wait_until,
|
||||||
)
|
)
|
||||||
@ -32,9 +32,9 @@ class WalletTest(BitcoinTestFramework):
|
|||||||
self.start_node(0)
|
self.start_node(0)
|
||||||
self.start_node(1)
|
self.start_node(1)
|
||||||
self.start_node(2)
|
self.start_node(2)
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
connect_nodes_bi(self.nodes, 1, 2)
|
connect_nodes(self.nodes[1], 2)
|
||||||
connect_nodes_bi(self.nodes, 0, 2)
|
connect_nodes(self.nodes[0], 2)
|
||||||
self.sync_all(self.nodes[0:3])
|
self.sync_all(self.nodes[0:3])
|
||||||
|
|
||||||
def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size):
|
def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size):
|
||||||
@ -214,7 +214,7 @@ class WalletTest(BitcoinTestFramework):
|
|||||||
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('100'), fee_per_byte, count_bytes(self.nodes[2].gettransaction(txid)['hex']))
|
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('100'), fee_per_byte, count_bytes(self.nodes[2].gettransaction(txid)['hex']))
|
||||||
|
|
||||||
self.start_node(3)
|
self.start_node(3)
|
||||||
connect_nodes_bi(self.nodes, 0, 3)
|
connect_nodes(self.nodes[0], 3)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
# check if we can list zero value tx as available coins
|
# check if we can list zero value tx as available coins
|
||||||
@ -249,9 +249,9 @@ class WalletTest(BitcoinTestFramework):
|
|||||||
self.start_node(0, ["-walletbroadcast=0"])
|
self.start_node(0, ["-walletbroadcast=0"])
|
||||||
self.start_node(1, ["-walletbroadcast=0"])
|
self.start_node(1, ["-walletbroadcast=0"])
|
||||||
self.start_node(2, ["-walletbroadcast=0"])
|
self.start_node(2, ["-walletbroadcast=0"])
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
connect_nodes_bi(self.nodes, 1, 2)
|
connect_nodes(self.nodes[1], 2)
|
||||||
connect_nodes_bi(self.nodes, 0, 2)
|
connect_nodes(self.nodes[0], 2)
|
||||||
self.sync_all(self.nodes[0:3])
|
self.sync_all(self.nodes[0:3])
|
||||||
|
|
||||||
txid_not_broadcast = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
|
txid_not_broadcast = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
|
||||||
@ -276,9 +276,9 @@ class WalletTest(BitcoinTestFramework):
|
|||||||
self.start_node(0)
|
self.start_node(0)
|
||||||
self.start_node(1)
|
self.start_node(1)
|
||||||
self.start_node(2)
|
self.start_node(2)
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
connect_nodes_bi(self.nodes, 1, 2)
|
connect_nodes(self.nodes[1], 2)
|
||||||
connect_nodes_bi(self.nodes, 0, 2)
|
connect_nodes(self.nodes[0], 2)
|
||||||
self.sync_blocks(self.nodes[0:3])
|
self.sync_blocks(self.nodes[0:3])
|
||||||
|
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
|
@ -7,15 +7,10 @@
|
|||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.messages import CTransaction, FromHex, ToHex
|
from test_framework.messages import CTransaction, FromHex, ToHex
|
||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
|
assert_approx,
|
||||||
assert_equal,
|
assert_equal,
|
||||||
)
|
)
|
||||||
|
|
||||||
def assert_approx(v, vexp, vspan=0.00001):
|
|
||||||
if v < vexp - vspan:
|
|
||||||
raise AssertionError("%s < [%s..%s]" % (str(v), str(vexp - vspan), str(vexp + vspan)))
|
|
||||||
if v > vexp + vspan:
|
|
||||||
raise AssertionError("%s > [%s..%s]" % (str(v), str(vexp - vspan), str(vexp + vspan)))
|
|
||||||
|
|
||||||
class WalletGroupTest(BitcoinTestFramework):
|
class WalletGroupTest(BitcoinTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
self.setup_clean_chain = True
|
self.setup_clean_chain = True
|
||||||
|
@ -10,7 +10,7 @@ import os
|
|||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_equal,
|
assert_equal,
|
||||||
connect_nodes_bi,
|
connect_nodes,
|
||||||
)
|
)
|
||||||
|
|
||||||
class WalletHDTest(BitcoinTestFramework):
|
class WalletHDTest(BitcoinTestFramework):
|
||||||
@ -31,7 +31,7 @@ class WalletHDTest(BitcoinTestFramework):
|
|||||||
self.stop_node(1)
|
self.stop_node(1)
|
||||||
self.nodes[1].assert_start_raises_init_error(['-usehd=0'], "Error: Error loading : You can't disable HD on an already existing HD wallet")
|
self.nodes[1].assert_start_raises_init_error(['-usehd=0'], "Error: Error loading : You can't disable HD on an already existing HD wallet")
|
||||||
self.start_node(1)
|
self.start_node(1)
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
|
||||||
# Make sure we use hd, keep chainid
|
# Make sure we use hd, keep chainid
|
||||||
chainid = self.nodes[1].getwalletinfo()['hdchainid']
|
chainid = self.nodes[1].getwalletinfo()['hdchainid']
|
||||||
@ -92,7 +92,7 @@ class WalletHDTest(BitcoinTestFramework):
|
|||||||
assert_equal(hd_info_2["hdkeypath"], "m/44'/1'/0'/0/"+str(i))
|
assert_equal(hd_info_2["hdkeypath"], "m/44'/1'/0'/0/"+str(i))
|
||||||
assert_equal(hd_info_2["hdchainid"], chainid)
|
assert_equal(hd_info_2["hdchainid"], chainid)
|
||||||
assert_equal(hd_add, hd_add_2)
|
assert_equal(hd_add, hd_add_2)
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
# Needs rescan
|
# Needs rescan
|
||||||
@ -108,7 +108,7 @@ class WalletHDTest(BitcoinTestFramework):
|
|||||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "llmq"))
|
shutil.rmtree(os.path.join(self.nodes[1].datadir, self.chain, "llmq"))
|
||||||
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, self.chain, "wallets", "wallet.dat"))
|
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, self.chain, "wallets", "wallet.dat"))
|
||||||
self.start_node(1, extra_args=self.extra_args[1])
|
self.start_node(1, extra_args=self.extra_args[1])
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
# Wallet automatically scans blocks older than key on startup
|
# Wallet automatically scans blocks older than key on startup
|
||||||
assert_equal(self.nodes[1].getbalance(), NUM_HD_ADDS + 1)
|
assert_equal(self.nodes[1].getbalance(), NUM_HD_ADDS + 1)
|
||||||
|
@ -16,7 +16,7 @@ import shutil
|
|||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_equal,
|
assert_equal,
|
||||||
connect_nodes_bi,
|
connect_nodes,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
|
|||||||
self.stop_node(1)
|
self.stop_node(1)
|
||||||
shutil.copyfile(wallet_path, wallet_backup_path)
|
shutil.copyfile(wallet_path, wallet_backup_path)
|
||||||
self.start_node(1, self.extra_args[1])
|
self.start_node(1, self.extra_args[1])
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
|
||||||
self.log.info("Generate keys for wallet")
|
self.log.info("Generate keys for wallet")
|
||||||
for _ in range(90):
|
for _ in range(90):
|
||||||
@ -57,7 +57,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
|
|||||||
self.stop_node(1)
|
self.stop_node(1)
|
||||||
shutil.copyfile(wallet_backup_path, wallet_path)
|
shutil.copyfile(wallet_backup_path, wallet_path)
|
||||||
self.start_node(1, self.extra_args[1])
|
self.start_node(1, self.extra_args[1])
|
||||||
connect_nodes_bi(self.nodes, 0, 1)
|
connect_nodes(self.nodes[0], 1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
self.log.info("Verify keypool is restored and balance is correct")
|
self.log.info("Verify keypool is restored and balance is correct")
|
||||||
|
@ -5,7 +5,13 @@
|
|||||||
"""Test the listsincelast RPC."""
|
"""Test the listsincelast RPC."""
|
||||||
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal, assert_array_result, assert_raises_rpc_error
|
from test_framework.util import (
|
||||||
|
assert_array_result,
|
||||||
|
assert_equal,
|
||||||
|
assert_raises_rpc_error,
|
||||||
|
connect_nodes,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ListSinceBlockTest(BitcoinTestFramework):
|
class ListSinceBlockTest(BitcoinTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
@ -16,6 +22,9 @@ class ListSinceBlockTest (BitcoinTestFramework):
|
|||||||
self.skip_if_no_wallet()
|
self.skip_if_no_wallet()
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
|
# All nodes are in IBD from genesis, so they'll need the miner (node2) to be an outbound connection, or have
|
||||||
|
# only one connection. (See fPreferredDownload in net_processing)
|
||||||
|
connect_nodes(self.nodes[1], 2)
|
||||||
self.nodes[2].generate(101)
|
self.nodes[2].generate(101)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
|
|||||||
"llmq/signing -> net_processing -> llmq/signing"
|
"llmq/signing -> net_processing -> llmq/signing"
|
||||||
"llmq/signing_shares -> net_processing -> llmq/signing_shares"
|
"llmq/signing_shares -> net_processing -> llmq/signing_shares"
|
||||||
"logging -> util/system -> logging"
|
"logging -> util/system -> logging"
|
||||||
|
"logging -> util/system -> random -> logging"
|
||||||
"masternode/payments -> validation -> masternode/payments"
|
"masternode/payments -> validation -> masternode/payments"
|
||||||
"net -> netmessagemaker -> net"
|
"net -> netmessagemaker -> net"
|
||||||
"net_processing -> spork -> net_processing"
|
"net_processing -> spork -> net_processing"
|
||||||
|
Loading…
Reference in New Issue
Block a user