Skip to content

Commit 9e5aaef

Browse files
committed
Merge 7791d31 into merged_master (Elements PR ElementsProject#1499)
2 parents 655e5c1 + 7791d31 commit 9e5aaef

13 files changed

Lines changed: 1391 additions & 25 deletions

File tree

src/chainparams.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
#include <chainparamsbase.h>
1313
#include <common/args.h>
1414
#include <consensus/params.h>
15+
#include <crypto/sha256.h>
1516
#include <deploymentinfo.h>
1617
#include <issuance.h>
1718
#include <primitives/transaction.h>
1819
#include <logging.h>
1920
#include <tinyformat.h>
2021
#include <util/chaintype.h>
22+
#include <util/moneystr.h>
2123
#include <util/strencodings.h>
2224
#include <util/string.h>
2325
#include <crypto/sha256.h>

src/dynafed.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,34 @@ DynaFedParamEntry ComputeNextBlockCurrentParameters(const CBlockIndex* pindexPre
123123
}
124124
}
125125

126+
bool ParseFedPegQuorum(const CScript& fedpegscript, int& t, int& n) {
127+
CScript::const_iterator it = fedpegscript.begin();
128+
std::vector<unsigned char> vch;
129+
opcodetype opcode;
130+
131+
// parse the required threshold number
132+
if (!fedpegscript.GetOp(it, opcode, vch)) return false;
133+
t = CScript::DecodeOP_N(opcode);
134+
if (t < 1 || t > MAX_PUBKEYS_PER_MULTISIG) return false;
135+
136+
// support a fedpegscript like OP_TRUE if we're at the end of the script
137+
if (it == fedpegscript.end()) return true;
138+
139+
// count the pubkeys
140+
int pubkeys = 0;
141+
while (fedpegscript.GetOp(it, opcode, vch)) {
142+
if (opcode != 0x21) break;
143+
if (vch.size() != 33) return false;
144+
pubkeys++;
145+
}
146+
147+
// parse the total number of pubkeys
148+
n = CScript::DecodeOP_N(opcode);
149+
if (n < 1 || n > MAX_PUBKEYS_PER_MULTISIG || n < t) return false;
150+
if (pubkeys != n) return false;
151+
152+
// the next opcode must be OP_CHECKMULTISIG
153+
if (!fedpegscript.GetOp(it, opcode, vch)) return false;
154+
155+
return opcode == OP_CHECKMULTISIG;
156+
}

src/dynafed.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,10 @@ DynaFedParamEntry ComputeNextBlockFullCurrentParameters(const CBlockIndex* pinde
1515
* publish signblockscript-related fields */
1616
DynaFedParamEntry ComputeNextBlockCurrentParameters(const CBlockIndex* pindexPrev, const Consensus::Params& consensus);
1717

18+
/* Get the threshold (t) and maybe the total pubkeys (n) of the first OP_CHECKMULTISIG in the fedpegscript.
19+
* Assumes the fedpegscript starts with the threshold, otherwise returns false.
20+
* Uses CScript::DecodeOP_N, so only supports up to a threshold of 16, otherwise asserts.
21+
* Supports a fedpegscript like OP_TRUE by returning early. */
22+
bool ParseFedPegQuorum(const CScript& fedpegscript, int& t, int& n);
1823

1924
#endif // BITCOIN_DYNAFED_H

src/init.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ void SetupServerArgs(ArgsManager& argsman)
712712
argsman.AddArg("-mainchainrpcpassword=<pwd>", "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);
713713
argsman.AddArg("-mainchainrpccookiefile=<file>", "The bitcoind cookie auth path which the daemon will use to connect to the trusted mainchain daemon to validate peg-ins. (default: `<datadir>/regtest/.cookie`)", ArgsManager::ALLOW_ANY, OptionsCategory::ELEMENTS);
714714
argsman.AddArg("-mainchainrpctimeout=<n>", strprintf("Timeout in seconds during mainchain RPC requests, or 0 for no timeout. (default: %d)", DEFAULT_HTTP_CLIENT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::ELEMENTS);
715-
argsman.AddArg("-peginconfirmationdepth=<n>", strprintf("Pegin claims must be this deep to be considered valid. (default: %d)", DEFAULT_PEGIN_CONFIRMATION_DEPTH), ArgsManager::ALLOW_ANY, OptionsCategory::ELEMENTS);
715+
argsman.AddArg("-peginconfirmationdepth=<n>", strprintf("Peg-in claims must be this deep to be considered valid. (default: %d)", DEFAULT_PEGIN_CONFIRMATION_DEPTH), ArgsManager::ALLOW_ANY, OptionsCategory::ELEMENTS);
716716
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);
717717
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);
718718
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)
725725
argsman.AddArg("-ct_exponent", strprintf("The hiding exponent. (default: %s)", 0), ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
726726
argsman.AddArg("-acceptdiscountct", "Accept discounted fees for Confidential Transactions (default: 1 in liquidtestnet and liquidv1, 0 otherwise)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
727727
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);
728+
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);
729+
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);
730+
argsman.AddArg("-peginminheight", "The block height at which a minimum peg-in value is enforced (default: not active).", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
731+
argsman.AddArg("-peginminamount", "The minimum value for a peg-in transaction after peginminheight (default: unset).", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
728732

729733
// Add the hidden options
730734
argsman.AddHiddenArgs(hidden_args);
@@ -2073,7 +2077,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
20732077
if (gArgs.GetBoolArg("-validatepegin", Params().GetConsensus().has_parent_chain)) {
20742078
uiInterface.InitMessage(_("Awaiting mainchain RPC warmup").translated);
20752079
if (!MainchainRPCCheck()) {
2076-
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";
2080+
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";
20772081
// We fail immediately if this node has RPC server enabled
20782082
if (gArgs.GetBoolArg("-server", false)) {
20792083
InitError(Untranslated(err_msg));
@@ -2084,6 +2088,23 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
20842088
gArgs.SoftSetArg("-validatepegin", "0");
20852089
}
20862090
}
2091+
// if we are validating peg-in subsidy or minimum then we require bitcoind >= v25
2092+
if (Params().GetPeginSubsidy().IsDefined() || Params().GetPeginMinimum().IsDefined()) {
2093+
UniValue params(UniValue::VARR);
2094+
UniValue reply = CallMainChainRPC("getnetworkinfo", params);
2095+
if (reply["error"].isStr()) {
2096+
InitError(Untranslated(reply["error"].get_str()));
2097+
return false;
2098+
} else {
2099+
const int version = reply["result"]["version"].getInt<int>();
2100+
const std::string& subversion = reply["result"]["subversion"].get_str();
2101+
if (version < 250000 && subversion.find("Satoshi") != std::string::npos) {
2102+
const std::string err = strprintf("ERROR: parent bitcoind must be version 25 or newer for peg-in subsidy/minimum validation. Found version: %s", version);
2103+
InitError(Untranslated(err));
2104+
return false;
2105+
}
2106+
}
2107+
}
20872108
}
20882109

20892110
// Call ActivateBestChain every 30 seconds. This is almost always a

src/kernel/chainparams.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <script/script.h>
2323
#include <uint256.h>
2424
#include <util/chaintype.h>
25+
#include <util/moneystr.h>
2526
#include <util/strencodings.h>
2627
#include <issuance.h>
2728
#include <deploymentinfo.h>
@@ -249,6 +250,8 @@ class CMainParams : public CChainParams {
249250
multi_data_permitted = false;
250251
accept_discount_ct = false;
251252
create_discount_ct = false;
253+
pegin_subsidy = PeginSubsidy();
254+
pegin_minimum = PeginMinimum();
252255
consensus.has_parent_chain = false;
253256
g_signed_blocks = false;
254257
g_con_elementsmode = false;
@@ -394,6 +397,8 @@ class CTestNetParams : public CChainParams {
394397
multi_data_permitted = false;
395398
accept_discount_ct = false;
396399
create_discount_ct = false;
400+
pegin_subsidy = PeginSubsidy();
401+
pegin_minimum = PeginMinimum();
397402
consensus.has_parent_chain = false;
398403
g_signed_blocks = false;
399404
g_con_elementsmode = false;
@@ -557,6 +562,8 @@ class SigNetParams : public CChainParams {
557562
multi_data_permitted = false;
558563
accept_discount_ct = false;
559564
create_discount_ct = false;
565+
pegin_subsidy = PeginSubsidy();
566+
pegin_minimum = PeginMinimum();
560567
consensus.has_parent_chain = false;
561568
g_signed_blocks = false; // lol
562569
g_con_elementsmode = false;
@@ -669,6 +676,8 @@ class CRegTestParams : public CChainParams
669676
multi_data_permitted = false;
670677
accept_discount_ct = false;
671678
create_discount_ct = false;
679+
pegin_subsidy = PeginSubsidy();
680+
pegin_minimum = PeginMinimum();
672681
consensus.has_parent_chain = false;
673682
g_signed_blocks = false;
674683
g_con_elementsmode = false;
@@ -837,6 +846,38 @@ void UpdateActivationParametersFromArgs(const ArgsManager& args, Consensus::Par
837846
}
838847
}
839848
}
849+
// ELEMENTS
850+
PeginSubsidy ParsePeginSubsidy(const ArgsManager& args) {
851+
PeginSubsidy pegin_subsidy;
852+
853+
pegin_subsidy.height = args.GetIntArg("-peginsubsidyheight", std::numeric_limits<int>::max());
854+
if (pegin_subsidy.height < 0) {
855+
throw std::runtime_error(strprintf("Invalid block height (%d) for -peginsubsidyheight. Must be positive.", pegin_subsidy.height));
856+
}
857+
if (std::optional<CAmount> amount = ParseMoney(args.GetArg("-peginsubsidythreshold", "0"))) {
858+
pegin_subsidy.threshold = amount.value();
859+
} else {
860+
throw std::runtime_error("Invalid -peginsubsidythreshold");
861+
}
862+
863+
return pegin_subsidy;
864+
};
865+
866+
PeginMinimum ParsePeginMinimum(const ArgsManager& args) {
867+
PeginMinimum pegin_minimum;
868+
869+
pegin_minimum.height = args.GetIntArg("-peginminheight", std::numeric_limits<int>::max());
870+
if (pegin_minimum.height < 0) {
871+
throw std::runtime_error(strprintf("Invalid block height (%d) for -peginminheight. Must be positive.", pegin_minimum.height));
872+
}
873+
if (std::optional<CAmount> amount = ParseMoney(args.GetArg("-peginminamount", "0"))) {
874+
pegin_minimum.amount = amount.value();
875+
} else {
876+
throw std::runtime_error("Invalid -peginminamount");
877+
}
878+
879+
return pegin_minimum;
880+
};
840881

841882
/**
842883
* Custom params for testing.
@@ -976,6 +1017,11 @@ class CCustomParams : public CRegTestParams {
9761017
consensus.start_p2wsh_script = args.GetIntArg("-con_start_p2wsh_script", consensus.start_p2wsh_script);
9771018
create_discount_ct = args.GetBoolArg("-creatediscountct", create_discount_ct);
9781019
accept_discount_ct = args.GetBoolArg("-acceptdiscountct", accept_discount_ct) || create_discount_ct;
1020+
pegin_subsidy = ParsePeginSubsidy(args);
1021+
pegin_minimum = ParsePeginMinimum(args);
1022+
if (pegin_subsidy.threshold < pegin_minimum.amount) {
1023+
throw std::runtime_error(strprintf("Peg-in subsidy threshold (%s) must be greater than or equal to peg-in minimum amount (%s)", FormatMoney(pegin_subsidy.threshold), FormatMoney(pegin_minimum.amount)));
1024+
}
9791025

9801026
// Calculate pegged Bitcoin asset
9811027
std::vector<unsigned char> commit = CommitToArguments(consensus, m_chain_type.chain_name);
@@ -1219,6 +1265,11 @@ class CLiquidV1Params : public CChainParams {
12191265
multi_data_permitted = true;
12201266
create_discount_ct = args.GetBoolArg("-creatediscountct", false);
12211267
accept_discount_ct = args.GetBoolArg("-acceptdiscountct", true) || create_discount_ct;
1268+
pegin_subsidy = ParsePeginSubsidy(args);
1269+
pegin_minimum = ParsePeginMinimum(args);
1270+
if (pegin_subsidy.threshold < pegin_minimum.amount) {
1271+
throw std::runtime_error(strprintf("Peg-in subsidy threshold (%s) must be greater than or equal to peg-in minimum amount (%s)", FormatMoney(pegin_subsidy.threshold), FormatMoney(pegin_minimum.amount)));
1272+
}
12221273

12231274
parentGenesisBlockHash = uint256S("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
12241275
const bool parent_genesis_is_null = parentGenesisBlockHash == uint256();
@@ -1574,6 +1625,11 @@ class CLiquidV1TestParams : public CLiquidV1Params {
15741625
multi_data_permitted = args.GetBoolArg("-multi_data_permitted", multi_data_permitted);
15751626
create_discount_ct = args.GetBoolArg("-creatediscountct", create_discount_ct);
15761627
accept_discount_ct = args.GetBoolArg("-acceptdiscountct", accept_discount_ct) || create_discount_ct;
1628+
pegin_subsidy = ParsePeginSubsidy(args);
1629+
pegin_minimum = ParsePeginMinimum(args);
1630+
if (pegin_subsidy.threshold < pegin_minimum.amount) {
1631+
throw std::runtime_error(strprintf("Peg-in subsidy threshold (%s) must be greater than or equal to peg-in minimum amount (%s)", FormatMoney(pegin_subsidy.threshold), FormatMoney(pegin_minimum.amount)));
1632+
}
15771633

15781634
if (args.IsArgSet("-parentgenesisblockhash")) {
15791635
parentGenesisBlockHash = uint256S(args.GetArg("-parentgenesisblockhash", ""));

src/kernel/chainparams.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,27 @@ struct ChainTxData {
7878
double dTxRate; //!< estimated number of transactions per second after that timestamp
7979
};
8080

81+
// ELEMENTS
82+
struct PeginSubsidy {
83+
int height{std::numeric_limits<int>::max()};
84+
CAmount threshold{0};
85+
86+
PeginSubsidy() {};
87+
bool IsDefined() {
88+
return threshold > 0 || height < std::numeric_limits<int>::max();
89+
};
90+
};
91+
92+
struct PeginMinimum {
93+
int height{std::numeric_limits<int>::max()};
94+
CAmount amount{0};
95+
96+
PeginMinimum() {};
97+
bool IsDefined() {
98+
return amount > 0 || height < std::numeric_limits<int>::max();
99+
};
100+
};
101+
81102
/**
82103
* CChainParams defines various tweakable parameters of a given instance of the
83104
* Bitcoin system.
@@ -150,6 +171,8 @@ class CChainParams
150171
bool GetMultiDataPermitted() const { return multi_data_permitted; }
151172
bool GetAcceptDiscountCT() const { return accept_discount_ct; }
152173
bool GetCreateDiscountCT() const { return create_discount_ct; }
174+
PeginSubsidy GetPeginSubsidy() const { return pegin_subsidy; }
175+
PeginMinimum GetPeginMinimum() const { return pegin_minimum; }
153176

154177
/**
155178
* SigNetOptions holds configurations for creating a signet CChainParams.
@@ -218,6 +241,8 @@ class CChainParams
218241
bool multi_data_permitted;
219242
bool accept_discount_ct;
220243
bool create_discount_ct;
244+
PeginSubsidy pegin_subsidy;
245+
PeginMinimum pegin_minimum;
221246
};
222247

223248
#endif // BITCOIN_KERNEL_CHAINPARAMS_H

src/rpc/blockchain.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <univalue.h>
4242
#include <util/check.h>
4343
#include <util/fs.h>
44+
#include <util/moneystr.h>
4445
#include <util/strencodings.h>
4546
#include <util/translation.h>
4647
#include <validation.h>
@@ -3183,6 +3184,25 @@ static RPCHelpMan getsidechaininfo()
31833184
obj.pushKV("parent_chain_signblockscript_hex", HexStr(consensus.parent_chain_signblockscript));
31843185
obj.pushKV("parent_pegged_asset", consensus.parent_pegged_asset.GetHex());
31853186
}
3187+
3188+
PeginMinimum pegin_minimum = Params().GetPeginMinimum();
3189+
if (pegin_minimum.amount > 0) {
3190+
obj.pushKV("pegin_min_amount", FormatMoney(pegin_minimum.amount));
3191+
}
3192+
if (pegin_minimum.height < std::numeric_limits<int>::max()) {
3193+
obj.pushKV("pegin_min_height", pegin_minimum.height);
3194+
obj.pushKV("pegin_min_active", chainman.ActiveTip()->nHeight >= pegin_minimum.height);
3195+
}
3196+
3197+
PeginSubsidy pegin_subsidy = Params().GetPeginSubsidy();
3198+
if (pegin_subsidy.threshold > 0) {
3199+
obj.pushKV("pegin_subsidy_threshold", FormatMoney(pegin_subsidy.threshold));
3200+
}
3201+
if (pegin_subsidy.height < std::numeric_limits<int>::max()) {
3202+
obj.pushKV("pegin_subsidy_height", pegin_subsidy.height);
3203+
obj.pushKV("pegin_subsidy_active", chainman.ActiveTip()->nHeight >= pegin_subsidy.height);
3204+
}
3205+
31863206
return obj;
31873207
},
31883208
};

src/rpc/client.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
342342
{ "calculateasset", 3, "blind_reissuance" },
343343
{ "updatepsbtpegin", 1, "input" },
344344
{ "updatepsbtpegin", 2, "value" },
345+
{ "claimpegin", 3, "fee_rate" },
346+
{ "createrawpegin", 3, "fee_rate" },
345347

346348
};
347349
// clang-format on

src/test/dynafed_tests.cpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5-
#include <test/util/setup_common.h>
6-
#include <string>
75
#include <boost/test/unit_test.hpp>
6+
#include <dynafed.h>
87
#include <primitives/block.h>
98
#include <script/script.h>
109
#include <serialize.h>
10+
#include <string>
11+
#include <test/util/setup_common.h>
1112

1213

1314
BOOST_FIXTURE_TEST_SUITE(dynafed_tests, BasicTestingSetup)
@@ -41,6 +42,48 @@ BOOST_AUTO_TEST_CASE(dynafed_params_root)
4142
);
4243
}
4344

44-
BOOST_AUTO_TEST_SUITE_END()
45+
BOOST_AUTO_TEST_CASE(parse_fedpegscript_multisig)
46+
{
47+
int t = 0;
48+
int n = 0;
49+
50+
auto simplebytes = ParseHex("512103dff4923d778550cc13ce0d887d737553b4b58f4e8e886507fc39f5e447b2186451ae");
51+
52+
CScript simple{simplebytes.begin(), simplebytes.end()};
53+
54+
BOOST_CHECK(ParseFedPegQuorum(simple, t, n));
55+
BOOST_CHECK_EQUAL(t, 1);
56+
BOOST_CHECK_EQUAL(n, 1);
57+
58+
auto liquidv1bytes = ParseHex("5b21020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b678172612102675333a4e4b8fb51d9d4e22fa5a8eaced3fdac8a8cbf9be8c030f75712e6af992102896807d54bc55c24981f24a453c60ad3e8993d693732288068a23df3d9f50d4821029e51a5ef5db3137051de8323b001749932f2ff0d34c82e96a2c2461de96ae56c2102a4e1a9638d46923272c266631d94d36bdb03a64ee0e14c7518e49d2f29bc401021031c41fdbcebe17bec8d49816e00ca1b5ac34766b91c9f2ac37d39c63e5e008afb2103079e252e85abffd3c401a69b087e590a9b86f33f574f08129ccbd3521ecf516b2103111cf405b627e22135b3b3733a4a34aa5723fb0f58379a16d32861bf576b0ec2210318f331b3e5d38156da6633b31929c5b220349859cc9ca3d33fb4e68aa08401742103230dae6b4ac93480aeab26d000841298e3b8f6157028e47b0897c1e025165de121035abff4281ff00660f99ab27bb53e6b33689c2cd8dcd364bc3c90ca5aea0d71a62103bd45cddfacf2083b14310ae4a84e25de61e451637346325222747b157446614c2103cc297026b06c71cbfa52089149157b5ff23de027ac5ab781800a578192d175462103d3bde5d63bdb3a6379b461be64dad45eabff42f758543a9645afd42f6d4248282103ed1e8d5109c9ed66f7941bc53cc71137baa76d50d274bda8d5e8ffbd6e61fe9a5fae736402c00fb269522103aab896d53a8e7d6433137bbba940f9c521e085dd07e60994579b64a6d992cf79210291b7d0b1b692f8f524516ed950872e5da10fb1b808b5a526dedc6fed1cf29807210386aa9372fbab374593466bc5451dc59954e90787f08060964d95c87ef34ca5bb53ae68");
4559

60+
CScript liquidv1{liquidv1bytes.begin(), liquidv1bytes.end()};
4661

62+
t = 0;
63+
n = 0;
64+
BOOST_CHECK(ParseFedPegQuorum(liquidv1, t, n));
65+
BOOST_CHECK_EQUAL(t, 11);
66+
BOOST_CHECK_EQUAL(n, 15);
67+
68+
auto optruebytes = ParseHex("51");
69+
70+
CScript optrue{optruebytes.begin(), optruebytes.end()};
71+
72+
t = 0;
73+
n = 0;
74+
BOOST_CHECK(ParseFedPegQuorum(optrue, t, n));
75+
BOOST_CHECK_EQUAL(t, 1);
76+
BOOST_CHECK_EQUAL(n, 0);
77+
78+
auto op3bytes = ParseHex("53");
79+
80+
CScript op3{op3bytes.begin(), op3bytes.end()};
81+
82+
t = 0;
83+
n = 0;
84+
BOOST_CHECK(ParseFedPegQuorum(op3, t, n));
85+
BOOST_CHECK_EQUAL(t, 3);
86+
BOOST_CHECK_EQUAL(n, 0);
87+
}
88+
89+
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)