X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=Novacoin%2FCBlockStore.cs;h=f44a93d5613c7ab7ca773e2052ef7d2ba22d2daf;hb=7b349e848699cdb1701a69350b4f677a43831931;hp=f4342a27adf41ca1af2a7baec7dce6230ef39b51;hpb=7179624be052575a50fe87ce5a380c0dd803a689;p=NovacoinLibrary.git diff --git a/Novacoin/CBlockStore.cs b/Novacoin/CBlockStore.cs index f4342a2..f44a93d 100644 --- a/Novacoin/CBlockStore.cs +++ b/Novacoin/CBlockStore.cs @@ -208,6 +208,9 @@ namespace Novacoin // Load data about the top node. ChainParams = dbConn.Table().First(); + + genesisBlockCursor = dbConn.Query("select * from [BlockStorage] where [Hash] = ?", (byte[])NetInfo.nHashGenesisBlock).First(); + bestBlockCursor = dbConn.Query("select * from [BlockStorage] where [Hash] = ?", ChainParams.HashBestChain).First(); } } @@ -274,6 +277,11 @@ namespace Novacoin { var outPoint = txin.prevout; + if (inputs.ContainsKey(outPoint)) + { + continue; // We have already seen this input. + } + if (!queued.ContainsKey(outPoint)) { return false; // No such transaction @@ -467,6 +475,11 @@ namespace Novacoin nTimeBestReceived = Interop.GetTime(); nTransactionsUpdated++; + if (!UpdateTopChain(cursor)) + { + return false; // unable to set top chain node. + } + return true; } @@ -608,7 +621,13 @@ namespace Novacoin } // Add to current best branch - cursor.prev.next = cursor; + var prevCursor = cursor.prev; + prevCursor.next = cursor; + + if (!UpdateDBCursor(ref prevCursor)) + { + return false; // unable to update + } // Delete redundant memory transactions foreach (var tx in block.vtx) @@ -836,10 +855,8 @@ namespace Novacoin private bool ConnectInputs(CTransaction tx, ref Dictionary inputs, ref Dictionary queued, ref CBlockStoreItem cursorBlock, bool fBlock, bool fScriptChecks, scriptflag scriptFlags) { - // Take over previous transactions' spent pointers + // Take over previous transactions' spent items // fBlock is true when this is called from AcceptBlock when a new best-block is added to the blockchain - // fMiner is true when called from the internal bitcoin miner - // ... both are false when called from CTransaction::AcceptToMemoryPool if (!tx.IsCoinBase) { @@ -852,26 +869,44 @@ namespace Novacoin var input = inputs[prevout]; CBlockStoreItem parentBlockCursor; - var merkleItem = GetMerkleCursor(input, out parentBlockCursor); - if (merkleItem == null) + if (input.nMerkleNodeID == -1) { - return false; // Unable to find merkle node - } + // This input seems as is confirmed by the same block. - // If prev is coinbase or coinstake, check that it's matured - if (merkleItem.IsCoinBase || merkleItem.IsCoinStake) - { - if (cursorBlock.nHeight - parentBlockCursor.nHeight < NetInfo.nGeneratedMaturity) + if (!queued.ContainsKey(prevout)) { - return false; // tried to spend non-matured generation input. + return false; // No such output has been queued by this block. } - } - // check transaction timestamp - if (merkleItem.nTime > tx.nTime) + // TODO: Ensure that neither coinbase nor coinstake outputs are + // available for spending in the generation block. + } + else { - return false; // transaction timestamp earlier than input transaction + // This input has been confirmed by one of the earlier accepted blocks. + + var merkleItem = GetMerkleCursor(input, out parentBlockCursor); + + if (merkleItem == null) + { + return false; // Unable to find merkle node + } + + // If prev is coinbase or coinstake, check that it's matured + if (merkleItem.IsCoinBase || merkleItem.IsCoinStake) + { + if (cursorBlock.nHeight - parentBlockCursor.nHeight < NetInfo.nGeneratedMaturity) + { + return false; // tried to spend non-matured generation input. + } + } + + // check transaction timestamp + if (merkleItem.nTime > tx.nTime) + { + return false; // transaction timestamp earlier than input transaction + } } // Check for negative or overflow input values @@ -917,7 +952,16 @@ namespace Novacoin // Write back if (fBlock) { - queued.Add(prevout, input); + if (input.nMerkleNodeID != -1) + { + // Input has been confirmed earlier. + queued.Add(prevout, input); + } + else + { + // Input has been confirmed by current block. + queued[prevout] = input; + } } } @@ -1078,14 +1122,19 @@ namespace Novacoin /// Block reference /// Block position reference /// Result of operation - public bool GetBlockByTransactionID(uint256 TxID, ref CBlock block, ref long nBlockPos) + public bool GetBlockByTransactionID(uint256 TxID, out CBlock block, out long nBlockPos) { + block = null; + nBlockPos = -1; + var queryResult = dbConn.Query("select b.* from [BlockStorage] b left join [MerkleNodes] m on (b.[ItemID] = m.[nParentBlockID]) where m.[TransactionHash] = ?", (byte[])TxID); if (queryResult.Count == 1) { CBlockStoreItem blockCursor = queryResult[0]; + nBlockPos = blockCursor.nBlockPos; + return blockCursor.ReadFromFile(ref fStreamReadWrite, out block); } @@ -1243,7 +1292,7 @@ namespace Novacoin // TODO: proof-of-stake validation uint256 hashProofOfStake = 0, targetProofOfStake = 0; - if (!StakeModifier.CheckProofOfStake(block.vtx[1], block.header.nBits, ref hashProofOfStake, ref targetProofOfStake)) + if (!StakeModifier.CheckProofOfStake(block.vtx[1], block.header.nBits, out hashProofOfStake, out targetProofOfStake)) { return false; // do not error here as we expect this during initial block download } @@ -1362,7 +1411,7 @@ namespace Novacoin } int nCount = blockMap.Count; - Console.WriteLine("nCount={0}, Hash={1}, Time={2}", nCount, block.header.Hash, DateTime.Now); // Commit on each 100th block + Console.WriteLine("nCount={0}, Hash={1}, NumTx={2}, Time={3}", nCount, block.header.Hash, block.vtx.Length, DateTime.Now); // Commit on each 100th block /* if (nCount % 100 == 0 && nCount != 0)