aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chow <achow101-github@achow101.com>2021-06-04 20:31:04 -0400
committerAndrew Chow <achow101-github@achow101.com>2021-06-10 15:45:47 -0400
commitfbf485c9b2bf1d056bfea77345a15cf56a9cd786 (patch)
tree3b4e510a4e0bfa9871eec7548a2505c70dc7065c
parent346e52afd6d5e317c96fc506bb54cde13e87c8b2 (diff)
Allow tr() import only when Taproot is active
To avoid issues around fund loss, only allow descriptor wallets to import tr() descriptors after taproot has activated.
-rw-r--r--src/interfaces/chain.h3
-rw-r--r--src/node/interfaces.cpp6
-rw-r--r--src/wallet/rpcdump.cpp12
-rwxr-xr-xtest/functional/wallet_taproot.py26
4 files changed, 45 insertions, 2 deletions
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index 3395741b1b..7cac435e96 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -277,6 +277,9 @@ public:
//! to be prepared to handle this by ignoring notifications about unknown
//! removed transactions and already added new transactions.
virtual void requestMempoolTransactions(Notifications& notifications) = 0;
+
+ //! Check if Taproot has activated
+ virtual bool isTaprootActive() const = 0;
};
//! Interface to let node manage chain clients (wallets, or maybe tools for
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index 8befbf5e30..e88594f7d6 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -709,6 +709,12 @@ public:
notifications.transactionAddedToMempool(entry.GetSharedTx(), 0 /* mempool_sequence */);
}
}
+ bool isTaprootActive() const override
+ {
+ LOCK(::cs_main);
+ const CBlockIndex* tip = Assert(m_node.chainman)->ActiveChain().Tip();
+ return VersionBitsState(tip, Params().GetConsensus(), Consensus::DEPLOYMENT_TAPROOT, versionbitscache) == ThresholdState::ACTIVE;
+ }
NodeContext& m_node;
};
} // namespace
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 726b13beac..4e9ba83ead 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -1530,6 +1530,18 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
}
}
+ // Taproot descriptors cannot be imported if Taproot is not yet active.
+ // Check if this is a Taproot descriptor
+ CTxDestination dest;
+ ExtractDestination(scripts[0], dest);
+ if (std::holds_alternative<WitnessV1Taproot>(dest)) {
+ // Check if Taproot is active
+ if (!wallet.chain().isTaprootActive()) {
+ // Taproot is not active, raise an error
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import tr() descriptor when Taproot is not active");
+ }
+ }
+
// If private keys are enabled, check some things.
if (!wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
if (keys.keys.empty()) {
diff --git a/test/functional/wallet_taproot.py b/test/functional/wallet_taproot.py
index 65ca7bdef7..5803c0cf54 100755
--- a/test/functional/wallet_taproot.py
+++ b/test/functional/wallet_taproot.py
@@ -172,9 +172,9 @@ class WalletTaprootTest(BitcoinTestFramework):
"""Test generation and spending of P2TR address outputs."""
def set_test_params(self):
- self.num_nodes = 2
+ self.num_nodes = 3
self.setup_clean_chain = True
- self.extra_args = [['-keypool=100'], ['-keypool=100']]
+ self.extra_args = [['-keypool=100'], ['-keypool=100'], ["-vbparams=taproot:1:1"]]
self.supports_cli = False
def skip_test_if_missing_module(self):
@@ -230,12 +230,34 @@ class WalletTaprootTest(BitcoinTestFramework):
addr_r = self.make_addr(treefn, keys, i)
assert_equal(addr_g, addr_r)
+ # tr descriptors cannot be imported when Taproot is not active
+ result = self.privs_tr_enabled.importdescriptors([{"desc": desc, "timestamp": "now"}])
+ assert(result[0]["success"])
+ result = self.privs_tr_disabled.importdescriptors([{"desc": desc, "timestamp": "now"}])
+ assert(not result[0]["success"])
+ assert_equal(result[0]["error"]["code"], -4)
+ assert_equal(result[0]["error"]["message"], "Cannot import tr() descriptor when Taproot is not active")
+ result = self.pubs_tr_enabled.importdescriptors([{"desc": desc_pub, "timestamp": "now"}])
+ assert(result[0]["success"])
+ result = self.pubs_tr_disabled.importdescriptors([{"desc": desc_pub, "timestamp": "now"}])
+ assert(not result[0]["success"])
+ assert_equal(result[0]["error"]["code"], -4)
+ assert_equal(result[0]["error"]["message"], "Cannot import tr() descriptor when Taproot is not active")
+
def do_test(self, comment, pattern, privmap, treefn, nkeys):
keys = self.rand_keys(nkeys)
self.do_test_addr(comment, pattern, privmap, treefn, keys)
def run_test(self):
self.log.info("Creating wallets...")
+ self.nodes[0].createwallet(wallet_name="privs_tr_enabled", descriptors=True, blank=True)
+ self.privs_tr_enabled = self.nodes[0].get_wallet_rpc("privs_tr_enabled")
+ self.nodes[2].createwallet(wallet_name="privs_tr_disabled", descriptors=True, blank=True)
+ self.privs_tr_disabled=self.nodes[2].get_wallet_rpc("privs_tr_disabled")
+ self.nodes[0].createwallet(wallet_name="pubs_tr_enabled", descriptors=True, blank=True, disable_private_keys=True)
+ self.pubs_tr_enabled = self.nodes[0].get_wallet_rpc("pubs_tr_enabled")
+ self.nodes[2].createwallet(wallet_name="pubs_tr_disabled", descriptors=True, blank=True, disable_private_keys=True)
+ self.pubs_tr_disabled=self.nodes[2].get_wallet_rpc("pubs_tr_disabled")
self.nodes[0].createwallet(wallet_name="addr_gen", descriptors=True, disable_private_keys=True, blank=True)
self.addr_gen = self.nodes[0].get_wallet_rpc("addr_gen")