X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=Novacoin%2FCBlockStore.cs;h=94fc2b67662143d9ae4db9f31ed2190fe2bbf9a5;hb=eb39142ad873e102405ceffb5ec837b510da9096;hp=a9c504cdfd310a048d42043a18c9adabc1e4bd26;hpb=7726cc3ff2ad58160957235de7c08f1e704c8532;p=NovacoinLibrary.git
diff --git a/Novacoin/CBlockStore.cs b/Novacoin/CBlockStore.cs
index a9c504c..94fc2b6 100644
--- a/Novacoin/CBlockStore.cs
+++ b/Novacoin/CBlockStore.cs
@@ -61,6 +61,11 @@ namespace Novacoin
public uint nNonce { get; set; }
///
+ /// Next block hash.
+ ///
+ public byte[] nextHash { get; set; }
+
+ ///
/// Block type flags
///
public BlockType BlockTypeFlag { get; set; }
@@ -71,9 +76,14 @@ namespace Novacoin
public long nStakeModifier { get; set; }
///
- /// Stake entropy bit
+ /// Chain trust score
+ ///
+ public byte[] ChainTrust { get; set; }
+
+ ///
+ /// Proof-of-Stake hash
///
- public byte nEntropyBit { get; set; }
+ public byte[] hashProofOfStake { get; set; }
///
/// Block height
@@ -211,19 +221,45 @@ namespace Novacoin
///
/// Previous block cursor
///
- public public CBlockStoreItem prev {
+ [Ignore]
+ public CBlockStoreItem prev {
get { return CBlockStore.Instance.GetCursor(prevHash); }
}
///
+ /// Next block cursor
+ ///
+ [Ignore]
+ public CBlockStoreItem next
+ {
+ get { return CBlockStore.Instance.GetCursor(nextHash); }
+ }
+
+ [Ignore]
+ bool IsInMainChain
+ {
+ get { return (next != null); }
+ }
+
+ ///
/// STake modifier generation flag
///
+ [Ignore]
public bool GeneratedStakeModifier
{
get { return (BlockTypeFlag & BlockType.BLOCK_STAKE_MODIFIER) != 0; }
}
///
+ /// Stake entropy bit
+ ///
+ [Ignore]
+ public uint StakeEntropyBit
+ {
+ get { return ((uint)(BlockTypeFlag & BlockType.BLOCK_STAKE_ENTROPY) >> 1); }
+ }
+
+ ///
/// Sets stake modifier and flag.
///
/// New stake modifier.
@@ -259,19 +295,143 @@ namespace Novacoin
///
/// Block has no proof-of-stake flag.
///
+ [Ignore]
public bool IsProofOfWork
{
- get { return (BlockTypeFlag & BlockType.BLOCK_PROOF_OF_STAKE) != 0; }
+ get { return (BlockTypeFlag & BlockType.BLOCK_PROOF_OF_STAKE) == 0; }
}
///
/// Block has proof-of-stake flag set.
///
+ [Ignore]
public bool IsProofOfStake
{
- get { return (BlockTypeFlag & BlockType.BLOCK_PROOF_OF_STAKE) == 0; }
+ get { return (BlockTypeFlag & BlockType.BLOCK_PROOF_OF_STAKE) != 0; }
}
+ ///
+ /// Chain trust score.
+ ///
+ [Ignore]
+ public uint256 nChainTrust {
+ get
+ {
+ if (ChainTrust.Length != 32)
+ {
+ byte[] tmp = ChainTrust;
+ Array.Resize(ref tmp, 32);
+ ChainTrust = tmp;
+ }
+
+ return ChainTrust;
+ }
+ set { ChainTrust = Interop.TrimArray(value); }
+ }
+
+ ///
+ /// Block trust score.
+ ///
+ [Ignore]
+ public uint256 nBlockTrust
+ {
+ get
+ {
+ uint256 nTarget = 0;
+ nTarget.Compact = nBits;
+
+ /* Old protocol */
+ if (nTime < NetUtils.nChainChecksSwitchTime)
+ {
+ return IsProofOfStake ? (new uint256(1) << 256) / (nTarget + 1) : 1;
+ }
+
+ /* New protocol */
+
+ // Calculate work amount for block
+ var nPoWTrust = NetUtils.nPoWBase / (nTarget + 1);
+
+ // Set nPowTrust to 1 if we are checking PoS block or PoW difficulty is too low
+ nPoWTrust = (IsProofOfStake || !nPoWTrust) ? 1 : nPoWTrust;
+
+ // Return nPoWTrust for the first 12 blocks
+ if (prev == null || prev.nHeight < 12)
+ return nPoWTrust;
+
+ CBlockStoreItem currentIndex = prev;
+
+ if (IsProofOfStake)
+ {
+ var nNewTrust = (new uint256(1) << 256) / (nTarget + 1);
+
+ // Return 1/3 of score if parent block is not the PoW block
+ if (!prev.IsProofOfWork)
+ {
+ return nNewTrust / 3;
+ }
+
+ int nPoWCount = 0;
+
+ // Check last 12 blocks type
+ while (prev.nHeight - currentIndex.nHeight < 12)
+ {
+ if (currentIndex.IsProofOfWork)
+ {
+ nPoWCount++;
+ }
+ currentIndex = currentIndex.prev;
+ }
+
+ // Return 1/3 of score if less than 3 PoW blocks found
+ if (nPoWCount < 3)
+ {
+ return nNewTrust / 3;
+ }
+
+ return nNewTrust;
+ }
+ else
+ {
+ var nLastBlockTrust = prev.nChainTrust - prev.prev.nChainTrust;
+
+ // Return nPoWTrust + 2/3 of previous block score if two parent blocks are not PoS blocks
+ if (!prev.IsProofOfStake || !prev.prev.IsProofOfStake)
+ {
+ return nPoWTrust + (2 * nLastBlockTrust / 3);
+ }
+
+ int nPoSCount = 0;
+
+ // Check last 12 blocks type
+ while (prev.nHeight - currentIndex.nHeight < 12)
+ {
+ if (currentIndex.IsProofOfStake)
+ {
+ nPoSCount++;
+ }
+ currentIndex = currentIndex.prev;
+ }
+
+ // Return nPoWTrust + 2/3 of previous block score if less than 7 PoS blocks found
+ if (nPoSCount < 7)
+ {
+ return nPoWTrust + (2 * nLastBlockTrust / 3);
+ }
+
+ nTarget.Compact = prev.nBits;
+
+ if (!nTarget)
+ {
+ return 0;
+ }
+
+ var nNewTrust = (new uint256(1) << 256) / (nTarget + 1);
+
+ // Return nPoWTrust + full trust score for previous block nBits
+ return nPoWTrust + nNewTrust;
+ }
+ }
+ }
}
@@ -422,6 +582,8 @@ namespace Novacoin
fStreamReadWrite = File.Open(strBlockFile, FileMode.OpenOrCreate, FileAccess.ReadWrite);
+ Instance = this;
+
if (firstInit)
{
lock (LockObj)
@@ -478,8 +640,6 @@ namespace Novacoin
blockMap.TryAdd(item.Hash, item);
}
}
-
- Instance = this;
}
public bool GetTransaction(uint256 TxID, ref CTransaction tx)
@@ -508,12 +668,23 @@ namespace Novacoin
return false;
}
- // TODO: compute chain trust, set stake entropy bit, record proof-of-stake hash value
+ // Compute chain trust score
+ itemTemplate.nChainTrust = (itemTemplate.prev != null ? itemTemplate.prev.nChainTrust : 0) + itemTemplate.nBlockTrust;
+
+ if (!itemTemplate.SetStakeEntropyBit(Entropy.GetStakeEntropyBit(itemTemplate.nHeight, blockHash)))
+ {
+ return false; // SetStakeEntropyBit() failed
+ }
+
+ // TODO: set stake entropy bit, record proof-of-stake hash value
// TODO: compute stake modifier
// Add to index
- itemTemplate.BlockTypeFlag = block.IsProofOfStake ? BlockType.PROOF_OF_STAKE : BlockType.PROOF_OF_WORK;
+ if (block.IsProofOfStake)
+ {
+ itemTemplate.SetProofOfStake();
+ }
if (!itemTemplate.WriteToFile(ref writer, ref block))
{
@@ -603,7 +774,6 @@ namespace Novacoin
var itemTemplate = new CBlockStoreItem()
{
nHeight = nHeight,
- nEntropyBit = Entropy.GetStakeEntropyBit(nHeight, nHash)
};
itemTemplate.FillHeader(block.header);