X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=Novacoin%2FCBlockStore.cs;h=62a021f970fa52b15b2cbef829372028de701e02;hb=6b0501a53995f78928332cfcd7ce1cae4b07486f;hp=cca056e90a9855309496a5220f247ab038e5fbbb;hpb=7d59deb2e70c69cad8526523f90b3fbdbfe40e17;p=NovacoinLibrary.git
diff --git a/Novacoin/CBlockStore.cs b/Novacoin/CBlockStore.cs
index cca056e..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,23 +355,26 @@ 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);
- itemTemplate.nStakeModifierChecksum = StakeModifier.GetStakeModifierChecksum(ref itemTemplate);
+ newCursor.SetStakeModifier(nStakeModifier, fGeneratedStakeModifier);
+ newCursor.nStakeModifierChecksum = StakeModifier.GetModifierChecksum(newCursor);
- // TODO: verify stake modifier checkpoints
+ if (!ModifierCheckpoints.Verify(newCursor.nHeight, newCursor.nStakeModifierChecksum))
+ {
+ return false; // Stake modifier checkpoints mismatch
+ }
// 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;
@@ -377,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.
}
@@ -645,7 +650,7 @@ namespace Novacoin
return false; // Invalid block found.
}
- bool fScriptChecks = cursor.nHeight >= Checkpoints.TotalBlocksEstimate;
+ bool fScriptChecks = cursor.nHeight >= HashCheckpoints.TotalBlocksEstimate;
var scriptFlags = scriptflag.SCRIPT_VERIFY_NOCACHE | scriptflag.SCRIPT_VERIFY_P2SH;
long nFees = 0;
@@ -965,20 +970,22 @@ namespace Novacoin
if (tx.IsCoinStake)
{
- // ppcoin: 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
@@ -1053,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
@@ -1073,22 +1079,32 @@ namespace Novacoin
}
// Check that the block chain matches the known block chain up to a checkpoint
- if (!Checkpoints.Verify(nHeight, nHash))
+ if (!HashCheckpoints.Verify(nHeight, nHash))
{
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();
@@ -1099,7 +1115,7 @@ namespace Novacoin
}
///
- /// GEt block by hash.
+ /// Get block by hash.
///
/// Block hash
/// Block object reference
@@ -1287,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))
{