Port btest rpc_z_sendmany_taddr_to_sapling to gtest suite WalletRPCTests

This commit is contained in:
sasha 2022-04-20 20:55:27 -07:00
parent 6daecd9f78
commit 6099daf8cd
2 changed files with 121 additions and 110 deletions

View File

@ -6,6 +6,7 @@
#include "consensus/validation.h"
#include "transaction_builder.h"
#include "utiltest.h"
#include "gtest/utils.h"
#include "wallet/asyncrpcoperation_mergetoaddress.h"
#include "wallet/asyncrpcoperation_shieldcoinbase.h"
#include "wallet/asyncrpcoperation_sendmany.h"
@ -231,4 +232,124 @@ TEST(WalletRPCTests, RPCZMergeToAddressInternals)
}
}
UnloadGlobalWallet();
}
TEST(WalletRPCTests, RPCZsendmanyTaddrToSapling)
{
LoadProofParameters();
SelectParams(CBaseChainParams::TESTNET);
LoadGlobalWallet();
RegtestActivateSapling();
{
LOCK2(cs_main, pwalletMain->cs_wallet);
if (!pwalletMain->HaveMnemonicSeed()) {
pwalletMain->GenerateNewSeed();
}
UniValue retValue;
KeyIO keyIO(Params());
// add keys manually
auto taddr = pwalletMain->GenerateNewKey(true).GetID();
auto pa = pwalletMain->GenerateNewLegacySaplingZKey();
const Consensus::Params& consensusParams = Params().GetConsensus();
int nextBlockHeight = chainActive.Height() + 1;
// Add a fake transaction to the wallet
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight);
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->LoadWalletTx(wtx);
// Fake-mine the transaction
EXPECT_EQ(-1, chainActive.Height());
CBlock block;
block.vtx.push_back(wtx);
block.hashMerkleRoot = block.BuildMerkleTree();
auto blockHash = block.GetHash();
CBlockIndex fakeIndex {block};
mapBlockIndex.insert(std::make_pair(blockHash, &fakeIndex));
chainActive.SetTip(&fakeIndex);
EXPECT_TRUE(chainActive.Contains(&fakeIndex));
EXPECT_EQ(0, chainActive.Height());
wtx.SetMerkleBranch(block);
pwalletMain->LoadWalletTx(wtx);
// Context that z_sendmany requires
auto builder = TransactionBuilder(consensusParams, nextBlockHeight, std::nullopt, pwalletMain);
mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight);
auto selector = pwalletMain->ZTXOSelectorForAddress(taddr, true, false).value();
std::vector<SendManyRecipient> recipients = { SendManyRecipient(std::nullopt, pa, 1*COIN, "ABCD") };
TransactionStrategy strategy(PrivacyPolicy::AllowRevealedSenders);
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 0, strategy));
std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
// Enable test mode so tx is not sent
static_cast<AsyncRPCOperation_sendmany *>(operation.get())->testmode = true;
// Generate the Sapling shielding transaction
operation->main();
if (!operation->isSuccess()) {
FAIL() << operation->getErrorMessage();
}
// Get the transaction
auto result = operation->getResult();
ASSERT_TRUE(result.isObject());
auto hexTx = result["hex"].getValStr();
CDataStream ss(ParseHex(hexTx), SER_NETWORK, PROTOCOL_VERSION);
CTransaction tx;
ss >> tx;
ASSERT_FALSE(tx.vShieldedOutput.empty());
// We shouldn't be able to decrypt with the empty ovk
EXPECT_FALSE(AttemptSaplingOutDecryption(
tx.vShieldedOutput[0].outCiphertext,
uint256(),
tx.vShieldedOutput[0].cv,
tx.vShieldedOutput[0].cmu,
tx.vShieldedOutput[0].ephemeralKey));
// We shouldn't be able to decrypt with a random ovk
EXPECT_FALSE(AttemptSaplingOutDecryption(
tx.vShieldedOutput[0].outCiphertext,
random_uint256(),
tx.vShieldedOutput[0].cv,
tx.vShieldedOutput[0].cmu,
tx.vShieldedOutput[0].ephemeralKey));
auto accountKey = pwalletMain->GetLegacyAccountKey().ToAccountPubKey();
auto ovks = accountKey.GetOVKsForShielding();
// We should not be able to decrypt with the internal change OVK for shielding
EXPECT_FALSE(AttemptSaplingOutDecryption(
tx.vShieldedOutput[0].outCiphertext,
ovks.first,
tx.vShieldedOutput[0].cv,
tx.vShieldedOutput[0].cmu,
tx.vShieldedOutput[0].ephemeralKey));
// We should be able to decrypt with the external OVK for shielding
EXPECT_TRUE(AttemptSaplingOutDecryption(
tx.vShieldedOutput[0].outCiphertext,
ovks.second,
tx.vShieldedOutput[0].cv,
tx.vShieldedOutput[0].cmu,
tx.vShieldedOutput[0].ephemeralKey));
// Tear down
chainActive.SetTip(NULL);
mapBlockIndex.erase(blockHash);
mapArgs.erase("-developersapling");
mapArgs.erase("-experimentalfeatures");
}
// Revert to default
RegtestDeactivateSapling();
UnloadGlobalWallet();
}

View File

@ -1311,116 +1311,6 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
}
}
BOOST_AUTO_TEST_CASE(rpc_z_sendmany_taddr_to_sapling)
{
RegtestActivateSapling();
LOCK2(cs_main, pwalletMain->cs_wallet);
if (!pwalletMain->HaveMnemonicSeed()) {
pwalletMain->GenerateNewSeed();
}
UniValue retValue;
KeyIO keyIO(Params());
// add keys manually
auto taddr = pwalletMain->GenerateNewKey(true).GetID();
std::string taddr1 = keyIO.EncodeDestination(taddr);
auto pa = pwalletMain->GenerateNewLegacySaplingZKey();
const Consensus::Params& consensusParams = Params().GetConsensus();
retValue = CallRPC("getblockcount");
int nextBlockHeight = retValue.get_int() + 1;
// Add a fake transaction to the wallet
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight);
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->LoadWalletTx(wtx);
// Fake-mine the transaction
BOOST_CHECK_EQUAL(0, chainActive.Height());
CBlock block;
block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
block.vtx.push_back(wtx);
block.hashMerkleRoot = block.BuildMerkleTree();
auto blockHash = block.GetHash();
CBlockIndex fakeIndex {block};
fakeIndex.nHeight = 1;
mapBlockIndex.insert(std::make_pair(blockHash, &fakeIndex));
chainActive.SetTip(&fakeIndex);
BOOST_CHECK(chainActive.Contains(&fakeIndex));
BOOST_CHECK_EQUAL(1, chainActive.Height());
wtx.SetMerkleBranch(block);
pwalletMain->LoadWalletTx(wtx);
// Context that z_sendmany requires
auto builder = TransactionBuilder(consensusParams, nextBlockHeight, std::nullopt, pwalletMain);
mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight);
auto selector = pwalletMain->ZTXOSelectorForAddress(taddr, true, false).value();
std::vector<SendManyRecipient> recipients = { SendManyRecipient(std::nullopt, pa, 1*COIN, "ABCD") };
TransactionStrategy strategy(PrivacyPolicy::AllowRevealedSenders);
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 0, strategy));
std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
// Enable test mode so tx is not sent
static_cast<AsyncRPCOperation_sendmany *>(operation.get())->testmode = true;
// Generate the Sapling shielding transaction
operation->main();
if (!operation->isSuccess()) {
BOOST_FAIL(operation->getErrorMessage());
}
// Get the transaction
auto result = operation->getResult();
BOOST_ASSERT(result.isObject());
auto hexTx = result["hex"].getValStr();
CDataStream ss(ParseHex(hexTx), SER_NETWORK, PROTOCOL_VERSION);
CTransaction tx;
ss >> tx;
BOOST_ASSERT(!tx.vShieldedOutput.empty());
// We shouldn't be able to decrypt with the empty ovk
BOOST_CHECK(!AttemptSaplingOutDecryption(
tx.vShieldedOutput[0].outCiphertext,
uint256(),
tx.vShieldedOutput[0].cv,
tx.vShieldedOutput[0].cmu,
tx.vShieldedOutput[0].ephemeralKey));
auto accountKey = pwalletMain->GetLegacyAccountKey().ToAccountPubKey();
auto ovks = accountKey.GetOVKsForShielding();
// We should not be able to decrypt with the internal change OVK for shielding
BOOST_CHECK(!AttemptSaplingOutDecryption(
tx.vShieldedOutput[0].outCiphertext,
ovks.first,
tx.vShieldedOutput[0].cv,
tx.vShieldedOutput[0].cmu,
tx.vShieldedOutput[0].ephemeralKey));
// We should be able to decrypt with the external OVK for shielding
BOOST_CHECK(AttemptSaplingOutDecryption(
tx.vShieldedOutput[0].outCiphertext,
ovks.second,
tx.vShieldedOutput[0].cv,
tx.vShieldedOutput[0].cmu,
tx.vShieldedOutput[0].ephemeralKey));
// Tear down
chainActive.SetTip(NULL);
mapBlockIndex.erase(blockHash);
mapArgs.erase("-developersapling");
mapArgs.erase("-experimentalfeatures");
// Revert to default
RegtestDeactivateSapling();
}
/*
* This test covers storing encrypted zkeys in the wallet.
*/