Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OP_CHECKTEMPLATEVERIFY, OP_CHECKSIGFROMSTACK(VERIFY), OP_INTERNALKEY validation (LNHANCE) #29198

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Makefile.test.include
Expand Up @@ -19,6 +19,7 @@ JSON_TEST_FILES = \
test/data/bip341_wallet_vectors.json \
test/data/base58_encode_decode.json \
test/data/blockfilters.json \
test/data/ctvhash.json \
test/data/key_io_valid.json \
test/data/key_io_invalid.json \
test/data/script_tests.json \
Expand Down Expand Up @@ -88,6 +89,7 @@ BITCOIN_TESTS =\
test/compilerbug_tests.cpp \
test/compress_tests.cpp \
test/crypto_tests.cpp \
test/ctvhash_tests.cpp \
test/cuckoocache_tests.cpp \
test/dbwrapper_tests.cpp \
test/denialofservice_tests.cpp \
Expand Down
1 change: 1 addition & 0 deletions src/addresstype.cpp
Expand Up @@ -94,6 +94,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
case TxoutType::MULTISIG:
case TxoutType::NULL_DATA:
case TxoutType::NONSTANDARD:
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
addressRet = CNoDestination(scriptPubKey);
return false;
} // no default case, so the compiler can warn about missing cases
Expand Down
1 change: 1 addition & 0 deletions src/consensus/params.h
Expand Up @@ -32,6 +32,7 @@ constexpr bool ValidDeployment(BuriedDeployment dep) { return dep <= DEPLOYMENT_
enum DeploymentPos : uint16_t {
DEPLOYMENT_TESTDUMMY,
DEPLOYMENT_TAPROOT, // Deployment of Schnorr/Taproot (BIPs 340-342)
DEPLOYMENT_LNHANCE, // Deployment of CHECKTEMPLATEVERIFY, CHECKSIGFROMSTACK(VERIFY), OP_INTERNALKEY (BIPs 119, xxx, yyy)
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp
MAX_VERSION_BITS_DEPLOYMENTS
};
Expand Down
4 changes: 4 additions & 0 deletions src/deploymentinfo.cpp
Expand Up @@ -17,6 +17,10 @@ const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_B
/*.name =*/ "taproot",
/*.gbt_force =*/ true,
},
{
/*.name =*/ "lnhance",
/*.gbt_force =*/ true,
},
};

std::string DeploymentName(Consensus::BuriedDeployment dep)
Expand Down
24 changes: 24 additions & 0 deletions src/kernel/chainparams.cpp
Expand Up @@ -103,6 +103,12 @@ class CMainParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = 1619222400; // April 24th, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 709632; // Approximately November 12th, 2021
//
// Deployment of ctv/csfs/internalkey (BIPs 119, yyy, zzz)
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].bit = 3;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].min_activation_height = 0; // No activation delay

consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000052b2559353df4117b7348b64");
consensus.defaultAssumeValid = uint256S("0x00000000000000000001a0a448d6cf2546b06801389cc030b2b18c6491266815"); // 804000
Expand Down Expand Up @@ -222,6 +228,12 @@ class CTestNetParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay

// Deployment of ctv/csfs/internalkey (BIPs 119, yyy, zzz)
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].bit = 3;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].min_activation_height = 0; // No activation delay

consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000b6a51f415a67c0da307");
consensus.defaultAssumeValid = uint256S("0x0000000000000093bcb68c03a9a168ae252572d348a2eaeba2cdf9231d73206f"); // 2500000

Expand Down Expand Up @@ -359,6 +371,12 @@ class SigNetParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay

// Deployment of ctv/csfs/internalkey (BIPs 119, yyy, zzz)
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].bit = 3;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].min_activation_height = 0; // No activation delay

// message start is defined as the first 4 bytes of the sha256d of the block script
HashWriter h{};
h << consensus.signet_challenge;
Expand Down Expand Up @@ -435,6 +453,12 @@ class CRegTestParams : public CChainParams
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay

// Deployment of ctv/csfs/internalkey (BIPs 119, yyy, zzz)
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].bit = 3;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_LNHANCE].min_activation_height = 0;

consensus.nMinimumChainWork = uint256{};
consensus.defaultAssumeValid = uint256{};

Expand Down
5 changes: 5 additions & 0 deletions src/policy/policy.cpp
Expand Up @@ -202,6 +202,11 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
return false;
}
} else if (whichType == TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY) {
// after activation, only allow bare with no scriptsig.
// pre-activation disallowing enforced via discouraged logic in the
// interpreter.
if (tx.vin[i].scriptSig.size() != 0) return false;
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/policy/policy.h
Expand Up @@ -113,7 +113,9 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI
SCRIPT_VERIFY_CONST_SCRIPTCODE |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION |
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE};
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_CHECKTEMPLATEVERIFY |
SCRIPT_VERIFY_LNHANCE};

/** For convenience, standard but not mandatory verify flags. */
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS};
Expand Down
4 changes: 2 additions & 2 deletions src/pubkey.cpp
Expand Up @@ -217,12 +217,12 @@ bool XOnlyPubKey::IsFullyValid() const
return secp256k1_xonly_pubkey_parse(secp256k1_context_static, &pubkey, m_keydata.data());
}

bool XOnlyPubKey::VerifySchnorr(const uint256& msg, Span<const unsigned char> sigbytes) const
bool XOnlyPubKey::VerifySchnorr(const Span<const unsigned char> msg, Span<const unsigned char> sigbytes) const
{
assert(sigbytes.size() == 64);
secp256k1_xonly_pubkey pubkey;
if (!secp256k1_xonly_pubkey_parse(secp256k1_context_static, &pubkey, m_keydata.data())) return false;
return secp256k1_schnorrsig_verify(secp256k1_context_static, sigbytes.data(), msg.begin(), 32, &pubkey);
return secp256k1_schnorrsig_verify(secp256k1_context_static, sigbytes.data(), msg.data(), msg.size(), &pubkey);
}

static const HashWriter HASHER_TAPTWEAK{TaggedHash("TapTweak")};
Expand Down
2 changes: 1 addition & 1 deletion src/pubkey.h
Expand Up @@ -258,7 +258,7 @@ class XOnlyPubKey
*
* sigbytes must be exactly 64 bytes.
*/
bool VerifySchnorr(const uint256& msg, Span<const unsigned char> sigbytes) const;
bool VerifySchnorr(const Span<const unsigned char> msg, Span<const unsigned char> sigbytes) const;

/** Compute the Taproot tweak as specified in BIP341, with *this as internal
* key:
Expand Down
1 change: 1 addition & 0 deletions src/rpc/blockchain.cpp
Expand Up @@ -1315,6 +1315,7 @@ UniValue DeploymentInfo(const CBlockIndex* blockindex, const ChainstateManager&
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_SEGWIT);
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_TESTDUMMY);
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_TAPROOT);
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_LNHANCE);
return softforks;
}
} // anon namespace
Expand Down
4 changes: 4 additions & 0 deletions src/rpc/rawtransaction.cpp
Expand Up @@ -556,6 +556,8 @@ static RPCHelpMan decodescript()
case TxoutType::SCRIPTHASH:
case TxoutType::WITNESS_UNKNOWN:
case TxoutType::WITNESS_V1_TAPROOT:
// don't wrap CTV because P2SH CTV is a hash cycle
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
// Should not be wrapped
return false;
} // no default case, so the compiler can warn about missing cases
Expand Down Expand Up @@ -598,6 +600,8 @@ static RPCHelpMan decodescript()
case TxoutType::WITNESS_V0_KEYHASH:
case TxoutType::WITNESS_V0_SCRIPTHASH:
case TxoutType::WITNESS_V1_TAPROOT:
// don't wrap CTV because P2SH CTV is a hash cycle
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
// Should not be wrapped
return false;
} // no default case, so the compiler can warn about missing cases
Expand Down