From 7179624be052575a50fe87ce5a380c0dd803a689 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Tue, 8 Sep 2015 23:06:08 +0300 Subject: [PATCH] getTxOutItem() --- Novacoin/CBlockStore.cs | 115 +++++++++++++++++++++++++----------------- Novacoin/DatabaseObjects.cs | 23 +++++++++ 2 files changed, 91 insertions(+), 47 deletions(-) diff --git a/Novacoin/CBlockStore.cs b/Novacoin/CBlockStore.cs index 133a18e..f4342a2 100644 --- a/Novacoin/CBlockStore.cs +++ b/Novacoin/CBlockStore.cs @@ -260,10 +260,8 @@ namespace Novacoin var inputsKey = new COutPoint(item.TransactionHash, item.nOut); -// item.IsSpent = true; - // Add output data to dictionary - inputs.Add(inputsKey, (TxOutItem)item); + inputs.Add(inputsKey, item.getTxOutItem()); } if (queryResults.Count < tx.vin.Length) @@ -285,7 +283,7 @@ namespace Novacoin inputs.Add(outPoint, queued[outPoint]); // Mark output as spent - queued[outPoint].IsSpent = true; + // queued[outPoint].IsSpent = true; } } else @@ -639,13 +637,20 @@ namespace Novacoin uint nSigOps = 0; var queuedMerkleNodes = new Dictionary(); - var queued = new Dictionary(); + var queuedOutputs = new Dictionary(); for (var nTx = 0; nTx < block.vtx.Length; nTx++) { var tx = block.vtx[nTx]; var hashTx = tx.Hash; - var nTxPos = cursor.nBlockPos + block.GetTxOffset(nTx); + + if (!queuedMerkleNodes.ContainsKey(hashTx)) + { + var nTxPos = cursor.nBlockPos + block.GetTxOffset(nTx); + var mNode = new CMerkleNode(cursor.ItemID, nTxPos, tx); + + queuedMerkleNodes.Add(hashTx, mNode); + } Dictionary txouts; if (GetOutputs(hashTx, out txouts)) @@ -670,7 +675,7 @@ namespace Novacoin else { bool Invalid; - if (!FetchInputs(tx, ref queued, ref inputs, true, out Invalid)) + if (!FetchInputs(tx, ref queuedOutputs, ref inputs, true, out Invalid)) { return false; // Unable to fetch some inputs. } @@ -695,7 +700,7 @@ namespace Novacoin nFees += nTxValueIn - nTxValueOut; } - if (!ConnectInputs(tx, ref inputs, ref queued, ref cursor, true, fScriptChecks, scriptFlags)) + if (!ConnectInputs(tx, ref inputs, ref queuedOutputs, ref cursor, true, fScriptChecks, scriptFlags)) { return false; } @@ -703,22 +708,17 @@ namespace Novacoin for (var i = 0u; i < tx.vout.Length; i++) { - if (!queuedMerkleNodes.ContainsKey(hashTx)) - { - var mNode = new CMerkleNode(cursor.ItemID, nTxPos, tx); - queuedMerkleNodes.Add(hashTx, mNode); - } - var outKey = new COutPoint(hashTx, i); - var outData = new TxOutItem(); - - outData.nValue = tx.vout[i].nValue; - outData.scriptPubKey = tx.vout[i].scriptPubKey; - outData.nOut = i; - - outData.IsSpent = false; + var outData = new TxOutItem() + { + nMerkleNodeID = -1, + nValue = tx.vout[i].nValue, + scriptPubKey = tx.vout[i].scriptPubKey, + IsSpent = false, + nOut = i + }; - queued.Add(outKey, outData); + queuedOutputs.Add(outKey, outData); } } @@ -746,54 +746,75 @@ namespace Novacoin return true; } + // Flush merkle nodes. + var savedMerkleNodes = new Dictionary(); + foreach (var merklePair in queuedMerkleNodes) + { + var merkleNode = merklePair.Value; + + if (!SaveMerkleNode(ref merkleNode)) + { + // Unable to save merkle tree cursor. + return false; + } + + savedMerkleNodes.Add(merklePair.Key, merkleNode); + } + // Write queued transaction changes - var actualMerkleNodes = new Dictionary(); - var queuedOutpointItems = new List(); - foreach (KeyValuePair outPair in queued) + var newOutpointItems = new List(); + var updatedOutpointItems = new List(); + foreach (var outPair in queuedOutputs) { - uint256 txID = outPair.Key.hash; - CMerkleNode merkleNode; + var outItem = outPair.Value; - if (actualMerkleNodes.ContainsKey(txID)) + if (outItem.nMerkleNodeID == -1) { - merkleNode = actualMerkleNodes[txID]; + // This outpoint doesn't exist yet, adding to insert list. + + outItem.nMerkleNodeID = savedMerkleNodes[outPair.Key.hash].nMerkleNodeID; + newOutpointItems.Add(outItem); } else { - // TODO: Bug here, we shouldn't mix new and already existent outpoints in the same dictionary. + // This outpount already exists, adding to update list. - - merkleNode = queuedMerkleNodes[txID]; - if (!SaveMerkleNode(ref merkleNode)) - { - // Unable to save merkle tree cursor. - return false; - } - actualMerkleNodes.Add(txID, merkleNode); + updatedOutpointItems.Add(outItem); } + } - var outItem = outPair.Value; - outItem.nMerkleNodeID = merkleNode.nMerkleNodeID; - - queuedOutpointItems.Add(outItem); + if (updatedOutpointItems.Count != 0 && !UpdateOutpoints(ref updatedOutpointItems)) + { + return false; // Unable to update outpoints } - if (!SaveOutpoints(ref queuedOutpointItems)) + if (newOutpointItems.Count != 0 && !InsertOutpoints(ref newOutpointItems)) { - return false; // Unable to save outpoints + return false; // Unable to insert outpoints } return true; } /// - /// Insert set of outpoints + /// Insert set of new outpoints + /// + /// List of TxOutItem objects. + /// Result + private bool InsertOutpoints(ref List newOutpointItems) + { + return (dbConn.InsertAll(newOutpointItems, false) != 0); + } + + + /// + /// Update set of outpoints /// /// List of TxOutItem objects. /// Result - private bool SaveOutpoints(ref List queuedOutpointItems) + private bool UpdateOutpoints(ref List updatedOutpointItems) { - return dbConn.InsertAll(queuedOutpointItems, false) != 0; + return (dbConn.UpdateAll(updatedOutpointItems, false) != 0); } /// diff --git a/Novacoin/DatabaseObjects.cs b/Novacoin/DatabaseObjects.cs index 55523d8..d9668f5 100644 --- a/Novacoin/DatabaseObjects.cs +++ b/Novacoin/DatabaseObjects.cs @@ -723,6 +723,12 @@ namespace Novacoin public class TxOutItem { /// + /// Outpoint identifier. + /// + [PrimaryKey, AutoIncrement] + public long nOutpointID { get; set; } + + /// /// Reference to transaction item. /// [ForeignKey(typeof(CMerkleNode), Name = "nMerkleNodeID")] @@ -786,6 +792,23 @@ namespace Novacoin public class InputsJoin : TxOutItem { public byte[] TransactionHash { get; set; } + + /// + /// To avoid awkwardness of sqlite wrapper. + /// + /// + public TxOutItem getTxOutItem() + { + return new TxOutItem() + { + nOutpointID = nOutpointID, + nMerkleNodeID = nMerkleNodeID, + outputFlags = outputFlags, + OutputNumber = OutputNumber, + OutputValue = OutputValue, + scriptPubKey = scriptPubKey + }; + } } -- 1.7.1