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:
commit
664b7d32a1
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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") };
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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, {});
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 wallet’s Sprout balance is below" + strprintf("%s %s", FormatMoney(CENT), CURRENCY_UNIT) + ".\n"
|
"the wallet’s 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();
|
||||||
|
|
Loading…
Reference in New Issue