Skip to content

Commit

Permalink
Merge pull request Peershares#75 from sigmike/cancel_duplicate_stake
Browse files Browse the repository at this point in the history
Cancel the best block when a duplicate stake is received
  • Loading branch information
sigmike committed Oct 18, 2014
2 parents c627cbc + d2d4ff4 commit 6658331
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 7 deletions.
44 changes: 39 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2494,10 +2494,39 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
return state.Invalid(error("ProcessBlock() : already have block (orphan) %s", hash.ToString().c_str()));

// ppcoin: check proof-of-stake
// Limited duplicity on stake: prevents block flood attack
// Duplicate stake allowed only when there is orphan child block
if (pblock->IsProofOfStake() && setStakeSeen.count(pblock->GetProofOfStake()) && !mapOrphanBlocksByPrev.count(hash) && !WantedByPendingSyncCheckpoint(hash))
return error("ProcessBlock() : duplicate proof-of-stake (%s, %d) for block %s", pblock->GetProofOfStake().first.ToString().c_str(), pblock->GetProofOfStake().second, hash.ToString().c_str());
if (pblock->IsProofOfStake())
{
std::pair<COutPoint, unsigned int> proofOfStake = pblock->GetProofOfStake();

if (pindexBest->IsProofOfStake() && proofOfStake.first == pindexBest->prevoutStake)
{
// The best block's stake is reused, we cancel the best block

// Only reject the best block if the duplicate is correctly signed
if (!pblock->CheckBlockSignature())
return state.DoS(100, error("ProcessBlock() : Invalid signature in duplicate block"));

printf("ProcessBlock() : block uses the same stake as the best block. Canceling the best block\n");

// Relay the duplicate block so that other nodes are aware of the duplication
RelayBlock(*pblock, hash);

// Cancel the best block
InvalidBlockFound(pindexBest);
CValidationState stateDummy;
if (!SetBestChain(stateDummy, pindexBest->pprev))
return error("ProcessBlock(): SetBestChain on previous best block failed");

return false;
}
else
{
// Limited duplicity on stake: prevents block flood attack
// Duplicate stake allowed only when there is orphan child block
if (pblock->IsProofOfStake() && setStakeSeen.count(proofOfStake) && !mapOrphanBlocksByPrev.count(hash) && !WantedByPendingSyncCheckpoint(hash))
return error("ProcessBlock() : duplicate proof-of-stake (%s, %d) for block %s", proofOfStake.first.ToString().c_str(), proofOfStake.second, hash.ToString().c_str());
}
}

// Preliminary checks
if (!pblock->CheckBlock(state))
Expand Down Expand Up @@ -3467,12 +3496,16 @@ void static ProcessGetData(CNode* pfrom)
boost::this_thread::interruption_point();
it++;

// ppcoin: relay memory may contain blocks too
bool found = false;

if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
{
// Send block from disk
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(inv.hash);
if (mi != mapBlockIndex.end())
{
found = true;
CBlock block;
block.ReadFromDisk((*mi).second);
if (inv.type == MSG_BLOCK)
Expand Down Expand Up @@ -3515,7 +3548,8 @@ void static ProcessGetData(CNode* pfrom)
}
}
}
else if (inv.IsKnownType())

if (!found && inv.IsKnownType())
{
// Send stream from relay memory
bool pushed = false;
Expand Down
26 changes: 24 additions & 2 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1875,9 +1875,8 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash)
RelayTransaction(tx, hash, ss);
}

void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
static void AddRelay(const CInv& inv, const CDataStream& ss)
{
CInv inv(MSG_TX, hash);
{
LOCK(cs_mapRelay);
// Expire old relay messages
Expand All @@ -1891,6 +1890,12 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
mapRelay.insert(std::make_pair(inv, ss));
vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
}
}

void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
{
CInv inv(MSG_TX, hash);
AddRelay(inv, ss);
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
Expand All @@ -1905,3 +1910,20 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
pnode->PushInventory(inv);
}
}

void RelayBlock(const CBlock& block, const uint256& hash)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(10000);
ss << block;
RelayBlock(block, hash, ss);
}

void RelayBlock(const CBlock& tx, const uint256& hash, const CDataStream& ss)
{
CInv inv(MSG_BLOCK, hash);
AddRelay(inv, ss);
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
pnode->PushInventory(inv);
}
4 changes: 4 additions & 0 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -643,4 +643,8 @@ class CTransaction;
void RelayTransaction(const CTransaction& tx, const uint256& hash);
void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss);

class CBlock;
void RelayBlock(const CBlock& tx, const uint256& hash);
void RelayBlock(const CBlock& tx, const uint256& hash, const CDataStream& ss);

#endif

0 comments on commit 6658331

Please sign in to comment.