X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=Novacoin%2FCBlockStore.cs;h=62a021f970fa52b15b2cbef829372028de701e02;hb=6b0501a53995f78928332cfcd7ce1cae4b07486f;hp=743923528090b030fe166ff408ed4ea20857c5bc;hpb=b0714a7418f2a8ff09904d1dc014c0ad46ef64c3;p=NovacoinLibrary.git diff --git a/Novacoin/CBlockStore.cs b/Novacoin/CBlockStore.cs index 7439235..62a021f 100644 --- a/Novacoin/CBlockStore.cs +++ b/Novacoin/CBlockStore.cs @@ -177,14 +177,14 @@ namespace Novacoin )); // Write block to file. - var itemTemplate = new CBlockStoreItem() + var rootCursor = new CBlockStoreItem() { nHeight = 0 }; - itemTemplate.FillHeader(genesisBlock.header); + rootCursor.FillHeader(genesisBlock.header); - if (!AddItemToIndex(ref itemTemplate, ref genesisBlock)) + if (!AddItemToIndex(ref rootCursor, ref genesisBlock)) { throw new Exception("Unable to write genesis block"); } @@ -197,6 +197,8 @@ namespace Novacoin // Init list of block items foreach (var item in blockTreeItems) { + item.nStakeModifierChecksum = StakeModifier.GetModifierChecksum(item); + blockMap.TryAdd(item.Hash, item); if (item.IsProofOfStake) @@ -329,9 +331,9 @@ namespace Novacoin return true; } - private bool AddItemToIndex(ref CBlockStoreItem itemTemplate, ref CBlock block) + private bool AddItemToIndex(ref CBlockStoreItem newCursor, ref CBlock block) { - uint256 blockHash = itemTemplate.Hash; + uint256 blockHash = newCursor.Hash; if (blockMap.ContainsKey(blockHash)) { @@ -343,9 +345,9 @@ namespace Novacoin dbConn.BeginTransaction(); // Compute chain trust score - itemTemplate.nChainTrust = (itemTemplate.prev != null ? itemTemplate.prev.nChainTrust : 0) + itemTemplate.nBlockTrust; + newCursor.nChainTrust = (newCursor.prev != null ? newCursor.prev.nChainTrust : 0) + newCursor.nBlockTrust; - if (!itemTemplate.SetStakeEntropyBit(Entropy.GetStakeEntropyBit(itemTemplate.nHeight, blockHash))) + if (!newCursor.SetStakeEntropyBit(Entropy.GetStakeEntropyBit(newCursor.nHeight, blockHash))) { return false; // SetStakeEntropyBit() failed } @@ -353,15 +355,15 @@ namespace Novacoin // compute stake modifier long nStakeModifier = 0; bool fGeneratedStakeModifier = false; - if (!StakeModifier.ComputeNextStakeModifier(itemTemplate, ref nStakeModifier, ref fGeneratedStakeModifier)) + if (!StakeModifier.ComputeNextStakeModifier(ref newCursor, ref nStakeModifier, ref fGeneratedStakeModifier)) { return false; // ComputeNextStakeModifier() failed } - itemTemplate.SetStakeModifier(nStakeModifier, fGeneratedStakeModifier); + newCursor.SetStakeModifier(nStakeModifier, fGeneratedStakeModifier); + newCursor.nStakeModifierChecksum = StakeModifier.GetModifierChecksum(newCursor); - var nChecksum = StakeModifier.GetModifierChecksum(ref itemTemplate); - if (!ModifierCheckpoints.Verify(itemTemplate.nHeight, nChecksum)) + if (!ModifierCheckpoints.Verify(newCursor.nHeight, newCursor.nStakeModifierChecksum)) { return false; // Stake modifier checkpoints mismatch } @@ -369,10 +371,10 @@ namespace Novacoin // Add to index if (block.IsProofOfStake) { - itemTemplate.SetProofOfStake(); + newCursor.SetProofOfStake(); - itemTemplate.prevoutStake = block.vtx[1].vin[0].prevout; - itemTemplate.nStakeTime = block.vtx[1].nTime; + newCursor.prevoutStake = block.vtx[1].vin[0].prevout; + newCursor.nStakeTime = block.vtx[1].nTime; // Save proof-of-stake hash value uint256 hashProofOfStake; @@ -380,32 +382,32 @@ namespace Novacoin { return false; // hashProofOfStake not found } - itemTemplate.hashProofOfStake = hashProofOfStake; + newCursor.hashProofOfStake = hashProofOfStake; } - if (!itemTemplate.WriteToFile(ref fStreamReadWrite, ref block)) + if (!newCursor.WriteToFile(ref fStreamReadWrite, ref block)) { return false; } - if (dbConn.Insert(itemTemplate) == 0) + if (dbConn.Insert(newCursor) == 0) { return false; // Insert failed } // Get last RowID. - itemTemplate.ItemID = dbPlatform.SQLiteApi.LastInsertRowid(dbConn.Handle); + newCursor.ItemID = dbPlatform.SQLiteApi.LastInsertRowid(dbConn.Handle); - if (!blockMap.TryAdd(blockHash, itemTemplate)) + if (!blockMap.TryAdd(blockHash, newCursor)) { return false; // blockMap add failed } - if (itemTemplate.nChainTrust > ChainParams.nBestChainTrust) + if (newCursor.nChainTrust > ChainParams.nBestChainTrust) { // New best chain - if (!SetBestChain(ref itemTemplate)) + if (!SetBestChain(ref newCursor)) { return false; // SetBestChain failed. } @@ -968,20 +970,22 @@ namespace Novacoin if (tx.IsCoinStake) { - // Coin stake tx earns reward instead of paying fee - long nCoinAge; - if (!tx.GetCoinAge(ref inputs, out nCoinAge)) + if (HashCheckpoints.LastCheckpointTime < tx.nTime) { - return false; // unable to get coin age for coinstake - } - - long nReward = tx.nValueOut - nValueIn; + // Coin stake tx earns reward instead of paying fee + long nCoinAge; + if (!tx.GetCoinAge(ref inputs, out nCoinAge)) + { + return false; // unable to get coin age for coinstake + } - long nCalculatedReward = CBlock.GetProofOfStakeReward(nCoinAge, cursorBlock.nBits, tx.nTime) - tx.GetMinFee(1, false, CTransaction.MinFeeMode.GMF_BLOCK) + CTransaction.nCent; + long nReward = tx.nValueOut - nValueIn; + long nCalculatedReward = CBlock.GetProofOfStakeReward(nCoinAge, cursorBlock.nBits, tx.nTime) - tx.GetMinFee(1, false, CTransaction.MinFeeMode.GMF_BLOCK) + CTransaction.nCent; - if (nReward > nCalculatedReward) - { - return false; // coinstake pays too much + if (nReward > nCalculatedReward) + { + return false; // coinstake pays too much + } } } else @@ -1056,7 +1060,6 @@ namespace Novacoin var prevBlockHeader = prevBlockCursor.BlockHeader; - // TODO: proof-of-work/proof-of-stake verification uint nHeight = prevBlockCursor.nHeight + 1; // Check timestamp against prev @@ -1081,17 +1084,27 @@ namespace Novacoin return false; // rejected by checkpoint lock-in } - // TODO: Enforce rule that the coinbase starts with serialized block height + // Enforce rule that the coinbase starts with serialized block height + var expect = new CScript(); + expect.AddNumber((int)nHeight); + + byte[] expectBytes = expect; + byte[] scriptSig = block.vtx[0].vin[0].scriptSig; + + if (!expectBytes.SequenceEqual(scriptSig.Take(expectBytes.Length))) + { + return false; // coinbase doesn't start with serialized height. + } // Write block to file. - var itemTemplate = new CBlockStoreItem() + var newCursor = new CBlockStoreItem() { nHeight = nHeight, }; - itemTemplate.FillHeader(block.header); + newCursor.FillHeader(block.header); - if (!AddItemToIndex(ref itemTemplate, ref block)) + if (!AddItemToIndex(ref newCursor, ref block)) { dbConn.Rollback(); @@ -1290,8 +1303,6 @@ namespace Novacoin if (block.IsProofOfStake) { - // TODO: proof-of-stake validation - uint256 hashProofOfStake = 0, targetProofOfStake = 0; if (!StakeModifier.CheckProofOfStake(block.vtx[1], block.header.nBits, out hashProofOfStake, out targetProofOfStake)) {