Clean up RPC tests (#1465)

* Enable full block tests
* Fix invalidblocktest
* Move watch only address funding to immediately before it's used, so node 0 doesn't spend the output before it checks it later.
* Fix `fundrawtransaction` tests and sanitize fee calculation at the same time
* Correct resolution of chain parameters when validating tx inputs, especially from previous coinbase transactions
* Set block versions on full block tests so that the generated blocks are AuxPoW compatible
This commit is contained in:
Ross Nicoll 2018-02-11 21:00:50 +00:00 committed by GitHub
parent c71589f237
commit 933436c265
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 53 additions and 53 deletions

View file

@ -103,7 +103,7 @@ testScripts = [
'wallet-hd.py',
'walletbackup.py',
# vv Tests less than 5m vv
# 'p2p-fullblocktest.py',
'p2p-fullblocktest.py',
'fundrawtransaction.py',
#'p2p-compactblocks.py',
# 'segwit.py',
@ -145,7 +145,7 @@ testScripts = [
'keypool.py',
'p2p-mempool.py',
'prioritise_transaction.py',
# 'invalidblockrequest.py',
'invalidblockrequest.py',
# 'invalidtxrequest.py',
# 'p2p-versionbits-warning.py',
'preciousblock.py',

View file

@ -54,13 +54,6 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[0].generate(121)
self.sync_all()
watchonly_address = self.nodes[0].getnewaddress()
watchonly_pubkey = self.nodes[0].validateaddress(watchonly_address)["pubkey"]
watchonly_amount = Decimal(200)
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5.0)
@ -610,6 +603,16 @@ class RawTransactionsTest(BitcoinTestFramework):
# test a fundrawtransaction using only watchonly #
##################################################
watchonly_address = self.nodes[0].getnewaddress()
watchonly_pubkey = self.nodes[0].validateaddress(watchonly_address)["pubkey"]
watchonly_amount = Decimal(2000)
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
self.nodes[0].generate(1)
self.sync_all()
inputs = []
outputs = {self.nodes[2].getnewaddress() : watchonly_amount / 2}
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
@ -661,7 +664,7 @@ class RawTransactionsTest(BitcoinTestFramework):
result = self.nodes[3].fundrawtransaction(rawtx) # uses min_relay_tx_fee (set by settxfee)
result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee})
result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10*min_relay_tx_fee})
result_fee_rate = result['fee'] * 1000 / count_bytes(result['hex'])
result_fee_rate = result['fee'] * 1000 / round_tx_size(count_bytes(result['hex']))
assert_fee_amount(result2['fee'], count_bytes(result2['hex']), 2 * result_fee_rate)
assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate)
@ -699,7 +702,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(len(self.nodes[3].listunspent(1)), 1)
inputs = []
outputs = {self.nodes[2].getnewaddress(): 1}
outputs = {self.nodes[2].getnewaddress(): 10}
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
result = [self.nodes[3].fundrawtransaction(rawtx), # uses min_relay_tx_fee (set by settxfee)
@ -722,7 +725,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(change[3] + result[3]['fee'], change[4])
inputs = []
outputs = {self.nodes[2].getnewaddress(): value for value in (1.0, 1.1, 1.2, 1.3)}
outputs = {self.nodes[2].getnewaddress(): value for value in (10, 11, 12, 13)}
keys = list(outputs.keys())
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)

View file

@ -58,7 +58,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
Now we need that block to mature so we can spend the coinbase.
'''
test = TestInstance(sync_every_block=False)
for i in range(100):
for i in range(60):
block = create_block(self.tip, create_coinbase(height), self.block_time)
block.solve()
self.tip = block.sha256
@ -103,7 +103,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
'''
block3 = create_block(self.tip, create_coinbase(height), self.block_time)
self.block_time += 1
block3.vtx[0].vout[0].nValue = 100 * COIN # Too high!
block3.vtx[0].vout[0].nValue = 10000000 * COIN # Too high!
block3.vtx[0].sha256=None
block3.vtx[0].calc_sha256()
block3.hashMerkleRoot = block3.calc_merkle_root()

View file

@ -6,8 +6,8 @@
#
# Test spending coinbase transactions.
# The coinbase transaction in block N can appear in block
# N+100... so is valid in the mempool when the best block
# height is N+99.
# N+60... so is valid in the mempool when the best block
# height is N+59.
# This test makes sure coinbase spends that will be mature
# in the next block are accepted into the memory pool,
# but less mature coinbase spends are NOT.
@ -43,21 +43,21 @@ class MempoolSpendCoinbaseTest(BitcoinTestFramework):
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
spends_raw = [ create_tx(self.nodes[0], txid, node0_address, 500000) for txid in coinbase_txids ]
spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0])
spend_61_id = self.nodes[0].sendrawtransaction(spends_raw[0])
# coinbase at height 102 should be too immature to spend
# coinbase at height 62 should be too immature to spend
assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, spends_raw[1])
# mempool should have just spend_101:
assert_equal(self.nodes[0].getrawmempool(), [ spend_101_id ])
# mempool should have just spend_61:
assert_equal(self.nodes[0].getrawmempool(), [ spend_61_id ])
# mine a block, spend_101 should get confirmed
# mine a block, spend_61 should get confirmed
self.nodes[0].generate(1)
assert_equal(set(self.nodes[0].getrawmempool()), set())
# ... and now height 102 can be spent:
spend_102_id = self.nodes[0].sendrawtransaction(spends_raw[1])
assert_equal(self.nodes[0].getrawmempool(), [ spend_102_id ])
# ... and now height 62 can be spent:
spend_62_id = self.nodes[0].sendrawtransaction(spends_raw[1])
assert_equal(self.nodes[0].getrawmempool(), [ spend_62_id ])
if __name__ == '__main__':
MempoolSpendCoinbaseTest().main()

View file

@ -616,6 +616,7 @@ class FullBlockTest(ComparisonTestFramework):
height = self.block_heights[self.tip.sha256] + 1
coinbase = create_coinbase(height, self.coinbase_pubkey)
b44 = CBlock()
b44.nVersion = 0x620004
b44.nTime = self.tip.nTime + 1
b44.hashPrevBlock = self.tip.sha256
b44.nBits = 0x207fffff
@ -630,6 +631,7 @@ class FullBlockTest(ComparisonTestFramework):
# A block with a non-coinbase as the first tx
non_coinbase = create_tx(out[15].tx, out[15].n, 1)
b45 = CBlock()
b44.nVersion = 0x620004
b45.nTime = self.tip.nTime + 1
b45.hashPrevBlock = self.tip.sha256
b45.nBits = 0x207fffff
@ -645,6 +647,7 @@ class FullBlockTest(ComparisonTestFramework):
# A block with no txns
tip(44)
b46 = CBlock()
b44.nVersion = 0x620004
b46.nTime = b44.nTime+1
b46.hashPrevBlock = b44.sha256
b46.nBits = 0x207fffff

View file

@ -25,6 +25,11 @@ CAmount CFeeRate::GetFee(size_t nBytes_) const
assert(nBytes_ <= uint64_t(std::numeric_limits<int64_t>::max()));
int64_t nSize = int64_t(nBytes_);
// Dogecoin: Round up to the nearest 1000 bytes so we get round tx fees
if (nSize % 1000 > 0) {
nSize = nSize + 1000 - (nSize % 1000);
}
CAmount nFee = nSatoshisPerK * nSize / 1000;
if (nFee == 0 && nSize != 0) {

View file

@ -221,6 +221,7 @@ public:
consensus.nHeightEffective = 0;
consensus.nPowTargetTimespan = 4 * 60 * 60; // pre-digishield: 4 hours
consensus.fDigishieldDifficultyCalculation = false;
consensus.nCoinbaseMaturity = 30;
consensus.fPowAllowMinDifficultyBlocks = true;
consensus.fPowAllowDigishieldMinDifficultyBlocks = false;
consensus.nSubsidyHalvingInterval = 100000;

View file

@ -16,8 +16,6 @@ static const unsigned int MAX_BLOCK_WEIGHT = 4000000;
static const unsigned int MAX_BLOCK_BASE_SIZE = 1000000;
/** The maximum allowed number of signature check operations in a block (network rule) */
static const int64_t MAX_BLOCK_SIGOPS_COST = 80000;
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
static const int COINBASE_MATURITY = 60*4; // 4 hours of blocks
/** Flags for nSequence and nLockTime locks */
enum {

View file

@ -146,17 +146,6 @@ CAmount GetDogecoinBlockSubsidy(int nHeight, const Consensus::Params& consensusP
}
}
unsigned int GetDogecoinTxSize(const unsigned int nTxBytes)
{
// Dogecoin: Round TX bytes up to the next 1,000 bytes
unsigned int nMod = nTxBytes % 1000;
if (nMod > 0) {
return nTxBytes + 1000 - nMod;
} else {
return nTxBytes;
}
}
CAmount GetDogecoinMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree)
{
{

View file

@ -18,6 +18,5 @@ unsigned int CalculateDogecoinNextWorkRequired(const CBlockIndex* pindexLast, in
*/
bool CheckAuxPowProofOfWork(const CBlockHeader& block, const Consensus::Params& params);
unsigned int GetDogecoinTxSize(const unsigned int nTxBytes);
CAmount GetDogecoinMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
CAmount GetDogecoinDustFee(const std::vector<CTxOut> &vout, CFeeRate &baseFeeRate);

View file

@ -1644,7 +1644,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// If pruning, don't inv blocks unless we have on disk and are likely to still have
// for some reasonable time window (1 hour) that block relay might require.
const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / chainparams.GetConsensus(pindex->nHeight).nPowTargetSpacing;
if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= chainActive.Tip()->nHeight - nPrunedBlocksLikelyToHave))
if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= chainActive.Height() - nPrunedBlocksLikelyToHave))
{
LogPrint("net", " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
break;

View file

@ -36,6 +36,9 @@ FastRandomContext insecure_rand_ctx(true);
extern bool fPrintToConsole;
extern void noui_connect();
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
static const int COINBASE_MATURITY = 60*4; // 4 hours of blocks
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
{
ECC_Start();

View file

@ -658,6 +658,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
const int64_t nSpendHeight = GetSpendHeight(mempoolDuplicate);
const CChainParams& params = Params();
LOCK(cs);
std::list<const CTxMemPoolEntry*> waitingOnDependants;
@ -739,7 +740,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
else {
CValidationState state;
bool fCheckResult = tx.IsCoinBase() ||
Consensus::CheckTxInputs(tx, state, mempoolDuplicate, nSpendHeight);
Consensus::CheckTxInputs(params, tx, state, mempoolDuplicate, nSpendHeight);
assert(fCheckResult);
UpdateCoins(tx, mempoolDuplicate, 1000000);
}
@ -755,7 +756,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
assert(stepsSinceLastRemove < waitingOnDependants.size());
} else {
bool fCheckResult = entry->GetTx().IsCoinBase() ||
Consensus::CheckTxInputs(entry->GetTx(), state, mempoolDuplicate, nSpendHeight);
Consensus::CheckTxInputs(params, entry->GetTx(), state, mempoolDuplicate, nSpendHeight);
assert(fCheckResult);
UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000);
stepsSinceLastRemove = 0;

View file

@ -1396,7 +1396,7 @@ int GetSpendHeight(const CCoinsViewCache& inputs)
}
namespace Consensus {
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight)
bool CheckTxInputs(const CChainParams& params, const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight)
{
// This doesn't trigger the DoS code on purpose; if it did, it would make it easier
// for an attacker to attempt to split the network.
@ -1414,7 +1414,7 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
// If prev is coinbase, check that it's matured
if (coins->IsCoinBase()) {
// Dogecoin: Switch maturity at depth 145,000
int nCoinbaseMaturity = Params().GetConsensus(coins->nHeight)->nCoinbaseMaturity;
int nCoinbaseMaturity = params.GetConsensus(coins->nHeight).nCoinbaseMaturity;
if (nSpendHeight - coins->nHeight < nCoinbaseMaturity)
return state.Invalid(false,
REJECT_INVALID, "bad-txns-premature-spend-of-coinbase",
@ -1447,7 +1447,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
{
if (!tx.IsCoinBase())
{
if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs)))
if (!Consensus::CheckTxInputs(Params(), tx, state, inputs, GetSpendHeight(inputs)))
return false;
if (pvChecks)
@ -2458,7 +2458,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c
}
if (fBlocksDisconnected) {
mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
mempool.removeForReorg(pcoinsTip, chainActive.Height() + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
LimitMempoolSize(mempool, GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
}
mempool.check(pcoinsTip);
@ -2627,7 +2627,7 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C
// ActivateBestChain considers blocks already in chainActive
// unconditionally valid already, so force disconnect away from it.
if (!DisconnectTip(state, chainparams)) {
mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
mempool.removeForReorg(pcoinsTip, chainActive.Height() + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
return false;
}
}
@ -2645,7 +2645,7 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C
}
InvalidChainFound(pindex);
mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
mempool.removeForReorg(pcoinsTip, chainActive.Height() + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev);
return true;
}
@ -3423,7 +3423,7 @@ void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeig
return;
// last block to prune is the lesser of (user-specified height, MIN_BLOCKS_TO_KEEP from the tip)
unsigned int nLastBlockWeCanPrune = std::min((unsigned)nManualPruneHeight, chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP);
unsigned int nLastBlockWeCanPrune = std::min((unsigned)nManualPruneHeight, chainActive.Height() - MIN_BLOCKS_TO_KEEP);
int count=0;
for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) {
if (vinfoBlockFile[fileNumber].nSize == 0 || vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune)
@ -3449,11 +3449,11 @@ void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight
if (chainActive.Tip() == NULL || nPruneTarget == 0) {
return;
}
if ((uint64_t)chainActive.Tip()->nHeight <= nPruneAfterHeight) {
if ((uint64_t)chainActive.Height() <= nPruneAfterHeight) {
return;
}
unsigned int nLastBlockWeCanPrune = chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP;
unsigned int nLastBlockWeCanPrune = chainActive.Height() - MIN_BLOCKS_TO_KEEP;
uint64_t nCurrentUsage = CalculateCurrentUsage();
// We don't check to prune until after we've allocated new space for files
// So we should leave a buffer under our target to account for another allocation

View file

@ -386,7 +386,7 @@ namespace Consensus {
* This does not modify the UTXO set. This does not check scripts and sigs.
* Preconditions: tx.IsCoinBase() is false.
*/
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight);
bool CheckTxInputs(const CChainParams& params, const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight);
} // namespace Consensus

View file

@ -2807,14 +2807,12 @@ bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwa
CAmount CWallet::GetRequiredFee(const CMutableTransaction& tx, unsigned int nTxBytes)
{
nTxBytes = GetDogecoinTxSize(nTxBytes);
// Dogecoin: Add an increased fee for each dust output
return std::max(minTxFee.GetFee(nTxBytes) + GetDogecoinDustFee(tx.vout, minTxFee), ::minRelayTxFee.GetFee(nTxBytes));
}
CAmount CWallet::GetRequiredFee(unsigned int nTxBytes)
{
nTxBytes = GetDogecoinTxSize(nTxBytes);
return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes));
}