X-Git-Url: https://git.novaco.in/?p=NovacoinLibrary.git;a=blobdiff_plain;f=Novacoin%2FCBlockStore.cs;fp=Novacoin%2FCBlockStore.cs;h=854897257986f96a2969944b8b82b5b64a84fc52;hp=6b03f083979e2b6e3fea2f4fa71767967944179f;hb=35b1bae36732d0110e2e3cf99c2059e52bfc73ce;hpb=1e2160be4bf5122f8bbea1c493df9a26be91e4cf 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;