Auto merge of #4005 - daira:migration-expiration, r=Eirik0

Change expiry delta for migration transactions to 450 blocks

Documentation: to be done as part of the ZIP 308 update (zcash/zips#229).

Test plan: manually check that migration transactions have the expected expiry height, using getrawtransaction $TXID 1.

Closes #3999
This commit is contained in:
Homu 2019-05-10 12:31:45 -07:00
commit 664b7d32a1
11 changed files with 67 additions and 42 deletions

View File

@ -102,14 +102,25 @@ class SproutSaplingMigration(BitcoinTestFramework):
self.sync_all() self.sync_all()
# At 499 % 500 there will be a transaction in the mempool and the note will be locked # At 499 % 500 there will be a transaction in the mempool and the note will be locked
assert_equal(1, len(node.getrawmempool()), "mempool size at 499 % 500") mempool = node.getrawmempool()
print("mempool: {}".format(mempool))
assert_equal(1, len(mempool), "mempool size at 499 % 500")
assert_equal(node.z_getbalance(sproutAddr), Decimal('0')) assert_equal(node.z_getbalance(sproutAddr), Decimal('0'))
assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0'))
assert_true(node.z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling balance at 499 % 500") assert_true(node.z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling balance at 499 % 500")
# Check that unmigrated amount + unfinalized = starting balance - fee # Check that unmigrated amount + unfinalized = starting balance - fee
status = node.z_getmigrationstatus() status = node.z_getmigrationstatus()
print("status: {}".format(status))
assert_equal(Decimal('9.9999'), Decimal(status['unmigrated_amount']) + Decimal(status['unfinalized_migrated_amount'])) assert_equal(Decimal('9.9999'), Decimal(status['unmigrated_amount']) + Decimal(status['unfinalized_migrated_amount']))
# The transaction in the mempool should be the one listed in migration_txids,
# and it should expire at the next 450 % 500.
assert_equal(1, len(status['migration_txids']))
txid = status['migration_txids'][0]
assert_equal(txid, mempool[0])
tx = node.getrawtransaction(txid, 1)
assert_equal(target_height + 450, tx['expiryheight'])
node.generate(1) node.generate(1)
self.sync_all() self.sync_all()

View File

@ -93,7 +93,7 @@ TEST(TransactionBuilder, TransparentToSapling)
// Create a shielding transaction from transparent to Sapling // Create a shielding transaction from transparent to Sapling
// 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee // 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee
auto builder = TransactionBuilder(consensusParams, 1, &keystore); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore);
builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000);
builder.AddSaplingOutput(fvk_from.ovk, pk, 40000, {}); builder.AddSaplingOutput(fvk_from.ovk, pk, 40000, {});
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -125,7 +125,7 @@ TEST(TransactionBuilder, SaplingToSapling) {
// Create a Sapling-only transaction // Create a Sapling-only transaction
// 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change // 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change
auto builder = TransactionBuilder(consensusParams, 2); auto builder = TransactionBuilder(consensusParams, 2, expiryDelta);
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
// Check that trying to add a different anchor fails // Check that trying to add a different anchor fails
@ -166,7 +166,7 @@ TEST(TransactionBuilder, SaplingToSprout) {
// - 0.0004 Sapling-ZEC in - 0.00025 Sprout-ZEC out // - 0.0004 Sapling-ZEC in - 0.00025 Sprout-ZEC out
// - 0.00005 Sapling-ZEC change // - 0.00005 Sapling-ZEC change
// - 0.0001 t-ZEC fee // - 0.0001 t-ZEC fee
auto builder = TransactionBuilder(consensusParams, 2, nullptr, params); auto builder = TransactionBuilder(consensusParams, 2, expiryDelta, nullptr, params);
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
builder.AddSproutOutput(sproutAddr, 25000); builder.AddSproutOutput(sproutAddr, 25000);
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -218,7 +218,7 @@ TEST(TransactionBuilder, SproutToSproutAndSapling) {
// - 0.00005 Sprout-ZEC change // - 0.00005 Sprout-ZEC change
// - 0.00005 Sapling-ZEC out // - 0.00005 Sapling-ZEC out
// - 0.00005 t-ZEC fee // - 0.00005 t-ZEC fee
auto builder = TransactionBuilder(consensusParams, 2, nullptr, params, &view); auto builder = TransactionBuilder(consensusParams, 2, expiryDelta, nullptr, params, &view);
builder.SetFee(5000); builder.SetFee(5000);
builder.AddSproutInput(sproutSk, sproutNote, sproutWitness); builder.AddSproutInput(sproutSk, sproutNote, sproutWitness);
builder.AddSproutOutput(sproutAddr, 6000); builder.AddSproutOutput(sproutAddr, 6000);
@ -255,7 +255,7 @@ TEST(TransactionBuilder, ThrowsOnSproutOutputWithoutParams)
auto sk = libzcash::SproutSpendingKey::random(); auto sk = libzcash::SproutSpendingKey::random();
auto addr = sk.address(); auto addr = sk.address();
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
ASSERT_THROW(builder.AddSproutOutput(addr, 10), std::runtime_error); ASSERT_THROW(builder.AddSproutOutput(addr, 10), std::runtime_error);
} }
@ -264,7 +264,7 @@ TEST(TransactionBuilder, ThrowsOnTransparentInputWithoutKeyStore)
SelectParams(CBaseChainParams::REGTEST); SelectParams(CBaseChainParams::REGTEST);
auto consensusParams = Params().GetConsensus(); auto consensusParams = Params().GetConsensus();
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
ASSERT_THROW(builder.AddTransparentInput(COutPoint(), CScript(), 1), std::runtime_error); ASSERT_THROW(builder.AddTransparentInput(COutPoint(), CScript(), 1), std::runtime_error);
} }
@ -275,7 +275,7 @@ TEST(TransactionBuilder, RejectsInvalidTransparentOutput)
// Default CTxDestination type is an invalid address // Default CTxDestination type is an invalid address
CTxDestination taddr; CTxDestination taddr;
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
ASSERT_THROW(builder.AddTransparentOutput(taddr, 50), UniValue); ASSERT_THROW(builder.AddTransparentOutput(taddr, 50), UniValue);
} }
@ -286,7 +286,7 @@ TEST(TransactionBuilder, RejectsInvalidTransparentChangeAddress)
// Default CTxDestination type is an invalid address // Default CTxDestination type is an invalid address
CTxDestination taddr; CTxDestination taddr;
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
ASSERT_THROW(builder.SendChangeTo(taddr), UniValue); ASSERT_THROW(builder.SendChangeTo(taddr), UniValue);
} }
@ -311,13 +311,13 @@ TEST(TransactionBuilder, FailsWithNegativeChange)
// Fail if there is only a Sapling output // Fail if there is only a Sapling output
// 0.0005 z-ZEC out, 0.0001 t-ZEC fee // 0.0005 z-ZEC out, 0.0001 t-ZEC fee
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
builder.AddSaplingOutput(fvk.ovk, pa, 50000, {}); builder.AddSaplingOutput(fvk.ovk, pa, 50000, {});
EXPECT_EQ("Change cannot be negative", builder.Build().GetError()); EXPECT_EQ("Change cannot be negative", builder.Build().GetError());
// Fail if there is only a transparent output // Fail if there is only a transparent output
// 0.0005 t-ZEC out, 0.0001 t-ZEC fee // 0.0005 t-ZEC out, 0.0001 t-ZEC fee
builder = TransactionBuilder(consensusParams, 1, &keystore); builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore);
builder.AddTransparentOutput(taddr, 50000); builder.AddTransparentOutput(taddr, 50000);
EXPECT_EQ("Change cannot be negative", builder.Build().GetError()); EXPECT_EQ("Change cannot be negative", builder.Build().GetError());
@ -359,14 +359,14 @@ TEST(TransactionBuilder, ChangeOutput)
// No change address and no Sapling spends // No change address and no Sapling spends
{ {
auto builder = TransactionBuilder(consensusParams, 1, &keystore); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore);
builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000);
EXPECT_EQ("Could not determine change address", builder.Build().GetError()); EXPECT_EQ("Could not determine change address", builder.Build().GetError());
} }
// Change to the same address as the first Sapling spend // Change to the same address as the first Sapling spend
{ {
auto builder = TransactionBuilder(consensusParams, 1, &keystore); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore);
builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000);
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -381,7 +381,7 @@ TEST(TransactionBuilder, ChangeOutput)
// Change to a Sapling address // Change to a Sapling address
{ {
auto builder = TransactionBuilder(consensusParams, 1, &keystore); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore);
builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000);
builder.SendChangeTo(zChangeAddr, fvkOut.ovk); builder.SendChangeTo(zChangeAddr, fvkOut.ovk);
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -396,7 +396,7 @@ TEST(TransactionBuilder, ChangeOutput)
// Change to a transparent address // Change to a transparent address
{ {
auto builder = TransactionBuilder(consensusParams, 1, &keystore); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore);
builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000);
builder.SendChangeTo(taddr); builder.SendChangeTo(taddr);
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -428,7 +428,7 @@ TEST(TransactionBuilder, SetFee)
// Default fee // Default fee
{ {
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {});
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -443,7 +443,7 @@ TEST(TransactionBuilder, SetFee)
// Configured fee // Configured fee
{ {
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {});
builder.SetFee(20000); builder.SetFee(20000);
@ -472,7 +472,7 @@ TEST(TransactionBuilder, CheckSaplingTxVersion)
auto pk = sk.default_address(); auto pk = sk.default_address();
// Cannot add Sapling outputs to a non-Sapling transaction // Cannot add Sapling outputs to a non-Sapling transaction
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
try { try {
builder.AddSaplingOutput(uint256(), pk, 12345, {}); builder.AddSaplingOutput(uint256(), pk, 12345, {});
} catch (std::runtime_error const & err) { } catch (std::runtime_error const & err) {

View File

@ -6612,12 +6612,19 @@ public:
// Set default values of new CMutableTransaction based on consensus rules at given height. // Set default values of new CMutableTransaction based on consensus rules at given height.
CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight) CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight)
{ {
CMutableTransaction mtx; return CreateNewContextualCMutableTransaction(consensusParams, nHeight, expiryDelta);
}
CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight, int nExpiryDelta) {
CMutableTransaction mtx;
bool isOverwintered = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_OVERWINTER); bool isOverwintered = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_OVERWINTER);
if (isOverwintered) { if (isOverwintered) {
mtx.fOverwintered = true; mtx.fOverwintered = true;
mtx.nExpiryHeight = nHeight + expiryDelta; mtx.nExpiryHeight = nHeight + nExpiryDelta;
if (mtx.nExpiryHeight <= 0 || mtx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) {
throw new std::runtime_error("CreateNewContextualCMutableTransaction: invalid expiry height");
}
// NOTE: If the expiry height crosses into an incompatible consensus epoch, and it is changed to the last block // NOTE: If the expiry height crosses into an incompatible consensus epoch, and it is changed to the last block
// of the current epoch (see below: Overwinter->Sapling), the transaction will be rejected if it falls within // of the current epoch (see below: Overwinter->Sapling), the transaction will be rejected if it falls within

View File

@ -595,7 +595,10 @@ int GetSpendHeight(const CCoinsViewCache& inputs);
uint64_t CalculateCurrentUsage(); uint64_t CalculateCurrentUsage();
/** Return a CMutableTransaction with contextual default values based on set of consensus rules at height */ /** Return a CMutableTransaction with contextual default values based on set of consensus rules at nHeight, and the default expiry delta. */
CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight); CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight);
/** Return a CMutableTransaction with contextual default values based on set of consensus rules at nHeight, and given expiry delta. */
CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight, int nExpiryDelta);
#endif // BITCOIN_MAIN_H #endif // BITCOIN_MAIN_H

View File

@ -1302,7 +1302,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_taddr_to_sapling)
pwalletMain->AddToWallet(wtx, true, NULL); pwalletMain->AddToWallet(wtx, true, NULL);
// Context that z_sendmany requires // Context that z_sendmany requires
auto builder = TransactionBuilder(consensusParams, nextBlockHeight, pwalletMain); auto builder = TransactionBuilder(consensusParams, nextBlockHeight, expiryDelta, pwalletMain);
mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight); mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight);
std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD") }; std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD") };

View File

@ -50,6 +50,7 @@ std::string TransactionBuilderResult::GetError() {
TransactionBuilder::TransactionBuilder( TransactionBuilder::TransactionBuilder(
const Consensus::Params& consensusParams, const Consensus::Params& consensusParams,
int nHeight, int nHeight,
int nExpiryDelta,
CKeyStore* keystore, CKeyStore* keystore,
ZCJoinSplit* sproutParams, ZCJoinSplit* sproutParams,
CCoinsViewCache* coinsView, CCoinsViewCache* coinsView,
@ -61,7 +62,7 @@ TransactionBuilder::TransactionBuilder(
coinsView(coinsView), coinsView(coinsView),
cs_coinsView(cs_coinsView) cs_coinsView(cs_coinsView)
{ {
mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight); mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight, nExpiryDelta);
} }
// This exception is thrown in certain scenarios when building JoinSplits fails. // This exception is thrown in certain scenarios when building JoinSplits fails.

View File

@ -95,6 +95,7 @@ public:
TransactionBuilder( TransactionBuilder(
const Consensus::Params& consensusParams, const Consensus::Params& consensusParams,
int nHeight, int nHeight,
int nExpiryDelta,
CKeyStore* keyStore = nullptr, CKeyStore* keyStore = nullptr,
ZCJoinSplit* sproutParams = nullptr, ZCJoinSplit* sproutParams = nullptr,
CCoinsViewCache* coinsView = nullptr, CCoinsViewCache* coinsView = nullptr,

View File

@ -232,7 +232,7 @@ CWalletTx GetValidSaplingReceive(const Consensus::Params& consensusParams,
auto fvk = sk.expsk.full_viewing_key(); auto fvk = sk.expsk.full_viewing_key();
auto pa = sk.DefaultAddress(); auto pa = sk.DefaultAddress();
auto builder = TransactionBuilder(consensusParams, 1, &keyStore); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keyStore);
builder.SetFee(0); builder.SetFee(0);
builder.AddTransparentInput(COutPoint(), scriptPubKey, value); builder.AddTransparentInput(COutPoint(), scriptPubKey, value);
builder.AddSaplingOutput(fvk.ovk, pa, value, {}); builder.AddSaplingOutput(fvk.ovk, pa, value, {});

View File

@ -13,6 +13,7 @@
#include "wallet.h" #include "wallet.h"
const CAmount FEE = 10000; const CAmount FEE = 10000;
const int MIGRATION_EXPIRY_DELTA = 450;
AsyncRPCOperation_saplingmigration::AsyncRPCOperation_saplingmigration(int targetHeight) : targetHeight_(targetHeight) {} AsyncRPCOperation_saplingmigration::AsyncRPCOperation_saplingmigration(int targetHeight) : targetHeight_(targetHeight) {}
@ -98,7 +99,8 @@ bool AsyncRPCOperation_saplingmigration::main_impl() {
CCoinsViewCache coinsView(pcoinsTip); CCoinsViewCache coinsView(pcoinsTip);
do { do {
CAmount amountToSend = chooseAmount(availableFunds); CAmount amountToSend = chooseAmount(availableFunds);
auto builder = TransactionBuilder(consensusParams, targetHeight_, pwalletMain, pzcashParams, &coinsView, &cs_main); auto builder = TransactionBuilder(consensusParams, targetHeight_, MIGRATION_EXPIRY_DELTA, pwalletMain, pzcashParams,
&coinsView, &cs_main);
std::vector<CSproutNotePlaintextEntry> fromNotes; std::vector<CSproutNotePlaintextEntry> fromNotes;
CAmount fromNoteAmount = 0; CAmount fromNoteAmount = 0;
while (fromNoteAmount < amountToSend) { while (fromNoteAmount < amountToSend) {

View File

@ -379,7 +379,7 @@ TEST(WalletTests, SetSaplingNoteAddrsInCWalletTx) {
ASSERT_TRUE(nf); ASSERT_TRUE(nf);
uint256 nullifier = nf.get(); uint256 nullifier = nf.get();
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingSpend(expsk, note, anchor, witness);
builder.AddSaplingOutput(fvk.ovk, pk, 50000, {}); builder.AddSaplingOutput(fvk.ovk, pk, 50000, {});
builder.SetFee(0); builder.SetFee(0);
@ -506,7 +506,7 @@ TEST(WalletTests, FindMySaplingNotes) {
auto testNote = GetTestSaplingNote(pa, 50000); auto testNote = GetTestSaplingNote(pa, 50000);
// Generate transaction // Generate transaction
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {});
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -638,7 +638,7 @@ TEST(WalletTests, GetConflictedSaplingNotes) {
auto witness = saplingTree.witness(); auto witness = saplingTree.witness();
// Generate tx to create output note B // Generate tx to create output note B
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingSpend(expsk, note, anchor, witness);
builder.AddSaplingOutput(fvk.ovk, pk, 35000, {}); builder.AddSaplingOutput(fvk.ovk, pk, 35000, {});
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -692,13 +692,13 @@ TEST(WalletTests, GetConflictedSaplingNotes) {
anchor = saplingTree.root(); anchor = saplingTree.root();
// Create transaction to spend note B // Create transaction to spend note B
auto builder2 = TransactionBuilder(consensusParams, 2); auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta);
builder2.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder2.AddSaplingSpend(expsk, note2, anchor, spend_note_witness);
builder2.AddSaplingOutput(fvk.ovk, pk, 20000, {}); builder2.AddSaplingOutput(fvk.ovk, pk, 20000, {});
auto tx2 = builder2.Build().GetTxOrThrow(); auto tx2 = builder2.Build().GetTxOrThrow();
// Create conflicting transaction which also spends note B // Create conflicting transaction which also spends note B
auto builder3 = TransactionBuilder(consensusParams, 2); auto builder3 = TransactionBuilder(consensusParams, 2, expiryDelta);
builder3.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder3.AddSaplingSpend(expsk, note2, anchor, spend_note_witness);
builder3.AddSaplingOutput(fvk.ovk, pk, 19999, {}); builder3.AddSaplingOutput(fvk.ovk, pk, 19999, {});
auto tx3 = builder3.Build().GetTxOrThrow(); auto tx3 = builder3.Build().GetTxOrThrow();
@ -785,7 +785,7 @@ TEST(WalletTests, SaplingNullifierIsSpent) {
auto testNote = GetTestSaplingNote(pa, 50000); auto testNote = GetTestSaplingNote(pa, 50000);
// Generate transaction // Generate transaction
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {});
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -868,7 +868,7 @@ TEST(WalletTests, NavigateFromSaplingNullifierToNote) {
auto testNote = GetTestSaplingNote(pa, 50000); auto testNote = GetTestSaplingNote(pa, 50000);
// Generate transaction // Generate transaction
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {});
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -996,7 +996,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) {
auto witness = saplingTree.witness(); auto witness = saplingTree.witness();
// Generate transaction, which sends funds to note B // Generate transaction, which sends funds to note B
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingSpend(expsk, note, anchor, witness);
builder.AddSaplingOutput(fvk.ovk, pk, 25000, {}); builder.AddSaplingOutput(fvk.ovk, pk, 25000, {});
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -1066,7 +1066,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) {
anchor = saplingTree.root(); anchor = saplingTree.root();
// Create transaction to spend note B // Create transaction to spend note B
auto builder2 = TransactionBuilder(consensusParams, 2); auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta);
builder2.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder2.AddSaplingSpend(expsk, note2, anchor, spend_note_witness);
builder2.AddSaplingOutput(fvk.ovk, pk, 12500, {}); builder2.AddSaplingOutput(fvk.ovk, pk, 12500, {});
auto tx2 = builder2.Build().GetTxOrThrow(); auto tx2 = builder2.Build().GetTxOrThrow();
@ -1771,7 +1771,7 @@ TEST(WalletTests, UpdatedSaplingNoteData) {
auto testNote = GetTestSaplingNote(pa, 50000); auto testNote = GetTestSaplingNote(pa, 50000);
// Generate transaction // Generate transaction
auto builder = TransactionBuilder(consensusParams, 1); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta);
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
builder.AddSaplingOutput(fvk.ovk, pa2, 25000, {}); builder.AddSaplingOutput(fvk.ovk, pa2, 25000, {});
auto tx = builder.Build().GetTxOrThrow(); auto tx = builder.Build().GetTxOrThrow();
@ -1912,7 +1912,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) {
// Generate shielding tx from transparent to Sapling // Generate shielding tx from transparent to Sapling
// 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee // 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee
auto builder = TransactionBuilder(consensusParams, 1, &keystore); auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore);
builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000);
builder.AddSaplingOutput(fvk.ovk, pk, 40000, {}); builder.AddSaplingOutput(fvk.ovk, pk, 40000, {});
auto tx1 = builder.Build().GetTxOrThrow(); auto tx1 = builder.Build().GetTxOrThrow();
@ -1967,7 +1967,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) {
// Create a Sapling-only transaction // Create a Sapling-only transaction
// 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change // 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change
auto builder2 = TransactionBuilder(consensusParams, 2); auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta);
builder2.AddSaplingSpend(expsk, note, anchor, witness); builder2.AddSaplingSpend(expsk, note, anchor, witness);
builder2.AddSaplingOutput(fvk.ovk, pk, 25000, {}); builder2.AddSaplingOutput(fvk.ovk, pk, 25000, {});
auto tx2 = builder2.Build().GetTxOrThrow(); auto tx2 = builder2.Build().GetTxOrThrow();

View File

@ -3888,7 +3888,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
// Builder (used if Sapling addresses are involved) // Builder (used if Sapling addresses are involved)
boost::optional<TransactionBuilder> builder; boost::optional<TransactionBuilder> builder;
if (noSproutAddrs) { if (noSproutAddrs) {
builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain);
} }
// Contextual transaction we will build on // Contextual transaction we will build on
@ -4229,7 +4229,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
// Builder (used if Sapling addresses are involved) // Builder (used if Sapling addresses are involved)
TransactionBuilder builder = TransactionBuilder( TransactionBuilder builder = TransactionBuilder(
Params().GetConsensus(), nextBlockHeight, pwalletMain); Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain);
// Contextual transaction we will build on // Contextual transaction we will build on
// (used if no Sapling addresses are involved) // (used if no Sapling addresses are involved)
@ -4646,7 +4646,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
// Builder (used if Sapling addresses are involved) // Builder (used if Sapling addresses are involved)
boost::optional<TransactionBuilder> builder; boost::optional<TransactionBuilder> builder;
if (isToSaplingZaddr || saplingNoteInputs.size() > 0) { if (isToSaplingZaddr || saplingNoteInputs.size() > 0) {
builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain);
} }
// Create operation and add to global queue // Create operation and add to global queue
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue(); std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();