X-Git-Url: https://git.novaco.in/?p=NovacoinLibrary.git;a=blobdiff_plain;f=Novacoin%2FCBlockStore.cs;h=94fc2b67662143d9ae4db9f31ed2190fe2bbf9a5;hp=a579898bf14d271766ad6921364853c242b1b9fe;hb=eb39142ad873e102405ceffb5ec837b510da9096;hpb=f8e0e5777cdd3fbc2a0c7148731d301899dfea5f diff --git a/Novacoin/CBlockStore.cs b/Novacoin/CBlockStore.cs index a579898..94fc2b6 100644 --- a/Novacoin/CBlockStore.cs +++ b/Novacoin/CBlockStore.cs @@ -76,9 +76,9 @@ namespace Novacoin public long nStakeModifier { get; set; } /// - /// Stake entropy bit + /// Chain trust score /// - public byte nEntropyBit { get; set; } + public byte[] ChainTrust { get; set; } /// /// Proof-of-Stake hash @@ -221,6 +221,7 @@ namespace Novacoin /// /// Previous block cursor /// + [Ignore] public CBlockStoreItem prev { get { return CBlockStore.Instance.GetCursor(prevHash); } } @@ -228,25 +229,31 @@ namespace Novacoin /// /// Next block cursor /// + [Ignore] public CBlockStoreItem next { get { return CBlockStore.Instance.GetCursor(nextHash); } } + [Ignore] bool IsInMainChain { get { return (next != null); } } - - /// - /// STake modifier generation flag - /// - public bool GeneratedStakeModifier + /// + /// 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); } @@ -288,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; + } + } + } } @@ -451,6 +582,8 @@ namespace Novacoin fStreamReadWrite = File.Open(strBlockFile, FileMode.OpenOrCreate, FileAccess.ReadWrite); + Instance = this; + if (firstInit) { lock (LockObj) @@ -507,8 +640,6 @@ namespace Novacoin blockMap.TryAdd(item.Hash, item); } } - - Instance = this; } public bool GetTransaction(uint256 TxID, ref CTransaction tx) @@ -537,7 +668,15 @@ 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 @@ -635,7 +774,6 @@ namespace Novacoin var itemTemplate = new CBlockStoreItem() { nHeight = nHeight, - nEntropyBit = Entropy.GetStakeEntropyBit(nHeight, nHash) }; itemTemplate.FillHeader(block.header);