2018-07-17 09:36:38 -07:00
|
|
|
#include "chainparams.h"
|
|
|
|
#include "consensus/params.h"
|
|
|
|
#include "consensus/validation.h"
|
2018-07-30 03:03:29 -07:00
|
|
|
#include "key_io.h"
|
2018-07-17 09:36:38 -07:00
|
|
|
#include "main.h"
|
2018-07-30 03:03:29 -07:00
|
|
|
#include "pubkey.h"
|
2018-10-31 09:15:37 -07:00
|
|
|
#include "rpc/protocol.h"
|
2018-07-17 09:36:38 -07:00
|
|
|
#include "transaction_builder.h"
|
2018-11-06 14:53:04 -08:00
|
|
|
#include "utiltest.h"
|
2018-07-17 09:36:38 -07:00
|
|
|
#include "zcash/Address.hpp"
|
|
|
|
|
|
|
|
#include <gmock/gmock.h>
|
2018-07-27 00:49:43 -07:00
|
|
|
#include <gtest/gtest.h>
|
2018-07-17 09:36:38 -07:00
|
|
|
|
2018-07-27 00:49:43 -07:00
|
|
|
TEST(TransactionBuilder, Invoke)
|
|
|
|
{
|
2019-01-29 20:18:10 -08:00
|
|
|
auto consensusParams = RegtestActivateSapling();
|
2018-07-17 09:36:38 -07:00
|
|
|
|
2018-07-30 03:03:29 -07:00
|
|
|
CBasicKeyStore keystore;
|
2019-01-29 20:18:10 -08:00
|
|
|
CKey tsk = AddTestCKeyToKeyStore(keystore);
|
2018-07-30 03:03:29 -07:00
|
|
|
auto scriptPubKey = GetScriptForDestination(tsk.GetPubKey().GetID());
|
|
|
|
|
2018-07-17 09:36:38 -07:00
|
|
|
auto sk_from = libzcash::SaplingSpendingKey::random();
|
|
|
|
auto fvk_from = sk_from.full_viewing_key();
|
|
|
|
|
|
|
|
auto sk = libzcash::SaplingSpendingKey::random();
|
2018-07-30 06:26:29 -07:00
|
|
|
auto expsk = sk.expanded_spending_key();
|
2018-07-17 09:36:38 -07:00
|
|
|
auto fvk = sk.full_viewing_key();
|
|
|
|
auto ivk = fvk.in_viewing_key();
|
|
|
|
libzcash::diversifier_t d = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
|
auto pk = *ivk.address(d);
|
|
|
|
|
|
|
|
// Create a shielding transaction from transparent to Sapling
|
2018-07-30 03:03:29 -07:00
|
|
|
// 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee
|
|
|
|
auto builder1 = TransactionBuilder(consensusParams, 1, &keystore);
|
|
|
|
builder1.AddTransparentInput(COutPoint(), scriptPubKey, 50000);
|
2018-09-18 15:22:50 -07:00
|
|
|
builder1.AddSaplingOutput(fvk_from.ovk, pk, 40000, {});
|
2018-10-30 13:12:40 -07:00
|
|
|
auto tx1 = builder1.Build().GetTxOrThrow();
|
2018-07-17 09:36:38 -07:00
|
|
|
|
2018-07-30 03:03:29 -07:00
|
|
|
EXPECT_EQ(tx1.vin.size(), 1);
|
2018-07-17 09:36:38 -07:00
|
|
|
EXPECT_EQ(tx1.vout.size(), 0);
|
|
|
|
EXPECT_EQ(tx1.vjoinsplit.size(), 0);
|
|
|
|
EXPECT_EQ(tx1.vShieldedSpend.size(), 0);
|
|
|
|
EXPECT_EQ(tx1.vShieldedOutput.size(), 1);
|
2018-07-30 03:03:29 -07:00
|
|
|
EXPECT_EQ(tx1.valueBalance, -40000);
|
2018-07-17 09:36:38 -07:00
|
|
|
|
|
|
|
CValidationState state;
|
|
|
|
EXPECT_TRUE(ContextualCheckTransaction(tx1, state, 2, 0));
|
|
|
|
EXPECT_EQ(state.GetRejectReason(), "");
|
|
|
|
|
|
|
|
// Prepare to spend the note that was just created
|
|
|
|
auto maybe_pt = libzcash::SaplingNotePlaintext::decrypt(
|
2018-08-01 14:02:32 -07:00
|
|
|
tx1.vShieldedOutput[0].encCiphertext, ivk, tx1.vShieldedOutput[0].ephemeralKey, tx1.vShieldedOutput[0].cm);
|
2018-07-17 09:36:38 -07:00
|
|
|
ASSERT_EQ(static_cast<bool>(maybe_pt), true);
|
|
|
|
auto maybe_note = maybe_pt.get().note(ivk);
|
|
|
|
ASSERT_EQ(static_cast<bool>(maybe_note), true);
|
|
|
|
auto note = maybe_note.get();
|
2018-08-01 09:31:09 -07:00
|
|
|
SaplingMerkleTree tree;
|
2018-07-17 09:36:38 -07:00
|
|
|
tree.append(tx1.vShieldedOutput[0].cm);
|
|
|
|
auto anchor = tree.root();
|
|
|
|
auto witness = tree.witness();
|
|
|
|
|
|
|
|
// Create a Sapling-only transaction
|
2018-07-30 04:36:42 -07:00
|
|
|
// 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change
|
2018-07-17 09:36:38 -07:00
|
|
|
auto builder2 = TransactionBuilder(consensusParams, 2);
|
2018-10-31 09:15:37 -07:00
|
|
|
builder2.AddSaplingSpend(expsk, note, anchor, witness);
|
2018-07-27 00:46:38 -07:00
|
|
|
// Check that trying to add a different anchor fails
|
2018-10-31 09:15:37 -07:00
|
|
|
// TODO: the following check can be split out in to another test
|
|
|
|
ASSERT_THROW(builder2.AddSaplingSpend(expsk, note, uint256(), witness), UniValue);
|
2018-07-27 00:46:38 -07:00
|
|
|
|
2018-09-18 15:22:50 -07:00
|
|
|
builder2.AddSaplingOutput(fvk.ovk, pk, 25000, {});
|
2018-10-30 13:12:40 -07:00
|
|
|
auto tx2 = builder2.Build().GetTxOrThrow();
|
2018-07-17 09:36:38 -07:00
|
|
|
|
|
|
|
EXPECT_EQ(tx2.vin.size(), 0);
|
|
|
|
EXPECT_EQ(tx2.vout.size(), 0);
|
|
|
|
EXPECT_EQ(tx2.vjoinsplit.size(), 0);
|
|
|
|
EXPECT_EQ(tx2.vShieldedSpend.size(), 1);
|
2018-07-30 04:36:42 -07:00
|
|
|
EXPECT_EQ(tx2.vShieldedOutput.size(), 2);
|
|
|
|
EXPECT_EQ(tx2.valueBalance, 10000);
|
2018-07-17 09:36:38 -07:00
|
|
|
|
|
|
|
EXPECT_TRUE(ContextualCheckTransaction(tx2, state, 3, 0));
|
|
|
|
EXPECT_EQ(state.GetRejectReason(), "");
|
|
|
|
|
|
|
|
// Revert to default
|
2019-01-29 20:18:10 -08:00
|
|
|
RegtestDeactivateSapling();
|
2018-07-17 09:36:38 -07:00
|
|
|
}
|
2018-07-30 03:03:29 -07:00
|
|
|
|
|
|
|
TEST(TransactionBuilder, ThrowsOnTransparentInputWithoutKeyStore)
|
|
|
|
{
|
2018-11-28 21:44:52 -08:00
|
|
|
SelectParams(CBaseChainParams::REGTEST);
|
2018-07-30 03:03:29 -07:00
|
|
|
auto consensusParams = Params().GetConsensus();
|
|
|
|
|
|
|
|
auto builder = TransactionBuilder(consensusParams, 1);
|
|
|
|
ASSERT_THROW(builder.AddTransparentInput(COutPoint(), CScript(), 1), std::runtime_error);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TransactionBuilder, RejectsInvalidTransparentOutput)
|
|
|
|
{
|
2018-11-28 21:44:52 -08:00
|
|
|
SelectParams(CBaseChainParams::REGTEST);
|
2018-07-30 03:03:29 -07:00
|
|
|
auto consensusParams = Params().GetConsensus();
|
|
|
|
|
|
|
|
// Default CTxDestination type is an invalid address
|
|
|
|
CTxDestination taddr;
|
|
|
|
auto builder = TransactionBuilder(consensusParams, 1);
|
2018-10-31 09:15:37 -07:00
|
|
|
ASSERT_THROW(builder.AddTransparentOutput(taddr, 50), UniValue);
|
2018-07-30 03:03:29 -07:00
|
|
|
}
|
|
|
|
|
2018-07-30 04:36:42 -07:00
|
|
|
TEST(TransactionBuilder, RejectsInvalidTransparentChangeAddress)
|
|
|
|
{
|
2018-11-28 21:44:52 -08:00
|
|
|
SelectParams(CBaseChainParams::REGTEST);
|
2018-07-30 04:36:42 -07:00
|
|
|
auto consensusParams = Params().GetConsensus();
|
|
|
|
|
|
|
|
// Default CTxDestination type is an invalid address
|
|
|
|
CTxDestination taddr;
|
|
|
|
auto builder = TransactionBuilder(consensusParams, 1);
|
2018-10-31 09:15:37 -07:00
|
|
|
ASSERT_THROW(builder.SendChangeTo(taddr), UniValue);
|
2018-07-30 04:36:42 -07:00
|
|
|
}
|
|
|
|
|
2018-07-30 03:03:29 -07:00
|
|
|
TEST(TransactionBuilder, FailsWithNegativeChange)
|
|
|
|
{
|
2019-01-29 20:18:10 -08:00
|
|
|
auto consensusParams = RegtestActivateSapling();
|
2018-07-30 03:03:29 -07:00
|
|
|
|
|
|
|
// Generate dummy Sapling address
|
|
|
|
auto sk = libzcash::SaplingSpendingKey::random();
|
2018-07-30 06:26:29 -07:00
|
|
|
auto expsk = sk.expanded_spending_key();
|
2018-07-30 03:03:29 -07:00
|
|
|
auto fvk = sk.full_viewing_key();
|
2018-11-06 15:57:10 -08:00
|
|
|
auto pa = sk.default_address();
|
2018-07-30 03:03:29 -07:00
|
|
|
|
|
|
|
// Set up dummy transparent address
|
|
|
|
CBasicKeyStore keystore;
|
2019-01-29 20:18:10 -08:00
|
|
|
CKey tsk = AddTestCKeyToKeyStore(keystore);
|
2018-07-30 03:03:29 -07:00
|
|
|
auto tkeyid = tsk.GetPubKey().GetID();
|
|
|
|
auto scriptPubKey = GetScriptForDestination(tkeyid);
|
|
|
|
CTxDestination taddr = tkeyid;
|
|
|
|
|
2018-11-06 15:57:10 -08:00
|
|
|
auto testNote = GetTestSaplingNote(pa, 59999);
|
2018-07-30 03:03:29 -07:00
|
|
|
|
|
|
|
// Fail if there is only a Sapling output
|
|
|
|
// 0.0005 z-ZEC out, 0.0001 t-ZEC fee
|
|
|
|
auto builder = TransactionBuilder(consensusParams, 1);
|
2018-11-06 15:57:10 -08:00
|
|
|
builder.AddSaplingOutput(fvk.ovk, pa, 50000, {});
|
2018-10-30 13:12:40 -07:00
|
|
|
EXPECT_EQ("Change cannot be negative", builder.Build().GetError());
|
2018-07-30 03:03:29 -07:00
|
|
|
|
|
|
|
// Fail if there is only a transparent output
|
|
|
|
// 0.0005 t-ZEC out, 0.0001 t-ZEC fee
|
|
|
|
builder = TransactionBuilder(consensusParams, 1, &keystore);
|
2018-10-31 09:15:37 -07:00
|
|
|
builder.AddTransparentOutput(taddr, 50000);
|
2018-10-30 13:12:40 -07:00
|
|
|
EXPECT_EQ("Change cannot be negative", builder.Build().GetError());
|
2018-07-30 03:03:29 -07:00
|
|
|
|
|
|
|
// Fails if there is insufficient input
|
|
|
|
// 0.0005 t-ZEC out, 0.0001 t-ZEC fee, 0.00059999 z-ZEC in
|
2018-11-06 15:57:10 -08:00
|
|
|
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
|
2018-10-30 13:12:40 -07:00
|
|
|
EXPECT_EQ("Change cannot be negative", builder.Build().GetError());
|
2018-07-30 03:03:29 -07:00
|
|
|
|
|
|
|
// Succeeds if there is sufficient input
|
|
|
|
builder.AddTransparentInput(COutPoint(), scriptPubKey, 1);
|
2018-10-30 13:12:40 -07:00
|
|
|
EXPECT_TRUE(builder.Build().IsTx());
|
2018-07-30 03:03:29 -07:00
|
|
|
|
|
|
|
// Revert to default
|
2019-01-29 20:18:10 -08:00
|
|
|
RegtestDeactivateSapling();
|
2018-07-30 03:03:29 -07:00
|
|
|
}
|
2018-07-30 04:36:42 -07:00
|
|
|
|
|
|
|
TEST(TransactionBuilder, ChangeOutput)
|
|
|
|
{
|
2019-01-29 20:18:10 -08:00
|
|
|
auto consensusParams = RegtestActivateSapling();
|
2018-07-30 04:36:42 -07:00
|
|
|
|
|
|
|
// Generate dummy Sapling address
|
|
|
|
auto sk = libzcash::SaplingSpendingKey::random();
|
2018-07-30 06:26:29 -07:00
|
|
|
auto expsk = sk.expanded_spending_key();
|
2018-11-06 15:57:10 -08:00
|
|
|
auto pa = sk.default_address();
|
2018-07-30 04:36:42 -07:00
|
|
|
|
2018-11-06 15:57:10 -08:00
|
|
|
auto testNote = GetTestSaplingNote(pa, 25000);
|
2018-07-30 04:36:42 -07:00
|
|
|
|
|
|
|
// Generate change Sapling address
|
|
|
|
auto sk2 = libzcash::SaplingSpendingKey::random();
|
|
|
|
auto fvkOut = sk2.full_viewing_key();
|
|
|
|
auto zChangeAddr = sk2.default_address();
|
|
|
|
|
|
|
|
// Set up dummy transparent address
|
|
|
|
CBasicKeyStore keystore;
|
2019-01-29 20:18:10 -08:00
|
|
|
CKey tsk = AddTestCKeyToKeyStore(keystore);
|
2018-07-30 04:36:42 -07:00
|
|
|
auto tkeyid = tsk.GetPubKey().GetID();
|
|
|
|
auto scriptPubKey = GetScriptForDestination(tkeyid);
|
|
|
|
CTxDestination taddr = tkeyid;
|
|
|
|
|
|
|
|
// No change address and no Sapling spends
|
|
|
|
{
|
|
|
|
auto builder = TransactionBuilder(consensusParams, 1, &keystore);
|
|
|
|
builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000);
|
2018-10-30 13:12:40 -07:00
|
|
|
EXPECT_EQ("Could not determine change address", builder.Build().GetError());
|
2018-07-30 04:36:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Change to the same address as the first Sapling spend
|
|
|
|
{
|
|
|
|
auto builder = TransactionBuilder(consensusParams, 1, &keystore);
|
|
|
|
builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000);
|
2018-11-06 15:57:10 -08:00
|
|
|
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
|
2018-10-30 13:12:40 -07:00
|
|
|
auto tx = builder.Build().GetTxOrThrow();
|
2018-07-30 04:36:42 -07:00
|
|
|
|
|
|
|
EXPECT_EQ(tx.vin.size(), 1);
|
|
|
|
EXPECT_EQ(tx.vout.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vjoinsplit.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vShieldedSpend.size(), 1);
|
|
|
|
EXPECT_EQ(tx.vShieldedOutput.size(), 1);
|
|
|
|
EXPECT_EQ(tx.valueBalance, -15000);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Change to a Sapling address
|
|
|
|
{
|
|
|
|
auto builder = TransactionBuilder(consensusParams, 1, &keystore);
|
|
|
|
builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000);
|
2018-09-18 15:22:50 -07:00
|
|
|
builder.SendChangeTo(zChangeAddr, fvkOut.ovk);
|
2018-10-30 13:12:40 -07:00
|
|
|
auto tx = builder.Build().GetTxOrThrow();
|
2018-07-30 04:36:42 -07:00
|
|
|
|
|
|
|
EXPECT_EQ(tx.vin.size(), 1);
|
|
|
|
EXPECT_EQ(tx.vout.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vjoinsplit.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vShieldedSpend.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vShieldedOutput.size(), 1);
|
|
|
|
EXPECT_EQ(tx.valueBalance, -15000);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Change to a transparent address
|
|
|
|
{
|
|
|
|
auto builder = TransactionBuilder(consensusParams, 1, &keystore);
|
|
|
|
builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000);
|
2018-10-31 09:15:37 -07:00
|
|
|
builder.SendChangeTo(taddr);
|
2018-10-30 13:12:40 -07:00
|
|
|
auto tx = builder.Build().GetTxOrThrow();
|
2018-07-30 04:36:42 -07:00
|
|
|
|
|
|
|
EXPECT_EQ(tx.vin.size(), 1);
|
|
|
|
EXPECT_EQ(tx.vout.size(), 1);
|
|
|
|
EXPECT_EQ(tx.vjoinsplit.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vShieldedSpend.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vShieldedOutput.size(), 0);
|
|
|
|
EXPECT_EQ(tx.valueBalance, 0);
|
|
|
|
EXPECT_EQ(tx.vout[0].nValue, 15000);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Revert to default
|
2019-01-29 20:18:10 -08:00
|
|
|
RegtestDeactivateSapling();
|
2018-07-30 04:36:42 -07:00
|
|
|
}
|
2018-07-30 04:52:48 -07:00
|
|
|
|
|
|
|
TEST(TransactionBuilder, SetFee)
|
|
|
|
{
|
2019-01-29 20:18:10 -08:00
|
|
|
auto consensusParams = RegtestActivateSapling();
|
2018-07-30 04:52:48 -07:00
|
|
|
|
|
|
|
// Generate dummy Sapling address
|
|
|
|
auto sk = libzcash::SaplingSpendingKey::random();
|
2018-07-30 06:26:29 -07:00
|
|
|
auto expsk = sk.expanded_spending_key();
|
2018-07-30 04:52:48 -07:00
|
|
|
auto fvk = sk.full_viewing_key();
|
2018-11-06 15:57:10 -08:00
|
|
|
auto pa = sk.default_address();
|
2018-07-30 04:52:48 -07:00
|
|
|
|
2018-11-06 15:57:10 -08:00
|
|
|
auto testNote = GetTestSaplingNote(pa, 50000);
|
2018-07-30 04:52:48 -07:00
|
|
|
|
|
|
|
// Default fee
|
|
|
|
{
|
|
|
|
auto builder = TransactionBuilder(consensusParams, 1);
|
2018-11-06 15:57:10 -08:00
|
|
|
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
|
|
|
|
builder.AddSaplingOutput(fvk.ovk, pa, 25000, {});
|
2018-10-30 13:12:40 -07:00
|
|
|
auto tx = builder.Build().GetTxOrThrow();
|
2018-07-30 04:52:48 -07:00
|
|
|
|
|
|
|
EXPECT_EQ(tx.vin.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vout.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vjoinsplit.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vShieldedSpend.size(), 1);
|
|
|
|
EXPECT_EQ(tx.vShieldedOutput.size(), 2);
|
|
|
|
EXPECT_EQ(tx.valueBalance, 10000);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Configured fee
|
|
|
|
{
|
|
|
|
auto builder = TransactionBuilder(consensusParams, 1);
|
2018-11-06 15:57:10 -08:00
|
|
|
builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness());
|
|
|
|
builder.AddSaplingOutput(fvk.ovk, pa, 25000, {});
|
2018-07-30 04:52:48 -07:00
|
|
|
builder.SetFee(20000);
|
2018-10-30 13:12:40 -07:00
|
|
|
auto tx = builder.Build().GetTxOrThrow();
|
2018-07-30 04:52:48 -07:00
|
|
|
|
|
|
|
EXPECT_EQ(tx.vin.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vout.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vjoinsplit.size(), 0);
|
|
|
|
EXPECT_EQ(tx.vShieldedSpend.size(), 1);
|
|
|
|
EXPECT_EQ(tx.vShieldedOutput.size(), 2);
|
|
|
|
EXPECT_EQ(tx.valueBalance, 20000);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Revert to default
|
2019-01-29 20:18:10 -08:00
|
|
|
RegtestDeactivateSapling();
|
2018-07-30 04:52:48 -07:00
|
|
|
}
|
2018-11-07 20:38:14 -08:00
|
|
|
|
|
|
|
TEST(TransactionBuilder, CheckSaplingTxVersion)
|
|
|
|
{
|
|
|
|
SelectParams(CBaseChainParams::REGTEST);
|
|
|
|
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
|
|
|
|
auto consensusParams = Params().GetConsensus();
|
|
|
|
|
|
|
|
auto sk = libzcash::SaplingSpendingKey::random();
|
|
|
|
auto expsk = sk.expanded_spending_key();
|
|
|
|
auto pk = sk.default_address();
|
|
|
|
|
|
|
|
// Cannot add Sapling outputs to a non-Sapling transaction
|
|
|
|
auto builder = TransactionBuilder(consensusParams, 1);
|
|
|
|
try {
|
|
|
|
builder.AddSaplingOutput(uint256(), pk, 12345, {});
|
|
|
|
} catch (std::runtime_error const & err) {
|
|
|
|
EXPECT_EQ(err.what(), std::string("TransactionBuilder cannot add Sapling output to pre-Sapling transaction"));
|
|
|
|
} catch(...) {
|
|
|
|
FAIL() << "Expected std::runtime_error";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cannot add Sapling spends to a non-Sapling transaction
|
|
|
|
libzcash::SaplingNote note(pk, 50000);
|
|
|
|
SaplingMerkleTree tree;
|
|
|
|
try {
|
|
|
|
builder.AddSaplingSpend(expsk, note, uint256(), tree.witness());
|
|
|
|
} catch (std::runtime_error const & err) {
|
|
|
|
EXPECT_EQ(err.what(), std::string("TransactionBuilder cannot add Sapling spend to pre-Sapling transaction"));
|
|
|
|
} catch(...) {
|
|
|
|
FAIL() << "Expected std::runtime_error";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Revert to default
|
|
|
|
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
|
|
|
|
}
|