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

Implement BIP 347 validation (OP_CAT) #68

Merged
merged 5 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ enum DeploymentPos : uint16_t {
DEPLOYMENT_TESTDUMMY,
DEPLOYMENT_CHECKTEMPLATEVERIFY, // Deployment of CTV (BIP 119)
DEPLOYMENT_ANYPREVOUT,
DEPLOYMENT_OP_CAT,
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp
MAX_VERSION_BITS_DEPLOYMENTS
};
Expand Down
6 changes: 6 additions & 0 deletions src/deploymentinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_B
/*.name =*/ "anyprevout",
/*.gbt_force =*/ true,
},
{
/*.name =*/ "opcat",
/*.gbt_force =*/ true,
},
};

std::string DeploymentName(Consensus::BuriedDeployment dep)
Expand Down Expand Up @@ -89,6 +93,8 @@ const std::map<std::string, uint32_t> g_verify_flag_names{
FLAG_NAME(DISCOURAGE_CHECK_TEMPLATE_VERIFY_HASH),
FLAG_NAME(ANYPREVOUT),
FLAG_NAME(DISCOURAGE_ANYPREVOUT),
FLAG_NAME(OP_CAT),
FLAG_NAME(DISCOURAGE_OP_CAT),
};
#undef FLAG_NAME

Expand Down
13 changes: 12 additions & 1 deletion src/kernel/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ class CMainParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY] = SetupDeployment{.activate = 0x30000000, .abandon = 0, .never = true};
consensus.vDeployments[Consensus::DEPLOYMENT_CHECKTEMPLATEVERIFY] = SetupDeployment{.activate = 0x60007700, .abandon = 0x40007700, .never = true};
consensus.vDeployments[Consensus::DEPLOYMENT_ANYPREVOUT] = SetupDeployment{.activate = 0x60007600, .abandon = 0x40007600, .never = true};
consensus.vDeployments[Consensus::DEPLOYMENT_OP_CAT] = SetupDeployment{.activate = 0x62000100, .abandon = 0x42000100, .never = true};

consensus.nMinimumChainWork = uint256{"000000000000000000000000000000000000000088e186b70e0862c193ec44d6"};
consensus.defaultAssumeValid = uint256{"000000000000000000011c5890365bdbe5d25b97ce0057589acaef4f1a57263f"}; // 856760
Expand Down Expand Up @@ -262,6 +263,7 @@ class CTestNetParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY] = SetupDeployment{.activate = 0x30000000, .abandon = 0, .never = true};
consensus.vDeployments[Consensus::DEPLOYMENT_CHECKTEMPLATEVERIFY] = SetupDeployment{.activate = 0x60007700, .abandon = 0x40007700, .never = true};
consensus.vDeployments[Consensus::DEPLOYMENT_ANYPREVOUT] = SetupDeployment{.activate = 0x60007600, .abandon = 0x40007600, .never = true};
consensus.vDeployments[Consensus::DEPLOYMENT_OP_CAT] = SetupDeployment{.activate = 0x62000100, .abandon = 0x42000100, .never = true};

consensus.nMinimumChainWork = uint256{"000000000000000000000000000000000000000000000f209695166be8b61fa9"};
consensus.defaultAssumeValid = uint256{"000000000000000465b1a66c9f386308e8c75acef9201f3f577811da09fc90ad"}; // 2873500
Expand Down Expand Up @@ -497,6 +499,15 @@ class SigNetParams : public CChainParams {
.activate = 0x60007600,
.abandon = 0x40007600,
};
consensus.vDeployments[Consensus::DEPLOYMENT_OP_CAT] = SetupDeployment{
.year = 2024,
.number = 1,
.revision = 0,
.start = 1704085200, // 2024-01-01
.timeout = 2019704400, // 2034-01-01
.activate = 0x62000100,
.abandon = 0x42000100,
};

RenounceDeployments(options.renounce, consensus.vDeployments);

Expand Down Expand Up @@ -572,7 +583,7 @@ class CRegTestParams : public CChainParams
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY] = SetupDeployment{.start = 0, .timeout = Consensus::HereticalDeployment::NO_TIMEOUT, .activate = 0x30000000, .abandon = 0x50000000};
consensus.vDeployments[Consensus::DEPLOYMENT_CHECKTEMPLATEVERIFY] = SetupDeployment{.activate = 0x60007700, .abandon = 0x40007700, .always = true};
consensus.vDeployments[Consensus::DEPLOYMENT_ANYPREVOUT] = SetupDeployment{.activate = 0x60007600, .abandon = 0x40007600, .always = true};

consensus.vDeployments[Consensus::DEPLOYMENT_OP_CAT] = SetupDeployment{.activate = 0x62000100, .abandon = 0x42000100, .always = true};
consensus.nMinimumChainWork = uint256{};
consensus.defaultAssumeValid = uint256{};

Expand Down
4 changes: 3 additions & 1 deletion src/policy/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_CHECK_TEMPLATE_VERIFY_HASH |
SCRIPT_VERIFY_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH |
SCRIPT_VERIFY_ANYPREVOUT};
SCRIPT_VERIFY_ANYPREVOUT |
SCRIPT_VERIFY_OP_CAT
};

/** 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
1 change: 1 addition & 0 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,7 @@ UniValue DeploymentInfo(const CBlockIndex* blockindex, const ChainstateManager&
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_TAPROOT);
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_CHECKTEMPLATEVERIFY);
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_ANYPREVOUT);
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_OP_CAT);
return softforks;
}
} // anon namespace
Expand Down
40 changes: 34 additions & 6 deletions src/script/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,10 +467,16 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) {
return set_error(serror, SCRIPT_ERR_OP_COUNT);
}

// When OP_SUCCESS disabled opcodes (CVE-2010-5137) are
// redefined in tapscript, remove them from the if below
// and put them here
if (opcode == OP_CAT) {
return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes (CVE-2010-5137).
}
}

if (opcode == OP_CAT ||
opcode == OP_SUBSTR ||
if (opcode == OP_SUBSTR ||
opcode == OP_LEFT ||
opcode == OP_RIGHT ||
opcode == OP_INVERT ||
Expand Down Expand Up @@ -534,6 +540,19 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
case OP_NOP:
break;

case OP_CAT:
{
if (stack.size() < 2)
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype& vch1 = stacktop(-2);
valtype& vch2 = stacktop(-1);
if (vch1.size() + vch2.size() > MAX_SCRIPT_ELEMENT_SIZE)
return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
vch1.insert(vch1.end(), vch2.begin(), vch2.end());
stack.pop_back();
}
break;

case OP_CHECKLOCKTIMEVERIFY:
{
if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
Expand Down Expand Up @@ -1961,12 +1980,21 @@ std::optional<bool> CheckTapscriptOpSuccess(const CScript& exec_script, unsigned
// Note how this condition would not be reached if an unknown OP_SUCCESSx was found
return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
}
// New opcodes will be listed here. May use a different sigversion to modify existing opcodes.

if (IsOpSuccess(opcode)) {
if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
return set_error(serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
if (opcode == OP_CAT) {
if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_CAT) {
return set_error(serror, SCRIPT_ERR_DISCOURAGE_OP_CAT);
} else if (!(flags & SCRIPT_VERIFY_OP_CAT)) {
return set_success(serror);
}
} else {
// OP_SUCCESS behaviour
if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
return set_error(serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
}
return set_success(serror);
}
return set_success(serror);
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/script/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ enum : uint32_t {
// Making ANYPREVOUT public key versions (in BIP 342 scripts) non-standard
SCRIPT_VERIFY_DISCOURAGE_ANYPREVOUT = (1U << 25),

// Support OP_CAT in tapscript
SCRIPT_VERIFY_OP_CAT = (1U << 26),
SCRIPT_VERIFY_DISCOURAGE_OP_CAT = (1U << 27),

// Constants to point to the highest flag in use. Add new flags above this line.
//
SCRIPT_VERIFY_END_MARKER
Expand Down
1 change: 1 addition & 0 deletions src/script/script_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ typedef enum ScriptError_t
SCRIPT_ERR_DISCOURAGE_OP_SUCCESS,
SCRIPT_ERR_DISCOURAGE_UPGRADABLE_PUBKEYTYPE,
SCRIPT_ERR_DISCOURAGE_ANYPREVOUT,
SCRIPT_ERR_DISCOURAGE_OP_CAT,

/* segregated witness */
SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH,
Expand Down
Loading
Loading