diff --git a/src/gtest/test_transaction_builder.cpp b/src/gtest/test_transaction_builder.cpp index f7ab416a3..399562190 100644 --- a/src/gtest/test_transaction_builder.cpp +++ b/src/gtest/test_transaction_builder.cpp @@ -272,3 +272,64 @@ TEST(TransactionBuilder, ChangeOutput) UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); } + +TEST(TransactionBuilder, SetFee) +{ + SelectParams(CBaseChainParams::REGTEST); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + auto consensusParams = Params().GetConsensus(); + + // Generate dummy Sapling address + auto sk = libzcash::SaplingSpendingKey::random(); + auto xsk = sk.expanded_spending_key(); + auto fvk = sk.full_viewing_key(); + auto pk = sk.default_address(); + + // Generate dummy Sapling note + libzcash::SaplingNote note(pk, 50000); + auto cm = note.cm().value(); + ZCSaplingIncrementalMerkleTree tree; + tree.append(cm); + auto anchor = tree.root(); + auto witness = tree.witness(); + + // Default fee + { + auto builder = TransactionBuilder(consensusParams, 1); + ASSERT_TRUE(builder.AddSaplingSpend(xsk, note, anchor, witness)); + builder.AddSaplingOutput(fvk, pk, 25000, {}); + auto maybe_tx = builder.Build(); + ASSERT_EQ(static_cast(maybe_tx), true); + auto tx = maybe_tx.get(); + + EXPECT_EQ(tx.vin.size(), 0); + EXPECT_EQ(tx.vout.size(), 0); + EXPECT_EQ(tx.vjoinsplit.size(), 0); + EXPECT_EQ(tx.vShieldedSpend.size(), 1); + EXPECT_EQ(tx.vShieldedOutput.size(), 2); + EXPECT_EQ(tx.valueBalance, 10000); + } + + // Configured fee + { + auto builder = TransactionBuilder(consensusParams, 1); + ASSERT_TRUE(builder.AddSaplingSpend(xsk, note, anchor, witness)); + builder.AddSaplingOutput(fvk, pk, 25000, {}); + builder.SetFee(20000); + auto maybe_tx = builder.Build(); + ASSERT_EQ(static_cast(maybe_tx), true); + auto tx = maybe_tx.get(); + + EXPECT_EQ(tx.vin.size(), 0); + EXPECT_EQ(tx.vout.size(), 0); + EXPECT_EQ(tx.vjoinsplit.size(), 0); + EXPECT_EQ(tx.vShieldedSpend.size(), 1); + EXPECT_EQ(tx.vShieldedOutput.size(), 2); + EXPECT_EQ(tx.valueBalance, 20000); + } + + // Revert to default + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); +} diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index d1f9a0f0b..e7fac9a35 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -79,6 +79,11 @@ bool TransactionBuilder::AddTransparentOutput(CTxDestination& to, CAmount value) return true; } +void TransactionBuilder::SetFee(CAmount fee) +{ + this->fee = fee; +} + void TransactionBuilder::SendChangeTo(libzcash::SaplingPaymentAddress changeAddr, libzcash::SaplingFullViewingKey fvkOut) { zChangeAddr = std::make_pair(fvkOut, changeAddr); @@ -97,9 +102,6 @@ bool TransactionBuilder::SendChangeTo(CTxDestination& changeAddr) boost::optional TransactionBuilder::Build() { - // Fixed fee - const CAmount fee = 10000; - // // Consistency checks // diff --git a/src/transaction_builder.h b/src/transaction_builder.h index 3b5b68368..d01260497 100644 --- a/src/transaction_builder.h +++ b/src/transaction_builder.h @@ -59,6 +59,7 @@ private: int nHeight; const CKeyStore* keystore; CMutableTransaction mtx; + CAmount fee = 10000; std::vector spends; std::vector outputs; @@ -70,6 +71,8 @@ private: public: TransactionBuilder(const Consensus::Params& consensusParams, int nHeight, CKeyStore* keyStore = nullptr); + void SetFee(CAmount fee); + // Returns false if the anchor does not match the anchor used by // previously-added Sapling spends. bool AddSaplingSpend(