Auto merge of #4304 - oxarbitrage:issue3893, r=str4d

Add status to transactions in RPC calls

Closes https://github.com/zcash/zcash/issues/3893.
This commit is contained in:
Homu 2020-05-12 03:05:37 +00:00
commit d0b533aacb
2 changed files with 102 additions and 0 deletions

View File

@ -86,6 +86,8 @@ void EnsureWalletIsUnlocked()
void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
{
int confirms = wtx.GetDepthInMainChain();
std::string status = "waiting";
entry.push_back(Pair("confirmations", confirms));
if (wtx.IsCoinBase())
entry.push_back(Pair("generated", true));
@ -95,7 +97,18 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
entry.push_back(Pair("blockindex", wtx.nIndex));
entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
entry.push_back(Pair("expiryheight", (int64_t)wtx.nExpiryHeight));
status = "mined";
}
else
{
const int height = chainActive.Height();
if (!IsExpiredTx(wtx, height) && IsExpiringSoonTx(wtx, height + 1))
status = "expiringsoon";
else if (IsExpiredTx(wtx, height))
status = "expired";
}
entry.push_back(Pair("status", status));
uint256 hash = wtx.GetHash();
entry.push_back(Pair("txid", hash.GetHex()));
UniValue conflicts(UniValue::VARR);
@ -1443,6 +1456,8 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
" transaction between accounts, and not associated with an address,\n"
" transaction id or block. 'send' and 'receive' transactions are \n"
" associated with an address, transaction id and block details\n"
" \"status\" : \"mined|waiting|expiringsoon|expired\", (string) The transaction status, can be 'mined', 'waiting', 'expiringsoon' \n"
" or 'expired'. Available for 'send' and 'receive' category of transactions.\n"
" \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n"
" 'move' category for moves outbound. It is positive for the 'receive' category,\n"
" and for the 'move' category for inbound funds.\n"
@ -1639,6 +1654,8 @@ UniValue listsinceblock(const UniValue& params, bool fHelp)
" \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
" \"address\":\"zcashaddress\", (string) The Zcash address of the transaction. Not present for move transactions (category = move).\n"
" \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
" \"status\" : \"mined|waiting|expiringsoon|expired\", (string) The transaction status, can be 'mined', 'waiting', 'expiringsoon' \n"
" or 'expired'. Available for 'send' and 'receive' category of transactions.\n"
" \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n"
" outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
" \"vout\" : n, (numeric) the vout value\n"
@ -1725,6 +1742,7 @@ UniValue gettransaction(const UniValue& params, bool fHelp)
"2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
"\nResult:\n"
"{\n"
" \"status\" : \"mined|waiting|expiringsoon|expired\", (string) The transaction status, can be 'mined', 'waiting', 'expiringsoon' or 'expired'\n"
" \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
" \"confirmations\" : n, (numeric) The number of confirmations\n"
" \"blockhash\" : \"hash\", (string) The block hash\n"

View File

@ -2008,5 +2008,89 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_internals)
}
}
void TestWTxStatus(const Consensus::Params consensusParams, const int delta) {
auto AddTrx = [&consensusParams]() {
auto taddr = pwalletMain->GenerateNewKey().GetID();
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, 1);
CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(taddr) << OP_EQUALVERIFY << OP_CHECKSIG;
mtx.vout.push_back(CTxOut(5 * COIN, scriptPubKey));
CWalletTx wtx(pwalletMain, mtx);
pwalletMain->AddToWallet(wtx, true, NULL);
return wtx;
};
vector<uint256> hashes;
CWalletTx wtx;
auto FakeMine = [&](const int height, bool has_trx) {
BOOST_CHECK_EQUAL(height, chainActive.Height());
CBlock block;
if (has_trx) block.vtx.push_back(wtx);
block.hashMerkleRoot = block.BuildMerkleTree();
auto blockHash = block.GetHash();
CBlockIndex fakeIndex {block};
fakeIndex.nHeight = height+1;
mapBlockIndex.insert(std::make_pair(blockHash, &fakeIndex));
chainActive.SetTip(&fakeIndex);
BOOST_CHECK(chainActive.Contains(&fakeIndex));
BOOST_CHECK_EQUAL(height+1, chainActive.Height());
if (has_trx) {
wtx.SetMerkleBranch(block);
pwalletMain->AddToWallet(wtx, true, NULL);
}
hashes.push_back(blockHash);
UniValue retValue = CallRPC("gettransaction " + wtx.GetHash().GetHex());
return retValue.get_obj();
};
// Add a transaction to the wallet
wtx = AddTrx();
// Mine blocks but never include the transaction, check status of wallet trx
for(int i=0; i<=delta + 1; i++) {
auto retObj = FakeMine(i, false);
BOOST_CHECK_EQUAL(find_value(retObj, "confirmations").get_real(), -1);
auto status = find_value(retObj, "status").get_str();
if (i >= delta - TX_EXPIRING_SOON_THRESHOLD && i <= delta)
BOOST_CHECK_EQUAL(status, "expiringsoon");
else if (i >= delta - TX_EXPIRING_SOON_THRESHOLD)
BOOST_CHECK_EQUAL(status, "expired");
else
BOOST_CHECK_EQUAL(status, "waiting");
}
// Now mine including the transaction, check status
auto retObj = FakeMine(delta + 2, true);
BOOST_CHECK_EQUAL(find_value(retObj, "confirmations").get_real(), 1);
BOOST_CHECK_EQUAL(find_value(retObj, "status").get_str(), "mined");
// Cleanup
chainActive.SetTip(NULL);
for (auto hash : hashes)
mapBlockIndex.erase(hash);
}
BOOST_AUTO_TEST_CASE(rpc_gettransaction_status_sapling)
{
LOCK2(cs_main, pwalletMain->cs_wallet);
TestWTxStatus(RegtestActivateSapling(), DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA);
RegtestDeactivateSapling();
}
BOOST_AUTO_TEST_CASE(rpc_gettransaction_status_blossom)
{
LOCK2(cs_main, pwalletMain->cs_wallet);
TestWTxStatus(RegtestActivateBlossom(true), DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA);
RegtestDeactivateBlossom();
}
BOOST_AUTO_TEST_SUITE_END()