Skip to content

Commit bd11097

Browse files
committed
Add fedpeg_program field in dynafed header
1 parent 4ad2b80 commit bd11097

File tree

14 files changed

+75
-46
lines changed

14 files changed

+75
-46
lines changed

src/consensus/tx_verify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe
243243
}
244244

245245
namespace Consensus {
246-
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<CScript>& fedpegscripts)
246+
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<std::pair<CScript, CScript>>& fedpegscripts)
247247
{
248248
// are the actual inputs available?
249249
if (!inputs.HaveInputs(tx)) {

src/consensus/tx_verify.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace Consensus {
3131
* @param[out] fee_map Set to the transaction fee if successful.
3232
* Preconditions: tx.IsCoinBase() is false.
3333
*/
34-
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<CScript>& fedpegscripts);
34+
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<std::pair<CScript, CScript>>& fedpegscripts);
3535
} // namespace Consensus
3636

3737
/** Auxiliary functions for transaction validation (ideally should not be exposed) */

src/dynafed.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ DynaFedParamEntry ComputeNextBlockFullCurrentParameters(const CBlockIndex* pinde
6060
// We need to construct the "full" current parameters of pre-dynafed
6161
// consensus
6262

63-
// Convert signblockscript to P2WSH
63+
// Convert signblockscript to P2WSH and fedpeg_program to P2SH-P2WSH
6464
CScript p2wsh_signblock_script = GetScriptForDestination(WitnessV0ScriptHash(p_epoch_start->proof.challenge));
65-
winning_proposal = DynaFedParamEntry(p2wsh_signblock_script, consensus.max_block_signature_size+consensus.signblockscript.size(), consensus.fedpegScript, consensus.first_extension_space);
65+
CScript sh_wsh_fedpeg_program = GetScriptForDestination(ScriptHash(GetScriptForDestination(WitnessV0ScriptHash(consensus.fedpegScript))));
66+
winning_proposal = DynaFedParamEntry(p2wsh_signblock_script, consensus.max_block_signature_size+consensus.signblockscript.size(), sh_wsh_fedpeg_program, consensus.fedpegScript, consensus.first_extension_space);
6667
} else {
6768
winning_proposal = p_epoch_start->dynafed_params.m_current;
6869
}

src/pegins.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ CScript calculate_contract(const CScript& federation_script, const CScript& scri
141141
}
142142

143143
template<typename T>
144-
static bool CheckPeginTx(const std::vector<unsigned char>& tx_data, T& pegtx, const COutPoint& prevout, const CAmount claim_amount, const CScript& claim_script, const std::vector<CScript>& fedpegscripts)
144+
static bool CheckPeginTx(const std::vector<unsigned char>& tx_data, T& pegtx, const COutPoint& prevout, const CAmount claim_amount, const CScript& claim_script, const std::vector<std::pair<CScript, CScript>>& fedpegscripts)
145145
{
146146
try {
147147
CDataStream pegtx_stream(tx_data, SER_NETWORK, PROTOCOL_VERSION);
@@ -171,12 +171,15 @@ static bool CheckPeginTx(const std::vector<unsigned char>& tx_data, T& pegtx, co
171171
return false;
172172
}
173173

174-
// Check that the witness program matches the p2ch on the p2sh-p2wsh transaction output
175-
// We support multiple scripts as a grace period for peg-in users
176-
for (const auto& fedpegscript : fedpegscripts) {
177-
CScript tweaked_fedpegscript = calculate_contract(fedpegscript, claim_script);
178-
CScript witness_output(GetScriptForWitness(tweaked_fedpegscript));
179-
CScript expected_script(CScript() << OP_HASH160 << ToByteVector(ScriptHash(CScriptID(witness_output))) << OP_EQUAL);
174+
// Check that the witness program matches the p2ch on the (p2sh-)p2wsh
175+
// transaction output. We support multiple scripts as a grace period for peg-in users
176+
for (const auto& scripts : fedpegscripts) {
177+
CScript tweaked_fedpegscript = calculate_contract(scripts.second, claim_script);
178+
// TODO: Remove script/standard.h dep for GetScriptFor*
179+
CScript expected_script(GetScriptForWitness(tweaked_fedpegscript));
180+
if (scripts.first.IsPayToScriptHash()) {
181+
expected_script = GetScriptForDestination(ScriptHash(expected_script));
182+
}
180183
if (pegtx->vout[prevout.n].scriptPubKey == expected_script) {
181184
return true;
182185
}
@@ -228,7 +231,7 @@ bool CheckParentProofOfWork(uint256 hash, unsigned int nBits, const Consensus::P
228231
return true;
229232
}
230233

231-
bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const std::vector<CScript>& fedpegscripts, const COutPoint& prevout, std::string& err_msg, bool check_depth) {
234+
bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const std::vector<std::pair<CScript, CScript>>& fedpegscripts, const COutPoint& prevout, std::string& err_msg, bool check_depth) {
232235
// 0) Return false if !consensus.has_parent_chain
233236
if (!Params().GetConsensus().has_parent_chain) {
234237
err_msg = "Parent chain is not enabled on this network.";
@@ -447,11 +450,11 @@ bool MatchLiquidWatchman(const CScript& script)
447450
return (it == script.end());
448451
}
449452

450-
std::vector<CScript> GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation)
453+
std::vector<std::pair<CScript, CScript>> GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation)
451454
{
452455
assert(pblockindex);
453456

454-
std::vector<CScript> fedpegscripts;
457+
std::vector<std::pair<CScript, CScript>> fedpegscripts;
455458

456459
const int32_t epoch_length = params.dynamic_epoch_length;
457460
const int32_t epoch_age = pblockindex->nHeight % epoch_length;
@@ -460,7 +463,8 @@ std::vector<CScript> GetValidFedpegScripts(const CBlockIndex* pblockindex, const
460463
// In mempool and general "enforced next block" RPC we need to look ahead one block
461464
// to see if we're on a boundary. If so, put that epoch's fedpegscript in place
462465
if (nextblock_validation && epoch_age == epoch_length - 1) {
463-
fedpegscripts.push_back(ComputeNextBlockFullCurrentParameters(pblockindex, params).m_fedpegscript);
466+
DynaFedParamEntry next_param = ComputeNextBlockFullCurrentParameters(pblockindex, params);
467+
fedpegscripts.push_back(std::make_pair(next_param.m_fedpeg_program, next_param.m_fedpegscript));
464468
}
465469

466470
// Next we walk backwards up to two epoch start blocks
@@ -469,17 +473,17 @@ std::vector<CScript> GetValidFedpegScripts(const CBlockIndex* pblockindex, const
469473

470474
if (p_current_epoch_start) {
471475
if (!p_current_epoch_start->dynafed_params.IsNull()) {
472-
fedpegscripts.push_back(p_current_epoch_start->dynafed_params.m_current.m_fedpegscript);
476+
fedpegscripts.push_back(std::make_pair(p_current_epoch_start->dynafed_params.m_current.m_fedpeg_program, p_current_epoch_start->dynafed_params.m_current.m_fedpegscript));
473477
} else {
474-
fedpegscripts.push_back(params.fedpegScript);
478+
fedpegscripts.push_back(std::make_pair(GetScriptForDestination(ScriptHash(GetScriptForDestination(WitnessV0ScriptHash(params.fedpegScript)))), params.fedpegScript));
475479
}
476480
}
477481

478482
if (p_prev_epoch_start) {
479483
if (!p_prev_epoch_start->dynafed_params.IsNull()) {
480-
fedpegscripts.push_back(p_prev_epoch_start->dynafed_params.m_current.m_fedpegscript);
484+
fedpegscripts.push_back(std::make_pair(p_prev_epoch_start->dynafed_params.m_current.m_fedpeg_program, p_prev_epoch_start->dynafed_params.m_current.m_fedpegscript));
481485
} else {
482-
fedpegscripts.push_back(params.fedpegScript);
486+
fedpegscripts.push_back(std::make_pair(GetScriptForDestination(ScriptHash(GetScriptForDestination(WitnessV0ScriptHash(params.fedpegScript)))), params.fedpegScript));
483487
}
484488
}
485489

src/pegins.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ bool GetAmountFromParentChainPegin(CAmount& amount, const CTransaction& txBTC, u
1919
/** Check whether a parent chain block hash satisfies the proof-of-work requirement specified by nBits */
2020
bool CheckParentProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
2121
/** Checks pegin witness for validity */
22-
bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const std::vector<CScript>& fedpegscripts, const COutPoint& prevout, std::string& err_msg, bool check_depth);
22+
bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const std::vector<std::pair<CScript, CScript>>& fedpegscripts, const COutPoint& prevout, std::string& err_msg, bool check_depth);
2323
// Constructs unblinded output to be used in amount and scriptpubkey checks during pegin
2424
CTxOut GetPeginOutputFromWitness(const CScriptWitness& pegin_witness);
2525

@@ -34,7 +34,8 @@ bool MatchLiquidWatchman(const CScript& script);
3434

3535
/** Get full fedpegscripts from two previous epoch starts based on given index
3636
* nextblock_validation is false when doing block validation, true for mempool
37-
* or "lookahead" purposes. Newest epochs first. */
38-
std::vector<CScript> GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation);
37+
* or "lookahead" purposes. Newest epochs first. The first returned element is the
38+
* scriptPubKey for the script, the second is the witnessScript. */
39+
std::vector<std::pair<CScript, CScript>> GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation);
3940

4041
#endif // BITCOIN_PEGINS_H

src/primitives/block.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ uint256 DynaFedParamEntry::CalculateRoot() const
5050
std::vector<uint256> leaves;
5151
leaves.push_back(SerializeHash(m_signblockscript, SER_GETHASH, 0));
5252
leaves.push_back(SerializeHash(m_signblock_witness_limit, SER_GETHASH, 0));
53+
leaves.push_back(SerializeHash(m_fedpeg_program, SER_GETHASH, 0));
5354
leaves.push_back(SerializeHash(m_fedpegscript, SER_GETHASH, 0));
5455
leaves.push_back(SerializeHash(m_extension_space, SER_GETHASH, 0));
5556
return ComputeFastMerkleRoot(leaves);

src/primitives/block.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,16 @@ class DynaFedParamEntry
6161
unsigned char m_serialize_type; // Determines how it is serialized, defaults to null
6262
CScript m_signblockscript;
6363
uint32_t m_signblock_witness_limit; // Max block signature witness serialized size
64-
CScript m_fedpegscript;
64+
CScript m_fedpeg_program; // The "scriptPubKey" of the fedpegscript
65+
CScript m_fedpegscript; // The witnessScript for witness v0 or undefined otherwise.
6566
// No consensus meaning to the particular bytes, currently we interpret as PAK keys, details in pak.h
6667
std::vector<std::vector<unsigned char>> m_extension_space;
6768

6869
// Each constructor sets its own serialization type implicitly based on which
6970
// arguments are given
7071
DynaFedParamEntry() { m_signblock_witness_limit = 0; m_serialize_type = 0; };
7172
DynaFedParamEntry(const CScript& signblockscript_in, const uint32_t sbs_wit_limit_in) : m_signblockscript(signblockscript_in), m_signblock_witness_limit(sbs_wit_limit_in) { m_serialize_type = 1; };
72-
DynaFedParamEntry(const CScript& signblockscript_in, const uint32_t sbs_wit_limit_in, const CScript& fedpegscript_in, const std::vector<std::vector<unsigned char>> extension_space_in) : m_signblockscript(signblockscript_in), m_signblock_witness_limit(sbs_wit_limit_in), m_fedpegscript(fedpegscript_in), m_extension_space(extension_space_in) { m_serialize_type = 2; };
73+
DynaFedParamEntry(const CScript& signblockscript_in, const uint32_t sbs_wit_limit_in, const CScript& fedpeg_program_in, const CScript& fedpegscript_in, const std::vector<std::vector<unsigned char>> extension_space_in) : m_signblockscript(signblockscript_in), m_signblock_witness_limit(sbs_wit_limit_in), m_fedpeg_program(fedpeg_program_in), m_fedpegscript(fedpegscript_in), m_extension_space(extension_space_in) { m_serialize_type = 2; };
7374

7475
ADD_SERIALIZE_METHODS;
7576

@@ -87,6 +88,7 @@ class DynaFedParamEntry
8788
case 2:
8889
READWRITE(m_signblockscript);
8990
READWRITE(m_signblock_witness_limit);
91+
READWRITE(m_fedpeg_program);
9092
READWRITE(m_fedpegscript);
9193
READWRITE(m_extension_space);
9294
break;
@@ -102,6 +104,7 @@ class DynaFedParamEntry
102104
return m_serialize_type == 0 &&
103105
m_signblockscript.empty() &&
104106
m_signblock_witness_limit == 0 &&
107+
m_fedpeg_program.empty() &&
105108
m_fedpegscript.empty() &&
106109
m_extension_space.empty();
107110

@@ -110,9 +113,10 @@ class DynaFedParamEntry
110113
void SetNull()
111114
{
112115
m_serialize_type = 0;
113-
m_signblockscript = CScript();
116+
m_signblockscript.clear();
114117
m_signblock_witness_limit = 0;
115-
m_fedpegscript = CScript();
118+
m_fedpeg_program.clear();
119+
m_fedpegscript.clear();
116120
m_extension_space.clear();
117121
}
118122

@@ -121,6 +125,7 @@ class DynaFedParamEntry
121125
return m_serialize_type == other.m_serialize_type &&
122126
m_signblockscript == other.m_signblockscript &&
123127
m_signblock_witness_limit == other.m_signblock_witness_limit &&
128+
m_fedpeg_program == other.m_fedpeg_program &&
124129
m_fedpegscript == other.m_fedpegscript &&
125130
m_extension_space == other.m_extension_space;
126131
}

src/rpc/blockchain.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2509,6 +2509,11 @@ UniValue getsidechaininfo(const JSONRPCRequest& request)
25092509
" \"xxxx\", (string) Hex-encoded active fedpegscript\n"
25102510
" ...\n"
25112511
" ]\n"
2512+
" \"current_fedpeg_programs\": (array) The currently-enforced fedpegscript scriptPubKeys in hex. Prior to a transition this may be P2SH scriptpubkey, otherwise it will be a native segwit script. Results are paired in-order with current_fedpegscripts.\n"
2513+
" [\n"
2514+
" \"xxxx\", (string) Hex-encoded active fedpegscriptscriptPubKeys\n"
2515+
" ...\n"
2516+
" ]\n"
25122517
" \"pegged_asset\" : \"xxxx\", (string) Pegged asset type in hex\n"
25132518
" \"min_peg_diff\" : \"xxxx\", (string) The minimum difficulty parent chain header target. Peg-in headers that have less work will be rejected as an anti-Dos measure.\n"
25142519
" \"parent_blockhash\" : \"xxxx\", (string) The parent genesis blockhash as source of pegged-in funds.\n"
@@ -2534,11 +2539,14 @@ UniValue getsidechaininfo(const JSONRPCRequest& request)
25342539
UniValue obj(UniValue::VOBJ);
25352540
obj.pushKV("fedpegscript", HexStr(consensus.fedpegScript.begin(), consensus.fedpegScript.end()));
25362541
// We use mempool_validation as true to show what is enforced for *next* block
2537-
std::vector<CScript> fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), consensus, true /* nextblock_validation */);
2542+
std::vector<std::pair<CScript, CScript>> fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), consensus, true /* nextblock_validation */);
2543+
UniValue fedpeg_prog_entries(UniValue::VARR);
25382544
UniValue fedpeg_entries(UniValue::VARR);
2539-
for (const auto& script : fedpegscripts) {
2540-
fedpeg_entries.push_back(HexStr(script));
2545+
for (const auto& scripts : fedpegscripts) {
2546+
fedpeg_prog_entries.push_back(HexStr(scripts.first));
2547+
fedpeg_entries.push_back(HexStr(scripts.second));
25412548
}
2549+
obj.pushKV("current_fedpeg_programs", fedpeg_prog_entries);
25422550
obj.pushKV("current_fedpegscripts", fedpeg_entries);
25432551
obj.pushKV("pegged_asset", consensus.pegged_asset.GetHex());
25442552
obj.pushKV("min_peg_diff", consensus.parentChainPowLimit.GetHex());

src/rpc/rawtransaction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con
988988
// Script verification errors
989989
UniValue vErrors(UniValue::VARR);
990990

991-
const std::vector<CScript> fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), Params().GetConsensus(), true /* nextblock_validation */);
991+
const auto& fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), Params().GetConsensus(), true /* nextblock_validation */);
992992

993993
// ELEMENTS:
994994
// Track an immature peg-in that's otherwise valid, give warning

src/test/coins_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
#include <boost/test/unit_test.hpp>
1919

20-
int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out, const CTxIn& txin, const CScriptWitness& pegin_witness, const std::vector<CScript>& fedpegscripts);
20+
int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out, const CTxIn& txin, const CScriptWitness& pegin_witness, const std::vector<std::pair<CScript, CScript>>& fedpegscripts);
2121
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight);
2222

2323
namespace
@@ -410,7 +410,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
410410
if (!tx.IsCoinBase()) {
411411
const COutPoint &out = tx.vin[0].prevout;
412412
Coin coin = undo.vprevout[0];
413-
std::vector<CScript> fedpegscripts;
413+
std::vector<std::pair<CScript, CScript>> fedpegscripts;
414414
ApplyTxInUndo(std::move(coin), *(stack.back()), out, tx.vin[0], CScriptWitness(), fedpegscripts);
415415
}
416416
// Store as a candidate for reconnection

0 commit comments

Comments
 (0)