Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Touch up transition to version 2 transactions #1715

Merged
merged 5 commits into from
Jun 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 42 additions & 23 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1311,7 +1311,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CTransaction &tx, bool* pfMissingInput
// TODO: remove this check in the next release after mandatory block.
//
if (!IsV11Enabled(nBestHeight + 1) && tx.nVersion > 1) {
return tx.DoS(100, error("AcceptToMemoryPool : v2 transaction too early"));
return error("AcceptToMemoryPool : v2 transaction too early");
}

if (!tx.CheckTransaction())
Expand Down Expand Up @@ -1546,6 +1546,19 @@ void CTxMemPool::queryHashes(std::vector<uint256>& vtxid)
vtxid.push_back((*mi).first);
}

void CTxMemPool::DiscardVersion1()
{
LOCK(cs);

// Recursively remove all version 1 transactions from the memory pool for
// the switch to transaction version 2 at the block version 11 threshold:
//
for (const auto& tx_pair : mapTx) {
if (tx_pair.second.nVersion == 1) {
remove(tx_pair.second, true);
}
}
}



Expand Down Expand Up @@ -2756,7 +2769,7 @@ bool GridcoinConnectBlock(
bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
{
// Check it again in case a previous version let a bad block in, but skip BlockSig checking
if (!CheckBlock("ConnectBlock",pindex->nHeight, 395*COIN, !fJustCheck, !fJustCheck, false,false))
if (!CheckBlock(pindex->nHeight, !fJustCheck, !fJustCheck, false, false))
{
LogPrintf("ConnectBlock::Failed - ");
return false;
Expand Down Expand Up @@ -3409,7 +3422,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos, const u
return true;
}

bool CBlock::CheckBlock(std::string sCaller, int height1, int64_t Mint, bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig, bool fLoadingIndex) const
bool CBlock::CheckBlock(int height1, bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig, bool fLoadingIndex) const
{
// Allow the genesis block to pass.
if(hashPrevBlock.IsNull() &&
Expand Down Expand Up @@ -3502,24 +3515,6 @@ bool CBlock::CheckBlock(std::string sCaller, int height1, int64_t Mint, bool fCh
// Check transactions
for (auto const& tx : vtx)
{
// Mandatory switch to binary contracts (tx version 2):
if (IsV11Enabled(height1) && tx.nVersion < 2) {
// Disallow tx version 1 after the mandatory block to prohibit the
// use of legacy string contracts:
return tx.DoS(100, error("CheckBlock[] : legacy transaction"));
}

// Reject version 2 transactions until mandatory threshold.
//
// CTransaction::CURRENT_VERSION is now 2, but we cannot send version 2
// transactions with binary contracts until clients can handle them.
//
// TODO: remove this check in the next release after mandatory block.
//
if (!IsV11Enabled(height1) && tx.nVersion > 1) {
return tx.DoS(100, error("CheckBlock[] : v2 transaction too early"));
}

if (!tx.CheckTransaction())
return DoS(tx.nDoS, error("CheckBlock[] : CheckTransaction failed"));

Expand Down Expand Up @@ -3609,6 +3604,24 @@ bool CBlock::AcceptBlock(bool generated_by_me)

for (auto const& tx : vtx)
{
// Mandatory switch to binary contracts (tx version 2):
if (nVersion >= 11 && tx.nVersion < 2) {
// Disallow tx version 1 after the mandatory block to prohibit the
// use of legacy string contracts:
return DoS(100, error("%s: legacy transaction", __func__));
}

// Reject version 2 transactions until mandatory threshold.
//
// CTransaction::CURRENT_VERSION is now 2, but we cannot send version 2
// transactions with binary contracts until clients can handle them.
//
// TODO: remove this check in the next release after mandatory block.
//
if (nVersion <= 10 && tx.nVersion > 1) {
return DoS(100, error("%s: v2 transaction too early", __func__));
}

// Check that all transactions are finalized
if (!IsFinalTx(tx, nHeight, GetBlockTime()))
return DoS(10, error("AcceptBlock() : contains a non-final transaction"));
Expand Down Expand Up @@ -3750,6 +3763,12 @@ bool GridcoinServices()
if (!NN::Tally::ActivateSnapshotAccrual(pindexBest)) {
return error("GridcoinServices: Failed to prepare tally for v11.");
}

// Remove all version 1 transactions from the memory pool for the
// switch to transaction version 2 to prevent nodes from relaying
// legacy transactions that cannot validate:
//
mempool.DiscardVersion1();
}

//Dont perform the following functions if out of sync
Expand Down Expand Up @@ -3878,7 +3897,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock, bool generated_by_me)
}

// Preliminary checks
if (!pblock->CheckBlock("ProcessBlock", pindexBest->nHeight + 1, 100*COIN))
if (!pblock->CheckBlock(pindexBest->nHeight + 1))
return error("ProcessBlock() : CheckBlock FAILED");

// If don't already have its previous block, shunt it off to holding area until we get it
Expand Down Expand Up @@ -4180,7 +4199,7 @@ bool LoadBlockIndex(bool fAllowNew)
uint256 merkle_root = uint256S("0x5109d5782a26e6a5a5eb76c7867f3e8ddae2bff026632c36afec5dc32ed8ce9f");
assert(block.hashMerkleRoot == merkle_root);
assert(block.GetHash(true) == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet));
assert(block.CheckBlock("LoadBlockIndex",1,10*COIN));
assert(block.CheckBlock(1));

// Start new block file
unsigned int nFile;
Expand Down
3 changes: 2 additions & 1 deletion src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -1411,7 +1411,7 @@ class CBlock : public CBlockHeader
bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck=false);
bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true);
bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos, const uint256& hashProof);
bool CheckBlock(std::string sCaller, int height1, int64_t mint, bool fCheckPOW=true, bool fCheckMerkleRoot=true, bool fCheckSig=true, bool fLoadingIndex=false) const;
bool CheckBlock(int height1, bool fCheckPOW=true, bool fCheckMerkleRoot=true, bool fCheckSig=true, bool fLoadingIndex=false) const;
bool AcceptBlock(bool generated_by_me);
bool CheckBlockSignature() const;

Expand Down Expand Up @@ -1974,6 +1974,7 @@ class CTxMemPool
bool removeConflicts(const CTransaction &tx);
void clear();
void queryHashes(std::vector<uint256>& vtxid);
void DiscardVersion1();

unsigned long size() const
{
Expand Down
2 changes: 1 addition & 1 deletion src/txdb-leveldb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ bool CTxDB::LoadBlockIndex()
}
}

if (nCheckLevel>0 && !block.CheckBlock("LoadBlockIndex", pindex->nHeight,pindex->nMint, true, true, (nCheckLevel>6), true))
if (nCheckLevel>0 && !block.CheckBlock(pindex->nHeight, true, true, (nCheckLevel>6), true))
{
LogPrintf("LoadBlockIndex() : *** found bad block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
pindexFork = pindex->pprev;
Expand Down
23 changes: 21 additions & 2 deletions src/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1172,10 +1172,29 @@ void CWallet::ResendWalletTransactions(bool fForce)
for (auto const &item : mapSorted)
{
CWalletTx& wtx = *item.second;
if (wtx.CheckTransaction())
if (wtx.CheckTransaction()) {
// Nodes erase version 1 transactions from the mempool at the
// block version 11 threshold to prepare for version 2. If we
// still have unconfirmed version 1 transactions removed from
// the pool when the transition occurred, we can't switch the
// format to version 2 because we need to re-sign these which
// may change the properties of the transaction in a way that
// requires the consent of the user. Log a message instead so
// that the user can take action if needed:
//
if (wtx.nVersion == 1 && IsV11Enabled(nBestHeight + 1)) {
LogPrintf(
"WARNING: %s: unable to resend legacy version 1 tx %s",
__func__,
wtx.GetHash().ToString());

continue;
}

wtx.RelayWalletTransaction(txdb);
else
} else {
LogPrintf("ResendWalletTransactions() : CheckTransaction failed for transaction %s", wtx.GetHash().ToString());
}
}
}
}
Expand Down