Closes #3597. TransactionBuilder checks tx version before adding Sapling spends and outputs.

This commit is contained in:
Simon 2018-11-07 20:38:14 -08:00
parent 59758e32f2
commit 7a9b6f8435
2 changed files with 45 additions and 0 deletions

View File

@ -333,3 +333,38 @@ TEST(TransactionBuilder, SetFee)
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
}
TEST(TransactionBuilder, CheckSaplingTxVersion)
{
SelectParams(CBaseChainParams::REGTEST);
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
auto consensusParams = Params().GetConsensus();
auto sk = libzcash::SaplingSpendingKey::random();
auto expsk = sk.expanded_spending_key();
auto pk = sk.default_address();
// Cannot add Sapling outputs to a non-Sapling transaction
auto builder = TransactionBuilder(consensusParams, 1);
try {
builder.AddSaplingOutput(uint256(), pk, 12345, {});
} catch (std::runtime_error const & err) {
EXPECT_EQ(err.what(), std::string("TransactionBuilder cannot add Sapling output to pre-Sapling transaction"));
} catch(...) {
FAIL() << "Expected std::runtime_error";
}
// Cannot add Sapling spends to a non-Sapling transaction
libzcash::SaplingNote note(pk, 50000);
SaplingMerkleTree tree;
try {
builder.AddSaplingSpend(expsk, note, uint256(), tree.witness());
} catch (std::runtime_error const & err) {
EXPECT_EQ(err.what(), std::string("TransactionBuilder cannot add Sapling spend to pre-Sapling transaction"));
} catch(...) {
FAIL() << "Expected std::runtime_error";
}
// Revert to default
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
}

View File

@ -34,6 +34,11 @@ bool TransactionBuilder::AddSaplingSpend(
uint256 anchor,
SaplingWitness witness)
{
// Sanity check: cannot add Sapling spend to pre-Sapling transaction
if (mtx.nVersion < SAPLING_TX_VERSION) {
throw std::runtime_error("TransactionBuilder cannot add Sapling spend to pre-Sapling transaction");
}
// Consistency check: all anchors must equal the first one
if (!spends.empty()) {
if (spends[0].anchor != anchor) {
@ -52,6 +57,11 @@ void TransactionBuilder::AddSaplingOutput(
CAmount value,
std::array<unsigned char, ZC_MEMO_SIZE> memo)
{
// Sanity check: cannot add Sapling output to pre-Sapling transaction
if (mtx.nVersion < SAPLING_TX_VERSION) {
throw std::runtime_error("TransactionBuilder cannot add Sapling output to pre-Sapling transaction");
}
auto note = libzcash::SaplingNote(to, value);
outputs.emplace_back(ovk, note, memo);
mtx.valueBalance -= value;