Skip to content

Commit a4ccaf6

Browse files
authored
Merge pull request #68 from ajtowns/202409-inq28-cat
Implement BIP 347 validation (OP_CAT)
2 parents aa0c738 + e9b3214 commit a4ccaf6

16 files changed

+960
-19
lines changed

src/consensus/params.h

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ enum DeploymentPos : uint16_t {
3434
DEPLOYMENT_TESTDUMMY,
3535
DEPLOYMENT_CHECKTEMPLATEVERIFY, // Deployment of CTV (BIP 119)
3636
DEPLOYMENT_ANYPREVOUT,
37+
DEPLOYMENT_OP_CAT,
3738
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp
3839
MAX_VERSION_BITS_DEPLOYMENTS
3940
};

src/deploymentinfo.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_B
2323
/*.name =*/ "anyprevout",
2424
/*.gbt_force =*/ true,
2525
},
26+
{
27+
/*.name =*/ "opcat",
28+
/*.gbt_force =*/ true,
29+
},
2630
};
2731

2832
std::string DeploymentName(Consensus::BuriedDeployment dep)
@@ -89,6 +93,8 @@ const std::map<std::string, uint32_t> g_verify_flag_names{
8993
FLAG_NAME(DISCOURAGE_CHECK_TEMPLATE_VERIFY_HASH),
9094
FLAG_NAME(ANYPREVOUT),
9195
FLAG_NAME(DISCOURAGE_ANYPREVOUT),
96+
FLAG_NAME(OP_CAT),
97+
FLAG_NAME(DISCOURAGE_OP_CAT),
9298
};
9399
#undef FLAG_NAME
94100

src/kernel/chainparams.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ class CMainParams : public CChainParams {
144144
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY] = SetupDeployment{.activate = 0x30000000, .abandon = 0, .never = true};
145145
consensus.vDeployments[Consensus::DEPLOYMENT_CHECKTEMPLATEVERIFY] = SetupDeployment{.activate = 0x60007700, .abandon = 0x40007700, .never = true};
146146
consensus.vDeployments[Consensus::DEPLOYMENT_ANYPREVOUT] = SetupDeployment{.activate = 0x60007600, .abandon = 0x40007600, .never = true};
147+
consensus.vDeployments[Consensus::DEPLOYMENT_OP_CAT] = SetupDeployment{.activate = 0x62000100, .abandon = 0x42000100, .never = true};
147148

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

266268
consensus.nMinimumChainWork = uint256{"000000000000000000000000000000000000000000000f209695166be8b61fa9"};
267269
consensus.defaultAssumeValid = uint256{"000000000000000465b1a66c9f386308e8c75acef9201f3f577811da09fc90ad"}; // 2873500
@@ -497,6 +499,15 @@ class SigNetParams : public CChainParams {
497499
.activate = 0x60007600,
498500
.abandon = 0x40007600,
499501
};
502+
consensus.vDeployments[Consensus::DEPLOYMENT_OP_CAT] = SetupDeployment{
503+
.year = 2024,
504+
.number = 1,
505+
.revision = 0,
506+
.start = 1704085200, // 2024-01-01
507+
.timeout = 2019704400, // 2034-01-01
508+
.activate = 0x62000100,
509+
.abandon = 0x42000100,
510+
};
500511

501512
RenounceDeployments(options.renounce, consensus.vDeployments);
502513

@@ -572,7 +583,7 @@ class CRegTestParams : public CChainParams
572583
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY] = SetupDeployment{.start = 0, .timeout = Consensus::HereticalDeployment::NO_TIMEOUT, .activate = 0x30000000, .abandon = 0x50000000};
573584
consensus.vDeployments[Consensus::DEPLOYMENT_CHECKTEMPLATEVERIFY] = SetupDeployment{.activate = 0x60007700, .abandon = 0x40007700, .always = true};
574585
consensus.vDeployments[Consensus::DEPLOYMENT_ANYPREVOUT] = SetupDeployment{.activate = 0x60007600, .abandon = 0x40007600, .always = true};
575-
586+
consensus.vDeployments[Consensus::DEPLOYMENT_OP_CAT] = SetupDeployment{.activate = 0x62000100, .abandon = 0x42000100, .always = true};
576587
consensus.nMinimumChainWork = uint256{};
577588
consensus.defaultAssumeValid = uint256{};
578589

src/policy/policy.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI
116116
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE |
117117
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_CHECK_TEMPLATE_VERIFY_HASH |
118118
SCRIPT_VERIFY_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH |
119-
SCRIPT_VERIFY_ANYPREVOUT};
119+
SCRIPT_VERIFY_ANYPREVOUT |
120+
SCRIPT_VERIFY_OP_CAT
121+
};
120122

121123
/** For convenience, standard but not mandatory verify flags. */
122124
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS};

src/rpc/blockchain.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,7 @@ UniValue DeploymentInfo(const CBlockIndex* blockindex, const ChainstateManager&
13951395
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_TAPROOT);
13961396
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_CHECKTEMPLATEVERIFY);
13971397
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_ANYPREVOUT);
1398+
SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_OP_CAT);
13981399
return softforks;
13991400
}
14001401
} // anon namespace

src/script/interpreter.cpp

+34-6
Original file line numberDiff line numberDiff line change
@@ -467,10 +467,16 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
467467
if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) {
468468
return set_error(serror, SCRIPT_ERR_OP_COUNT);
469469
}
470+
471+
// When OP_SUCCESS disabled opcodes (CVE-2010-5137) are
472+
// redefined in tapscript, remove them from the if below
473+
// and put them here
474+
if (opcode == OP_CAT) {
475+
return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes (CVE-2010-5137).
476+
}
470477
}
471478

472-
if (opcode == OP_CAT ||
473-
opcode == OP_SUBSTR ||
479+
if (opcode == OP_SUBSTR ||
474480
opcode == OP_LEFT ||
475481
opcode == OP_RIGHT ||
476482
opcode == OP_INVERT ||
@@ -534,6 +540,19 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
534540
case OP_NOP:
535541
break;
536542

543+
case OP_CAT:
544+
{
545+
if (stack.size() < 2)
546+
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
547+
valtype& vch1 = stacktop(-2);
548+
valtype& vch2 = stacktop(-1);
549+
if (vch1.size() + vch2.size() > MAX_SCRIPT_ELEMENT_SIZE)
550+
return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
551+
vch1.insert(vch1.end(), vch2.begin(), vch2.end());
552+
stack.pop_back();
553+
}
554+
break;
555+
537556
case OP_CHECKLOCKTIMEVERIFY:
538557
{
539558
if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
@@ -1961,12 +1980,21 @@ std::optional<bool> CheckTapscriptOpSuccess(const CScript& exec_script, unsigned
19611980
// Note how this condition would not be reached if an unknown OP_SUCCESSx was found
19621981
return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
19631982
}
1964-
// New opcodes will be listed here. May use a different sigversion to modify existing opcodes.
1983+
19651984
if (IsOpSuccess(opcode)) {
1966-
if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
1967-
return set_error(serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
1985+
if (opcode == OP_CAT) {
1986+
if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_CAT) {
1987+
return set_error(serror, SCRIPT_ERR_DISCOURAGE_OP_CAT);
1988+
} else if (!(flags & SCRIPT_VERIFY_OP_CAT)) {
1989+
return set_success(serror);
1990+
}
1991+
} else {
1992+
// OP_SUCCESS behaviour
1993+
if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
1994+
return set_error(serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
1995+
}
1996+
return set_success(serror);
19681997
}
1969-
return set_success(serror);
19701998
}
19711999
}
19722000
}

src/script/interpreter.h

+4
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ enum : uint32_t {
159159
// Making ANYPREVOUT public key versions (in BIP 342 scripts) non-standard
160160
SCRIPT_VERIFY_DISCOURAGE_ANYPREVOUT = (1U << 25),
161161

162+
// Support OP_CAT in tapscript
163+
SCRIPT_VERIFY_OP_CAT = (1U << 26),
164+
SCRIPT_VERIFY_DISCOURAGE_OP_CAT = (1U << 27),
165+
162166
// Constants to point to the highest flag in use. Add new flags above this line.
163167
//
164168
SCRIPT_VERIFY_END_MARKER

src/script/script_error.h

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ typedef enum ScriptError_t
6161
SCRIPT_ERR_DISCOURAGE_OP_SUCCESS,
6262
SCRIPT_ERR_DISCOURAGE_UPGRADABLE_PUBKEYTYPE,
6363
SCRIPT_ERR_DISCOURAGE_ANYPREVOUT,
64+
SCRIPT_ERR_DISCOURAGE_OP_CAT,
6465

6566
/* segregated witness */
6667
SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH,

0 commit comments

Comments
 (0)