Skip to content

Commit c8502bf

Browse files
committed
[Consensus] Guard P2CS change with contextual flag g_IsV6Active
1 parent 74bc415 commit c8502bf

File tree

5 files changed

+56
-27
lines changed

5 files changed

+56
-27
lines changed

src/script/interpreter.cpp

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -962,22 +962,24 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
962962

963963
case OP_CHECKCOLDSTAKEVERIFY:
964964
{
965-
// the stack can contain only <sig> <pk> <pkh> at this point
966-
if ((int)stack.size() != 3) {
967-
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
968-
}
969-
// check pubkey/signature encoding
970-
valtype& vchSig = stacktop(-3);
971-
valtype& vchPubKey = stacktop(-2);
972-
if (!CheckSignatureEncoding(vchSig, flags, serror) ||
973-
!CheckPubKeyEncoding(vchPubKey, flags, serror)) {
974-
// serror is set
975-
return false;
976-
}
977-
// check hash size
978-
valtype& vchPubKeyHash = stacktop(-1);
979-
if ((int)vchPubKeyHash.size() != 20) {
980-
return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE);
965+
if (g_IsV6Active) {
966+
// the stack can contain only <sig> <pk> <pkh> at this point
967+
if ((int)stack.size() != 3) {
968+
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
969+
}
970+
// check pubkey/signature encoding
971+
valtype& vchSig = stacktop(-3);
972+
valtype& vchPubKey = stacktop(-2);
973+
if (!CheckSignatureEncoding(vchSig, flags, serror) ||
974+
!CheckPubKeyEncoding(vchPubKey, flags, serror)) {
975+
// serror is set
976+
return false;
977+
}
978+
// check hash size
979+
valtype& vchPubKeyHash = stacktop(-1);
980+
if ((int)vchPubKeyHash.size() != 20) {
981+
return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE);
982+
}
981983
}
982984
if(!checker.CheckColdStake(script)) {
983985
return set_error(serror, SCRIPT_ERR_CHECKCOLDSTAKEVERIFY);

src/script/script.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include "tinyformat.h"
99
#include "utilstrencodings.h"
1010

11+
#include <atomic>
12+
1113

1214
const char* GetOpName(opcodetype opcode)
1315
{
@@ -223,18 +225,22 @@ bool CScript::IsPayToScriptHash() const
223225
(*this)[22] == OP_EQUAL);
224226
}
225227

228+
// contextual flag to guard the new rules for P2CS.
229+
// can be removed once v6 enforcement is activated.
230+
std::atomic<bool> g_IsV6Active{false};
231+
226232
bool CScript::IsPayToColdStaking() const
227233
{
228234
return (this->size() == 51 &&
229-
(*this)[0] == OP_DUP &&
230-
(*this)[1] == OP_HASH160 &&
235+
(!g_IsV6Active || (*this)[0] == OP_DUP) &&
236+
(!g_IsV6Active || (*this)[1] == OP_HASH160) &&
231237
(*this)[2] == OP_ROT &&
232-
(*this)[3] == OP_IF &&
238+
(!g_IsV6Active || (*this)[3] == OP_IF) &&
233239
(*this)[4] == OP_CHECKCOLDSTAKEVERIFY &&
234240
(*this)[5] == 0x14 &&
235-
(*this)[26] == OP_ELSE &&
241+
(!g_IsV6Active || (*this)[26] == OP_ELSE) &&
236242
(*this)[27] == 0x14 &&
237-
(*this)[48] == OP_ENDIF &&
243+
(!g_IsV6Active || (*this)[48] == OP_ENDIF) &&
238244
(*this)[49] == OP_EQUALVERIFY &&
239245
(*this)[50] == OP_CHECKSIG);
240246
}

src/script/script.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,4 +661,8 @@ class CScript : public CScriptBase
661661
size_t DynamicMemoryUsage() const;
662662
};
663663

664+
// contextual flag to guard the new rules for P2CS.
665+
// can be removed once v6 enforcement is activated.
666+
extern std::atomic<bool> g_IsV6Active;
667+
664668
#endif // BITCOIN_SCRIPT_SCRIPT_H

src/test/script_P2CS_tests.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,10 @@ static void setupWallet(CWallet& wallet)
232232
wallet.SetupSPKM(false);
233233
}
234234

235-
/* !TODO: check before/after v6 enforcement
236235
BOOST_AUTO_TEST_CASE(fake_script_test)
237236
{
237+
BOOST_ASSERT(!g_IsV6Active);
238+
238239
CWallet& wallet = *pwalletMain;
239240
LOCK(wallet.cs_wallet);
240241
setupWallet(wallet);
@@ -250,17 +251,21 @@ BOOST_AUTO_TEST_CASE(fake_script_test)
250251
const CScript& scriptP2CS = GetFakeLockingScript(stakerId, ownerId);
251252

252253
// Create prev transaction:
254+
// It has two outputs. The first one is spent before v6.
255+
// The second one is tested after v6 enforcement.
253256
CMutableTransaction txFrom;
254-
txFrom.vout.resize(1);
255-
txFrom.vout[0].nValue = amtIn;
256-
txFrom.vout[0].scriptPubKey = scriptP2CS;
257+
txFrom.vout.resize(2);
258+
for (size_t i = 0; i < 2; i++) {
259+
txFrom.vout[i].nValue = amtIn;
260+
txFrom.vout[i].scriptPubKey = scriptP2CS;
261+
}
257262

258263
// passes IsPayToColdStaking
259264
BOOST_CHECK(scriptP2CS.IsPayToColdStaking());
260265

261266
// the output amount is credited to the owner wallet
262267
wallet.AddToWallet({&wallet, MakeTransactionRef(CTransaction(txFrom))});
263-
BOOST_CHECK_EQUAL(wallet.GetWalletTx(txFrom.GetHash())->GetAvailableCredit(false, ISMINE_SPENDABLE_TRANSPARENT), amtIn);
268+
BOOST_CHECK_EQUAL(wallet.GetWalletTx(txFrom.GetHash())->GetAvailableCredit(false, ISMINE_SPENDABLE_TRANSPARENT), 2 * amtIn);
264269

265270
// create spend tx
266271
CMutableTransaction tx;
@@ -283,8 +288,16 @@ BOOST_AUTO_TEST_CASE(fake_script_test)
283288
BOOST_ERROR(strprintf("P2CS verification failed: %s", ScriptErrorString(err)));
284289
}
285290
wallet.AddToWallet({&wallet, MakeTransactionRef(CTransaction(tx))});
291+
BOOST_CHECK_EQUAL(wallet.GetWalletTx(txFrom.GetHash())->GetAvailableCredit(false, ISMINE_SPENDABLE_TRANSPARENT), amtIn);
292+
293+
// Now let's activate v6
294+
g_IsV6Active = true;
295+
296+
// it does NOT pass IsPayToColdStaking
297+
BOOST_CHECK_MESSAGE(!scriptP2CS.IsPayToColdStaking(), "Fake script passes as P2CS");
298+
299+
// the output amount is NOT credited to the owner wallet
286300
BOOST_CHECK_EQUAL(wallet.GetWalletTx(txFrom.GetHash())->GetAvailableCredit(false, ISMINE_SPENDABLE_TRANSPARENT), 0);
287301
}
288-
*/
289302

290303
BOOST_AUTO_TEST_SUITE_END()

src/validation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,6 +1922,7 @@ void static UpdateTip(CBlockIndex* pindexNew)
19221922
{
19231923
AssertLockHeld(cs_main);
19241924
chainActive.SetTip(pindexNew);
1925+
g_IsV6Active = Params().GetConsensus().NetworkUpgradeActive(pindexNew->nHeight, Consensus::UPGRADE_V6_0);
19251926

19261927
// New best block
19271928
mempool.AddTransactionsUpdated(1);
@@ -3660,6 +3661,9 @@ bool LoadChainTip(const CChainParams& chainparams)
36603661

36613662
const CBlockIndex* pChainTip = chainActive.Tip();
36623663

3664+
// initial global flag update
3665+
g_IsV6Active = Params().GetConsensus().NetworkUpgradeActive(pChainTip->nHeight, Consensus::UPGRADE_V5_0);
3666+
36633667
LogPrintf("Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n",
36643668
pChainTip->GetBlockHash().GetHex(), pChainTip->nHeight,
36653669
FormatISO8601DateTime(pChainTip->GetBlockTime()),

0 commit comments

Comments
 (0)