diff --git a/src/Makefile.am b/src/Makefile.am index 803074c6636..96c2a3be3d3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -939,6 +939,7 @@ bitcoin_chainstate_LDADD = \ $(LIBBITCOIN_CRYPTO) \ $(LIBUNIVALUE) \ $(LIBSECP256K1) \ + $(LIBELEMENTSSIMPLICITY) \ $(LIBLEVELDB) \ $(LIBLEVELDB_SSE42) \ $(LIBMEMENV) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 10f122424b0..28533047957 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -627,9 +627,11 @@ class CRegTestParams : public CChainParams { // Simplicity consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].bit = 24; - consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE; + consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nPeriod = 128; // test ability to change from default + consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nThreshold = 128; consensus.nMinimumChainWork = uint256{}; consensus.defaultAssumeValid = uint256{}; @@ -1034,6 +1036,10 @@ class CLiquidTestNetParams : public CCustomParams { base58Prefixes[BLINDED_ADDRESS] = std::vector(1, 23); base58Prefixes[SECRET_KEY] = std::vector(1, base58Prefixes[SECRET_KEY][0]); + // turn on Simplicity unconditionally on Liquid Testnet + consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE; + consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; + // disable automatic dynafed consensus.vDeployments[Consensus::DEPLOYMENT_DYNA_FED].nStartTime = 0; @@ -1286,6 +1292,8 @@ class CLiquidV1Params : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nPeriod = 10080; // one week... + consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nThreshold = 10080; // ...of 100% signalling // Activated from block 1,000,000. consensus.vDeployments[Consensus::DEPLOYMENT_DYNA_FED].bit = 25; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 03b6e449398..48bcfee1f8a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1837,6 +1837,7 @@ UniValue DeploymentInfo(const CBlockIndex* blockindex, const Consensus::Params& SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_DYNA_FED); SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_TESTDUMMY); SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_TAPROOT); + SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_SIMPLICITY); return softforks; } } // anon namespace diff --git a/test/functional/feature_elements_simplicity_activation.py b/test/functional/feature_elements_simplicity_activation.py new file mode 100755 index 00000000000..9ec041fcdca --- /dev/null +++ b/test/functional/feature_elements_simplicity_activation.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +# Copyright (c) 2015-2020 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test Simplicity soft fork activation for Elements + +This is essentially the same as the Taproot activation test. + +Like that one, it doesn't try to test the actual activation (which is +tested by feature_taproot.py) but instead makes sure that the parameters +do what we expect. +""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal + +class SimplicityActivationTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 1 + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + + def test_activation(self, rpc, activation_height): + self.log.info("Testing activation at height %d" % activation_height) + activation_height = 128 * ((activation_height + 127) // 128) + + assert_equal(rpc.getblockcount(), 0) + + blocks = self.generatetoaddress(rpc, activation_height - 2, rpc.getnewaddress()) + assert_equal(rpc.getblockcount(), activation_height - 2) + + for n, block in enumerate(blocks): + decode = rpc.getblockheader(block) + if n < 143: + assert_equal (decode["versionHex"], "20000000") + elif n < 431: + # TESTDUMMY deployment: 144 blocks active, 144 blocks locked in + assert_equal (decode["versionHex"], "30000000") + else: + assert_equal (decode["versionHex"], "20000000") + + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status"], "defined") + # The 1023rd block does not signal, but changes status-next to "started" from "defined" + # bitcoin PR #23508 changed bip9 status to the current block instead of the next block + blocks = self.generatetoaddress(rpc, 1, rpc.getnewaddress()) + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status"], "defined") + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status-next"], "started") + assert_equal(rpc.getblockheader(blocks[0])["versionHex"], "20000000") + + blocks = self.generatetoaddress(rpc, 127, rpc.getnewaddress()) + for n, block in enumerate(blocks): + decode = rpc.getblockheader(block) + assert_equal (decode["versionHex"], "21000000") + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status"], "started") + + # Fail to signal on the 128th block. Since the threshold for Simplicity is + # 100% this will prevent activation. Note that our period is 128, not + # 144 (the default), as we have overridden the period for Simplicity. On + # the main Liquid chain it is overridden to be one week of signalling. + block = rpc.getnewblockhex() + block = block[:7] + "0" + block[8:] # turn off Simplicity signal + rpc.submitblock(block) + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status"], "started") + + # Run through another 128 blocks, without failing to signal + blocks = self.generatetoaddress(rpc, 127, rpc.getnewaddress()) + for n, block in enumerate(blocks): + decode = rpc.getblockheader(block) + assert_equal (decode["versionHex"], "21000000") + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status"], "started") + # The 128th block then switches from "started" to "locked_in" + blocks = self.generatetoaddress(rpc, 1, rpc.getnewaddress()) + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status"], "started") + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status-next"], "locked_in") + assert_equal(rpc.getblockheader(blocks[0])["versionHex"], "21000000") + + # Run through another 128 blocks, which will go from "locked in" to "active" regardless of signalling + blocks = self.generatetoaddress(rpc, 127, rpc.getnewaddress()) + for n, block in enumerate(blocks): + decode = rpc.getblockheader(block) + assert_equal (decode["versionHex"], "21000000") + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status"], "locked_in") + block = rpc.getnewblockhex() + block = block[:7] + "0" + block[8:] # turn off Simplicity signal + rpc.submitblock(block) + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status"], "locked_in") + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status-next"], "active") + + # After the state is "active", signallng stops by default. + blocks = self.generatetoaddress(rpc, 1, self.nodes[0].getnewaddress()) + assert_equal(rpc.getdeploymentinfo()["deployments"]["simplicity"]["bip9"]["status"], "active") + assert_equal(rpc.getblockheader(blocks[0])["versionHex"], "20000000") + + def run_test(self): + # Test that regtest nodes never signal Simplicity or Simplicity by default + self.log.info("Testing node not configured to activate Simplicity") + blocks = self.generatetoaddress(self.nodes[0], 2500, self.nodes[0].getnewaddress()) + assert_equal(self.nodes[0].getblockcount(), 2500) + for n, block in enumerate(blocks): + decode = self.nodes[0].getblockheader(block) + if n < 143: + assert_equal (decode["versionHex"], "20000000") + elif n < 431: + # TESTDUMMY deployment: 144 blocks active, 144 blocks locked in + assert_equal (decode["versionHex"], "30000000") + else: + assert_equal (decode["versionHex"], "20000000") + + # Test activation starting from height 1000 + # Note that for Simplicity this is an illogical combination (Simplicity without + # Taproot) but for purposes of this test it's fine. + self.restart_node(0, ["-evbparams=simplicity:500:::"]) + self.nodes[0].invalidateblock(self.nodes[0].getblockhash(1)) + self.test_activation(self.nodes[0], 500) + +if __name__ == '__main__': + SimplicityActivationTest().main() diff --git a/test/functional/feature_taproot.py b/test/functional/feature_taproot.py index 24e088f21f7..b720010dcb8 100755 --- a/test/functional/feature_taproot.py +++ b/test/functional/feature_taproot.py @@ -1302,6 +1302,10 @@ def set_test_params(self): self.wallet_names = [None, self.default_wallet_name] else: self.extra_args[0].append("-vbparams=taproot:1:1") + # ELEMENTS: both nodes have Simplicity active. We activate one with evbparams + # and the other with vbparams to check that both work. + self.extra_args[0].append("-vbparams=simplicity:-1:1") + self.extra_args[1].append("-evbparams=simplicity:-1:::") def setup_nodes(self): self.add_nodes(self.num_nodes, self.extra_args, versions=[ diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index fc3c1034cce..b9efe9b8d87 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -241,6 +241,7 @@ 'p2p_invalid_locator.py', 'p2p_invalid_block.py', 'feature_elements_taproot_activation.py', + 'feature_elements_simplicity_activation.py', # ELEMENTS: needs to be fixed #'p2p_invalid_messages.py', 'p2p_invalid_tx.py',