diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 57b7a1ee75..0cdfc6621b 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -12,12 +12,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include diff --git a/src/dynafed.cpp b/src/dynafed.cpp index d719795149..cb288a83ed 100644 --- a/src/dynafed.cpp +++ b/src/dynafed.cpp @@ -123,3 +123,34 @@ DynaFedParamEntry ComputeNextBlockCurrentParameters(const CBlockIndex* pindexPre } } +bool ParseFedPegQuorum(const CScript& fedpegscript, int& t, int& n) { + CScript::const_iterator it = fedpegscript.begin(); + std::vector vch; + opcodetype opcode; + + // parse the required threshold number + if (!fedpegscript.GetOp(it, opcode, vch)) return false; + t = CScript::DecodeOP_N(opcode); + if (t < 1 || t > MAX_PUBKEYS_PER_MULTISIG) return false; + + // support a fedpegscript like OP_TRUE if we're at the end of the script + if (it == fedpegscript.end()) return true; + + // count the pubkeys + int pubkeys = 0; + while (fedpegscript.GetOp(it, opcode, vch)) { + if (opcode != 0x21) break; + if (vch.size() != 33) return false; + pubkeys++; + } + + // parse the total number of pubkeys + n = CScript::DecodeOP_N(opcode); + if (n < 1 || n > MAX_PUBKEYS_PER_MULTISIG || n < t) return false; + if (pubkeys != n) return false; + + // the next opcode must be OP_CHECKMULTISIG + if (!fedpegscript.GetOp(it, opcode, vch)) return false; + + return opcode == OP_CHECKMULTISIG; +} diff --git a/src/dynafed.h b/src/dynafed.h index ea651631fb..373fdb2e97 100644 --- a/src/dynafed.h +++ b/src/dynafed.h @@ -15,5 +15,10 @@ DynaFedParamEntry ComputeNextBlockFullCurrentParameters(const CBlockIndex* pinde * publish signblockscript-related fields */ DynaFedParamEntry ComputeNextBlockCurrentParameters(const CBlockIndex* pindexPrev, const Consensus::Params& consensus); +/* Get the threshold (t) and maybe the total pubkeys (n) of the first OP_CHECKMULTISIG in the fedpegscript. + * Assumes the fedpegscript starts with the threshold, otherwise returns false. + * Uses CScript::DecodeOP_N, so only supports up to a threshold of 16, otherwise asserts. + * Supports a fedpegscript like OP_TRUE by returning early. */ +bool ParseFedPegQuorum(const CScript& fedpegscript, int& t, int& n); #endif // BITCOIN_DYNAFED_H diff --git a/src/init.cpp b/src/init.cpp index c777da00a6..bb8df15505 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -712,7 +712,7 @@ void SetupServerArgs(ArgsManager& argsman) argsman.AddArg("-mainchainrpcpassword=", "The rpc password which the daemon will use to connect to the trusted mainchain daemon to validate peg-ins, if enabled. (default: cookie auth)", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::ELEMENTS); argsman.AddArg("-mainchainrpccookiefile=", "The bitcoind cookie auth path which the daemon will use to connect to the trusted mainchain daemon to validate peg-ins. (default: `/regtest/.cookie`)", ArgsManager::ALLOW_ANY, OptionsCategory::ELEMENTS); argsman.AddArg("-mainchainrpctimeout=", strprintf("Timeout in seconds during mainchain RPC requests, or 0 for no timeout. (default: %d)", DEFAULT_HTTP_CLIENT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::ELEMENTS); - argsman.AddArg("-peginconfirmationdepth=", strprintf("Pegin claims must be this deep to be considered valid. (default: %d)", DEFAULT_PEGIN_CONFIRMATION_DEPTH), ArgsManager::ALLOW_ANY, OptionsCategory::ELEMENTS); + argsman.AddArg("-peginconfirmationdepth=", strprintf("Peg-in claims must be this deep to be considered valid. (default: %d)", DEFAULT_PEGIN_CONFIRMATION_DEPTH), ArgsManager::ALLOW_ANY, OptionsCategory::ELEMENTS); argsman.AddArg("-parentpubkeyprefix", strprintf("The byte prefix, in decimal, of the parent chain's base58 pubkey address. (default: %d)", 111), ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-parentscriptprefix", strprintf("The byte prefix, in decimal, of the parent chain's base58 script address. (default: %d)", 196), ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-parent_bech32_hrp", strprintf("The human-readable part of the parent chain's bech32 encoding. (default: %s)", "bc"), ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); @@ -725,6 +725,10 @@ void SetupServerArgs(ArgsManager& argsman) argsman.AddArg("-ct_exponent", strprintf("The hiding exponent. (default: %s)", 0), ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-acceptdiscountct", "Accept discounted fees for Confidential Transactions (default: 1 in liquidtestnet and liquidv1, 0 otherwise)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-creatediscountct", "Create Confidential Transactions with discounted fees (default: 0). Setting this to 1 will also set 'acceptdiscountct' to 1.", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-peginsubsidyheight", "The block height at which peg-in transactions must have a burn subsidy (default: not active). The subsidy is an OP_RETURN output, with its value equal to the feerate of the parent transaction multiplied by the vsize of spending the P2WSH output created by the peg-in (feerate * 396 sats for liquidv1). ", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-peginsubsidythreshold", "The output value below which peg-in transactions must have a burn subsidy (default: 0). Peg-ins above this value do not require the subsidy.", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-peginminheight", "The block height at which a minimum peg-in value is enforced (default: not active).", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); + argsman.AddArg("-peginminamount", "The minimum value for a peg-in transaction after peginminheight (default: unset).", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); // Add the hidden options argsman.AddHiddenArgs(hidden_args); @@ -2073,7 +2077,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) if (gArgs.GetBoolArg("-validatepegin", Params().GetConsensus().has_parent_chain)) { uiInterface.InitMessage(_("Awaiting mainchain RPC warmup").translated); if (!MainchainRPCCheck()) { - const std::string err_msg = "ERROR: elements is set to verify pegins but cannot get a valid response from the mainchain daemon. Please check debug.log for more information.\n\nIf you haven't setup a bitcoind please get the latest stable version from https://bitcoincore.org/en/download/ or if you do not need to validate pegins set in your elements configuration validatepegin=0"; + const std::string err_msg = "ERROR: elements is set to verify peg-ins but cannot get a valid response from the mainchain daemon. Please check debug.log for more information.\n\nIf you haven't setup a bitcoind please get the latest stable version from https://bitcoincore.org/en/download/ or if you do not need to validate peg-ins set in your elements configuration validatepegin=0"; // We fail immediately if this node has RPC server enabled if (gArgs.GetBoolArg("-server", false)) { InitError(Untranslated(err_msg)); @@ -2084,6 +2088,23 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) gArgs.SoftSetArg("-validatepegin", "0"); } } + // if we are validating peg-in subsidy or minimum then we require bitcoind >= v25 + if (Params().GetPeginSubsidy().IsDefined() || Params().GetPeginMinimum().IsDefined()) { + UniValue params(UniValue::VARR); + UniValue reply = CallMainChainRPC("getnetworkinfo", params); + if (reply["error"].isStr()) { + InitError(Untranslated(reply["error"].get_str())); + return false; + } else { + const int version = reply["result"]["version"].getInt(); + const std::string& subversion = reply["result"]["subversion"].get_str(); + if (version < 250000 && subversion.find("Satoshi") != std::string::npos) { + const std::string err = strprintf("ERROR: parent bitcoind must be version 25 or newer for peg-in subsidy/minimum validation. Found version: %s", version); + InitError(Untranslated(err)); + return false; + } + } + } } // Call ActivateBestChain every 30 seconds. This is almost always a diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp index c6113596ac..35500905df 100644 --- a/src/kernel/chainparams.cpp +++ b/src/kernel/chainparams.cpp @@ -22,6 +22,7 @@ #include