diff --git a/src/chainparams.cpp b/src/chainparams.cpp index e8da22fe69..570a41ec35 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -153,6 +153,7 @@ public: consensus.genesis_subsidy = 50*COIN; consensus.connect_genesis_outputs = false; anyonecanspend_aremine = false; + enforce_pak = false; /** * The message start string is designed to be unlikely to occur in normal data. @@ -271,6 +272,7 @@ public: consensus.genesis_subsidy = 50*COIN; consensus.connect_genesis_outputs = false; anyonecanspend_aremine = false; + enforce_pak = false; pchMessageStart[0] = 0x0b; pchMessageStart[1] = 0x11; @@ -364,6 +366,7 @@ public: consensus.genesis_subsidy = 50*COIN; consensus.connect_genesis_outputs = false; anyonecanspend_aremine = false; + enforce_pak = false; pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0xbf; @@ -541,6 +544,9 @@ class CCustomParams : public CRegTestParams { anyonecanspend_aremine = args.GetBoolArg("-anyonecanspendaremine", true); consensus.has_parent_chain = args.GetBoolArg("-con_has_parent_chain", true); + + enforce_pak = args.GetBoolArg("-enforce_pak", false); + // bitcoin regtest is the parent chain by default parentGenesisBlockHash = uint256S(args.GetArg("-parentgenesisblockhash", "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")); // Either it has a parent chain or not diff --git a/src/chainparams.h b/src/chainparams.h index 8665b4ed53..69e2fe1743 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -87,6 +87,7 @@ public: const uint256 ParentGenesisBlockHash() const { return parentGenesisBlockHash; } bool anyonecanspend_aremine; const std::string& ParentBech32HRP() const { return parent_bech32_hrp; } + bool GetEnforcePak() const { return enforce_pak; } protected: CChainParams() {} @@ -111,6 +112,7 @@ protected: // ELEMENTS extra fields: uint256 parentGenesisBlockHash; std::string parent_bech32_hrp; + bool enforce_pak; }; /** diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 20397e53f0..e038d41dff 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -38,6 +38,7 @@ void SetupChainParamsBaseOptions() gArgs.AddArg("-con_parent_chain_signblockscript", "Whether parent chain uses pow or signed blocks. If the parent chain uses signed blocks, the challenge (scriptPubKey) script. If not, an empty string. (default: empty script [ie parent uses pow])", false, OptionsCategory::CHAINPARAMS); gArgs.AddArg("-fedpegscript", "The script for the federated peg.", false, OptionsCategory::CHAINPARAMS); + gArgs.AddArg("-enforce_pak", "Causes standardness checks to enforce Pegout Authorization Key(PAK) validation, and miner to include PAK commitments when configured. Can not be set when acceptnonstdtx is set to true.", false, OptionsCategory::ELEMENTS); } static std::unique_ptr globalChainBaseParams; diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 20eba0de46..270e0d48aa 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -14,6 +14,7 @@ #include #include #include +#include // Peg-out enforcement CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) @@ -61,6 +62,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) if (!Solver(scriptPubKey, whichType, vSolutions)) return false; + CChainParams params = Params(); if (whichType == TX_MULTISIG) { unsigned char m = vSolutions.front()[0]; @@ -70,6 +72,10 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) return false; if (m < 1 || m > n) return false; + } else if (whichType == TX_NULL_DATA && params.GetEnforcePak() && + scriptPubKey.IsPegoutScript(Params().ParentGenesisBlockHash()) ) { + // If we're enforcing pak let through larger peg-out scripts + return true; } else if (whichType == TX_NULL_DATA && (!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) return false; @@ -113,6 +119,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason) } } + CChainParams params = Params(); unsigned int nDataOut = 0; txnouttype whichType; for (const CTxOut& txout : tx.vout) { @@ -121,9 +128,18 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason) return false; } - if (whichType == TX_NULL_DATA) + if (whichType == TX_NULL_DATA) { + } + if (whichType == TX_NULL_DATA) { nDataOut++; - else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) { + if (params.GetEnforcePak() && + txout.scriptPubKey.IsPegoutScript(params.ParentGenesisBlockHash()) && + (!ScriptHasValidPAKProof(txout.scriptPubKey, params.ParentGenesisBlockHash()))) { + // TODO(rebase) CT/CA check for asset type + reason = "invalid-pegout-proof"; + return false; + } + } else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) { reason = "bare-multisig"; return false; } else if (IsDust(txout, ::dustRelayFee)) {