Skip to content

Commit

Permalink
1.5.0 Update + Patch exploit "Spent Stake"
Browse files Browse the repository at this point in the history
  • Loading branch information
Remapper committed Jan 25, 2019
1 parent 29a1bfd commit 4a62b27
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/clientversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

//! These need to be macros, as clientversion.cpp's and bitcoingenx*-res.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 1
#define CLIENT_VERSION_MINOR 4
#define CLIENT_VERSION_MINOR 5
#define CLIENT_VERSION_REVISION 0
#define CLIENT_VERSION_BUILD 0

Expand Down
75 changes: 75 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ CCriticalSection cs_main;

BlockMap mapBlockIndex;
map<uint256, uint256> mapProofOfStake;
map<COutPoint, int> mapStakeSpent;
set<pair<COutPoint, unsigned int> > setStakeSeen;
map<unsigned int, unsigned int> mapHashedBlocks;
CChain chainActive;
Expand Down Expand Up @@ -2543,6 +2544,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
if (coins->vout.size() < out.n + 1)
coins->vout.resize(out.n + 1);
coins->vout[out.n] = undo.txout;
if (pindex->nHeight>40000)
mapStakeSpent.erase(out);
}
}
}
Expand Down Expand Up @@ -3016,6 +3019,29 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (fTxIndex)
if (!pblocktree->WriteTxIndex(vPos))
return state.Abort("Failed to write transaction index");
// add new entries
if (pindex->nHeight>40000)
for (const CTransaction tx: block.vtx) {
if (tx.IsCoinBase())
continue;
for (const CTxIn in: tx.vin) {
LogPrint("map", "mapStakeSpent: Insert %s | %u\n", in.prevout.ToString(), pindex->nHeight);
mapStakeSpent.insert(std::make_pair(in.prevout, pindex->nHeight));
}
}

// delete old entries
if (pindex->nHeight>40000)
for (auto it = mapStakeSpent.begin(); it != mapStakeSpent.end();) {
if (it->second < pindex->nHeight - Params().MaxReorganizationDepth()) {
LogPrint("map", "mapStakeSpent: Erase %s | %u\n", it->first.ToString(), it->second);
it = mapStakeSpent.erase(it);
}
else {
it++;
}
}


// add this block to the view's block chain
view.SetBestBlock(pindex->GetBlockHash());
Expand Down Expand Up @@ -4182,6 +4208,55 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
}

int nHeight = pindex->nHeight;

if (pindex->nHeight>40000)
if (block.IsProofOfStake()) {
LOCK(cs_main);

CCoinsViewCache coins(pcoinsTip);

if (!coins.HaveInputs(block.vtx[1])) {
// the inputs are spent at the chain tip so we should look at the recently spent outputs

for (CTxIn in : block.vtx[1].vin) {
auto it = mapStakeSpent.find(in.prevout);
if (it == mapStakeSpent.end()) {
return false;
}
if (it->second <= pindexPrev->nHeight) {
return false;
}
}
}

// if this is on a fork
if (!chainActive.Contains(pindexPrev) && pindexPrev != NULL) {
// start at the block we're adding on to
CBlockIndex *last = pindexPrev;

// while that block is not on the main chain
while (!chainActive.Contains(last) && pindexPrev != NULL) {
CBlock bl;
ReadBlockFromDisk(bl, last);
// loop through every spent input from said block
for (CTransaction t : bl.vtx) {
for (CTxIn in: t.vin) {
// loop through every spent input in the staking transaction of the new block
for (CTxIn stakeIn : block.vtx[1].vin) {
// if they spend the same input
if (stakeIn.prevout == in.prevout) {
// reject the block
return false;
}
}
}
}

// go to the parent block
last = pindexPrev->pprev;
}
}
}

// Write block to history file
try {
Expand Down
6 changes: 3 additions & 3 deletions src/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* network protocol versioning
*/

static const int PROTOCOL_VERSION = 70900;
static const int PROTOCOL_VERSION = 70910;

//! initial proto version, to be increased after version/verack negotiation
static const int INIT_PROTO_VERSION = 209;
Expand All @@ -21,8 +21,8 @@ static const int INIT_PROTO_VERSION = 209;
static const int GETHEADERS_VERSION = 70077;

//! disconnect from peers older than this proto version
static const int MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT = 70810;
static const int MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT = 70900;
static const int MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT = 70900;
static const int MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT = 70910;

//! nTime field added to CAddress, starting with this version;
//! if possible, avoid requesting addresses nodes older than this
Expand Down

0 comments on commit 4a62b27

Please sign in to comment.