Merge #21121: [test] Small unit test improvements, including helper to make mempool transaction

1363b6c27d [doc / util] Use comments to clarify time unit for int64_t type. (Amiti Uttarwar)
47a7a1687d [util] Introduce a SetMockTime that takes chrono time (Amiti Uttarwar)
df6a5fc1df [util] Change GetMockTime to return chrono type instead of int (Amiti Uttarwar)
a2d908e1da [test] Throw error instead of segfaulting in failure scenario (Amiti Uttarwar)
9a3bbe8fc5 [test] Introduce a unit test helper to create a valid mempool transaction. (Amiti Uttarwar)

Pull request description:

  Some miscellaneous improvements that came up when working on #21061
  - The first commit is a helper to make valid mempool transactions & submit via ATMP. Introducing in this PR, using in #21061.
  - The second commit is a small improvement in `miner_tests.cpp` that uses `BOOST_REQUIRE_EQUAL` to properly terminate the program instead of segfaulting in the failure scenario where the blocks do not include the expected number of transactions.
  - The third commit changes the function signature of `GetMockTime()` to return a chrono type.
  - The fourth & fifth commit overload `SetMockTime` to also accept chrono type, and adds documentation to indicate that the `int64_t` function signature is deprecated.

ACKs for top commit:
  vasild:
    ACK 1363b6c27d

Tree-SHA512: c72574d73668ea04ee4c33858f8de68b368780f445e05afb569aaf8564093f8112259b3afe93cf6dc2ee12a1ab5af1130ac73c16416132c1ba2851c054a67d78
This commit is contained in:
MarcoFalke 2021-02-17 10:40:02 +01:00
commit 569b5ba1dc
No known key found for this signature in database
GPG Key ID: D2EA4850E7528B25
6 changed files with 90 additions and 7 deletions

View File

@ -203,9 +203,9 @@ std::string BCLog::Logger::LogTimestampStr(const std::string& str)
strStamped.pop_back();
strStamped += strprintf(".%06dZ", nTimeMicros%1000000);
}
int64_t mocktime = GetMockTime();
if (mocktime) {
strStamped += " (mocktime: " + FormatISO8601DateTime(mocktime) + ")";
std::chrono::seconds mocktime = GetMockTime();
if (mocktime > 0s) {
strStamped += " (mocktime: " + FormatISO8601DateTime(count_seconds(mocktime)) + ")";
}
strStamped += ' ' + str;
} else

View File

@ -123,6 +123,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co
m_node.mempool->addUnchecked(entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 4);
BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashMediumFeeTx);
@ -157,6 +158,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co
hashLowFeeTx = tx.GetHash();
m_node.mempool->addUnchecked(entry.Fee(feeToUse+2).FromTx(tx));
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6);
BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx);
BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx);
@ -191,6 +193,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co
tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
m_node.mempool->addUnchecked(entry.Fee(10000).FromTx(tx));
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 9);
BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
}

View File

@ -260,6 +260,55 @@ CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransa
return block;
}
CMutableTransaction TestChain100Setup::CreateValidMempoolTransaction(CTransactionRef input_transaction,
int input_vout,
int input_height,
CKey input_signing_key,
CScript output_destination,
CAmount output_amount)
{
// Transaction we will submit to the mempool
CMutableTransaction mempool_txn;
// Create an input
COutPoint outpoint_to_spend(input_transaction->GetHash(), input_vout);
CTxIn input(outpoint_to_spend);
mempool_txn.vin.push_back(input);
// Create an output
CTxOut output(output_amount, output_destination);
mempool_txn.vout.push_back(output);
// Sign the transaction
// - Add the signing key to a keystore
FillableSigningProvider keystore;
keystore.AddKey(input_signing_key);
// - Populate a CoinsViewCache with the unspent output
CCoinsView coins_view;
CCoinsViewCache coins_cache(&coins_view);
AddCoins(coins_cache, *input_transaction.get(), input_height);
// - Use GetCoin to properly populate utxo_to_spend,
Coin utxo_to_spend;
assert(coins_cache.GetCoin(outpoint_to_spend, utxo_to_spend));
// - Then add it to a map to pass in to SignTransaction
std::map<COutPoint, Coin> input_coins;
input_coins.insert({outpoint_to_spend, utxo_to_spend});
// - Default signature hashing type
int nHashType = SIGHASH_ALL;
std::map<int, std::string> input_errors;
assert(SignTransaction(mempool_txn, &keystore, input_coins, nHashType, input_errors));
// Add transaction to the mempool
{
LOCK(cs_main);
const MempoolAcceptResult result = AcceptToMemoryPool(*m_node.mempool.get(), MakeTransactionRef(mempool_txn), /* bypass_limits */ false);
assert(result.m_result_type == MempoolAcceptResult::ResultType::VALID);
}
return mempool_txn;
}
TestChain100Setup::~TestChain100Setup()
{
gArgs.ForceSetArg("-segwitheight", "0");

View File

@ -123,6 +123,23 @@ struct TestChain100Setup : public RegTestingSetup {
//! Mine a series of new blocks on the active chain.
void mineBlocks(int num_blocks);
/**
* Create a transaction and submit to the mempool.
*
* @param input_transaction The transaction to spend
* @param input_vout The vout to spend from the input_transaction
* @param input_height The height of the block that included the input_transaction
* @param input_signing_key The key to spend the input_transaction
* @param output_destination Where to send the output
* @param output_amount How much to send
*/
CMutableTransaction CreateValidMempoolTransaction(CTransactionRef input_transaction,
int input_vout,
int input_height,
CKey input_signing_key,
CScript output_destination,
CAmount output_amount = CAmount(1 * COIN));
~TestChain100Setup();
bool m_deterministic;

View File

@ -53,9 +53,14 @@ void SetMockTime(int64_t nMockTimeIn)
nMockTime.store(nMockTimeIn, std::memory_order_relaxed);
}
int64_t GetMockTime()
void SetMockTime(std::chrono::seconds mock_time_in)
{
return nMockTime.load(std::memory_order_relaxed);
nMockTime.store(mock_time_in.count(), std::memory_order_relaxed);
}
std::chrono::seconds GetMockTime()
{
return std::chrono::seconds(nMockTime.load(std::memory_order_relaxed));
}
int64_t GetTimeMillis()

View File

@ -43,10 +43,19 @@ int64_t GetTimeMicros();
/** Returns the system time (not mockable) */
int64_t GetSystemTimeInSeconds(); // Like GetTime(), but not mockable
/** For testing. Set e.g. with the setmocktime rpc, or -mocktime argument */
/**
* DEPRECATED
* Use SetMockTime with chrono type
*
* @param[in] nMockTimeIn Time in seconds.
*/
void SetMockTime(int64_t nMockTimeIn);
/** For testing. Set e.g. with the setmocktime rpc, or -mocktime argument */
void SetMockTime(std::chrono::seconds mock_time_in);
/** For testing */
int64_t GetMockTime();
std::chrono::seconds GetMockTime();
/** Return system time (or mocked time, if set) */
template <typename T>