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) {
@ -182,7 +184,7 @@ libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigration
libzcash::SaplingExtendedSpendingKey xsk = m_32h_cth.Derive(0 | ZIP32_HARDENED_KEY_LIMIT); libzcash::SaplingExtendedSpendingKey xsk = m_32h_cth.Derive(0 | ZIP32_HARDENED_KEY_LIMIT);
libzcash::SaplingPaymentAddress toAddress = xsk.DefaultAddress(); libzcash::SaplingPaymentAddress toAddress = xsk.DefaultAddress();
// Refactor: this is similar logic as in the visitor HaveSpendingKeyForPaymentAddress and is used elsewhere // Refactor: this is similar logic as in the visitor HaveSpendingKeyForPaymentAddress and is used elsewhere
libzcash::SaplingIncomingViewingKey ivk; libzcash::SaplingIncomingViewingKey ivk;
libzcash::SaplingFullViewingKey fvk; libzcash::SaplingFullViewingKey fvk;

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
@ -3921,7 +3921,7 @@ UniValue z_setmigration(const UniValue& params, bool fHelp) {
"Sprout balance, this process may take several weeks. The migration works by sending, up to 5, as many\n" "Sprout balance, this process may take several weeks. The migration works by sending, up to 5, as many\n"
"transactions as possible whenever the blockchain reaches a height equal to 499 modulo 500. The transaction\n" "transactions as possible whenever the blockchain reaches a height equal to 499 modulo 500. The transaction\n"
"amounts are picked according to the random distribution specified in ZIP 308. The migration will end once\n" "amounts are picked according to the random distribution specified in ZIP 308. The migration will end once\n"
"the wallets Sprout balance is below" + strprintf("%s %s", FormatMoney(CENT), CURRENCY_UNIT) + ".\n" "the wallets Sprout balance is below " + strprintf("%s %s", FormatMoney(CENT), CURRENCY_UNIT) + ".\n"
"\nArguments:\n" "\nArguments:\n"
"1. enabled (boolean, required) 'true' or 'false' to enable or disable respectively.\n" "1. enabled (boolean, required) 'true' or 'false' to enable or disable respectively.\n"
); );
@ -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();