policy: make bare OP_CHECKTEMPLATEVERIFY standard

Co-authored-by: James O'Beirne <github@au92.org>
This commit is contained in:
Jeremy Rubin 2019-10-16 15:04:09 -07:00 committed by James O'Beirne
parent a0bd24e9cd
commit d314cbb7ee
No known key found for this signature in database
GPG key ID: 7A935DADB2C44F05
13 changed files with 42 additions and 1 deletions

View file

@ -98,6 +98,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

View file

@ -212,6 +212,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;
}
}

View file

@ -124,7 +124,10 @@ 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_CHECKTEMPLATEVERIFY |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_CHECKTEMPLATEVERIFY |
SCRIPT_VERIFY_CHECKTEMPLATEVERIFY};
/** 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};

View file

@ -544,6 +544,8 @@ static RPCHelpMan decodescript()
case TxoutType::WITNESS_UNKNOWN:
case TxoutType::WITNESS_V1_TAPROOT:
case TxoutType::ANCHOR:
// 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
@ -587,6 +589,8 @@ static RPCHelpMan decodescript()
case TxoutType::WITNESS_V0_SCRIPTHASH:
case TxoutType::WITNESS_V1_TAPROOT:
case TxoutType::ANCHOR:
// 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

View file

@ -221,6 +221,14 @@ bool CScript::IsPayToAnchor(int version, const std::vector<unsigned char>& progr
program[1] == 0x73;
}
bool CScript::IsPayToBareDefaultCheckTemplateVerifyHash() const
{
// Extra-fast test for pay-to-bare-default-check-template-verify-hash CScripts:
return (this->size() == 34 &&
(*this)[0] == 0x20 &&
(*this)[33] == OP_CHECKTEMPLATEVERIFY);
}
bool CScript::IsPayToScriptHash() const
{
// Extra-fast test for pay-to-script-hash CScripts:

View file

@ -553,6 +553,8 @@ public:
*/
static bool IsPayToAnchor(int version, const std::vector<unsigned char>& program);
bool IsPayToBareDefaultCheckTemplateVerifyHash() const;
bool IsPayToScriptHash() const;
bool IsPayToWitnessScriptHash() const;
bool IsWitnessProgram(int& version, std::vector<unsigned char>& program) const;

View file

@ -412,6 +412,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
case TxoutType::NONSTANDARD:
case TxoutType::NULL_DATA:
case TxoutType::WITNESS_UNKNOWN:
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
return false;
case TxoutType::PUBKEY:
if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion)) return false;

View file

@ -29,6 +29,7 @@ std::string GetTxnOutputType(TxoutType t)
case TxoutType::WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
case TxoutType::WITNESS_V1_TAPROOT: return "witness_v1_taproot";
case TxoutType::WITNESS_UNKNOWN: return "witness_unknown";
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY: return "bare_default_ctv_hash";
} // no default case, so the compiler can warn about missing cases
assert(false);
}
@ -151,6 +152,10 @@ TxoutType Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned c
return TxoutType::SCRIPTHASH;
}
if (scriptPubKey.IsPayToBareDefaultCheckTemplateVerifyHash()) {
return TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY;
}
int witnessversion;
std::vector<unsigned char> witnessprogram;
if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {

View file

@ -31,6 +31,7 @@ enum class TxoutType {
WITNESS_V0_SCRIPTHASH,
WITNESS_V0_KEYHASH,
WITNESS_V1_TAPROOT,
TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY,
WITNESS_UNKNOWN, //!< Only for Witness versions not already defined above
};

View file

@ -76,6 +76,7 @@ FUZZ_TARGET(script, .init = initialize_script)
assert(which_type == TxoutType::PUBKEY ||
which_type == TxoutType::NONSTANDARD ||
which_type == TxoutType::NULL_DATA ||
which_type == TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY ||
which_type == TxoutType::MULTISIG);
}
if (which_type == TxoutType::NONSTANDARD ||

View file

@ -70,6 +70,9 @@ static std::map<std::string, unsigned int> mapFlagNames = {
{std::string("DISCOURAGE_UPGRADABLE_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE},
{std::string("DISCOURAGE_OP_SUCCESS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS},
{std::string("DISCOURAGE_UPGRADABLE_TAPROOT_VERSION"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION},
{std::string("DISCOURAGE_UPGRADABLE_CHECKTEMPLATEVERIFY"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_CHECKTEMPLATEVERIFY},
{std::string("DISCOURAGE_CHECKTEMPLATEVERIFY"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_CHECKTEMPLATEVERIFY},
{std::string("CHECKTEMPLATEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKTEMPLATEVERIFY},
};
unsigned int ParseScriptFlags(std::string strFlags)

View file

@ -912,6 +912,8 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d
case TxoutType::WITNESS_V1_TAPROOT:
case TxoutType::ANCHOR:
return "unrecognized script";
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
return "bare default CheckTemplateVerify hash";
} // no default case, so the compiler can warn about missing cases
NONFATAL_UNREACHABLE();
}

View file

@ -208,6 +208,11 @@ IsMineResult IsMineInner(const LegacyDataSPKM& keystore, const CScript& scriptPu
}
break;
}
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
{
ret = IsMineResult::NO;
break;
}
} // no default case, so the compiler can warn about missing cases
if (ret == IsMineResult::NO && keystore.HaveWatchOnly(scriptPubKey)) {