From 35b1bae36732d0110e2e3cf99c2059e52bfc73ce Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Fri, 11 Sep 2015 01:26:54 +0300 Subject: [PATCH] Limit duplicity on stake & Process orphans only if there are some. --- Novacoin/CBlock.cs | 8 +++++- Novacoin/CBlockStore.cs | 61 ++++++++++++++++++++++++++++++----------------- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/Novacoin/CBlock.cs b/Novacoin/CBlock.cs index fba1387..b616fa5 100644 --- a/Novacoin/CBlock.cs +++ b/Novacoin/CBlock.cs @@ -594,6 +594,12 @@ namespace Novacoin return nSubsidy; } - } + + public Tuple ProofOfStake + { + get { return IsProofOfStake ? new Tuple(vtx[1].vin[0].prevout, vtx[1].nTime) : new Tuple(new COutPoint(), 0); } + } + +} } diff --git a/Novacoin/CBlockStore.cs b/Novacoin/CBlockStore.cs index 6b03f08..8548972 100644 --- a/Novacoin/CBlockStore.cs +++ b/Novacoin/CBlockStore.cs @@ -85,7 +85,7 @@ namespace Novacoin private ConcurrentDictionary mapStakeSeen = new ConcurrentDictionary(); - private ConcurrentDictionary mapStakeSeenOrphan = new ConcurrentDictionary(); + private ConcurrentDictionary, uint256> mapStakeSeenOrphan = new ConcurrentDictionary, uint256>(); /// @@ -1303,12 +1303,22 @@ namespace Novacoin { if (block.IsProofOfStake) { - // TODO: limit duplicity on stake + var proof = block.ProofOfStake; + + // Limited duplicity on stake: prevents block flood attack + // Duplicate stake allowed only when there is orphan child block + if (mapStakeSeenOrphan.ContainsKey(proof) && !orphanMapByPrev.ContainsKey(blockHash)) + { + return false; // duplicate proof-of-stake + } + else + { + mapStakeSeenOrphan.TryAdd(proof, blockHash); + } } - var block2 = new CBlock(block); - orphanMap.TryAdd(blockHash, block2); - orphanMapByPrev.TryAdd(blockHash, block2); + orphanMap.TryAdd(blockHash, block); + orphanMapByPrev.TryAdd(blockHash, block); return true; } @@ -1320,32 +1330,39 @@ namespace Novacoin return false; } - // Recursively process any orphan blocks that depended on this one - var orphansQueue = new List(); - orphansQueue.Add(blockHash); - - for (int i = 0; i < orphansQueue.Count; i++) + if (orphanMapByPrev.Count > 0) { - var hashPrev = orphansQueue[i]; + // Recursively process any orphan blocks that depended on this one + + var orphansQueue = new List(); + orphansQueue.Add(blockHash); - foreach (var pair in orphanMap) + for (int i = 0; i < orphansQueue.Count; i++) { - var orphanBlock = pair.Value; + var hashPrev = orphansQueue[i]; - if (orphanBlock.header.prevHash == blockHash) + foreach (var pair in orphanMapByPrev) { - if (AcceptBlock(ref orphanBlock)) + var orphanBlock = pair.Value; + + if (orphanBlock.header.prevHash == blockHash) { - orphansQueue.Add(pair.Key); - } + if (AcceptBlock(ref orphanBlock)) + { + orphansQueue.Add(pair.Key); + } - CBlock dummy1; - orphanMap.TryRemove(pair.Key, out dummy1); + CBlock dummy1; + orphanMap.TryRemove(pair.Key, out dummy1); + + uint256 dummyHash; + mapStakeSeenOrphan.TryRemove(orphanBlock.ProofOfStake, out dummyHash); + } } - } - CBlock dummy2; - orphanMap.TryRemove(hashPrev, out dummy2); + CBlock dummy2; + orphanMapByPrev.TryRemove(hashPrev, out dummy2); + } } return true; -- 1.7.1