protected override void BuildMetaData(TransactionDiscStorage transactionStorage, long sliceIndex) { var dirtyData = new DirtyData(); Hash previousHash = null; // Todo, get hash from previous storage for (var transactionId = transactionStorage.StartIndex; transactionId <= transactionStorage.EndIndex; transactionId++) { if (transactionId <= LastProcessedTransactionId) { continue; } var transactionData = transactionStorage.GetBlockDataRawIndex(transactionId); var item = new TransactionItem <CoreOperation>(transactionData); if (previousHash != null) { if (!item.Validation.IsValid(previousHash, new ArraySegment <byte>(transactionData, 0, transactionData.Length - ValidationOperation.ValidationOperationDataSize))) { throw new Exception("Transaction Validation failed"); } } previousHash = item.Validation.Hash; ConsumeTransaction(dirtyData, item); } ProcessDirtyData(dirtyData); }
void ProcessDirtyData(DirtyData dirtyData) { foreach (var accountId in dirtyData.DirtyAccounts) { var account = GetCoreAccount(accountId); _accountStorage.UpdateEntry(accountId, account.ToByteArray()); } foreach (var chainId in dirtyData.DirtyChains) { var chain = GetChainInfo(chainId); _chainInfoStorage.UpdateEntry(chainId, chain.ToByteArray()); } }
public void ConsumeCoreBlockData(BlockData <CoreBlock> blockData) { var block = blockData.Block; if (block.BlockId < LastProcessedBlockId) { return; } var dirtyData = new DirtyData(); var i = 0; foreach (var item in block.Items) { var operation = item.Transaction; if (ConsumeTransaction(dirtyData, item)) { TransactionStorage.Add(block.BlockId, item); i++; } } ProcessDirtyData(dirtyData); var lastTransactionid = LastProcessedTransactionId; var count = block.Items.Count; if (count > 0) { lastTransactionid = block.Items[count - 1].Transaction.OperationId; } foreach (var metaStorage in _metaDiscStorage) { metaStorage.LastBlockId = block.BlockId; metaStorage.LastTransactionId = lastTransactionid; metaStorage.Commit(); } TransactionStorage.Save(); }
bool ConsumeTransaction(DirtyData dirtyData, TransactionItem <CoreOperation> coreItem) { var operation = coreItem.Transaction; var validation = coreItem.Validation; if (operation.OperationId <= LastProcessedTransactionId) { return(false); } var type = operation.CoreOperationType; if (type == CoreOperationTypes.Account) { var ar = operation as AccountOperation; { var ac = GetCoreAccount(ar.AccountId, false); if (ac != null) { return(false); } } var account = new CoreAccount(ar.AccountId, ar.PublicKey) { LastTransactionId = operation.OperationId }; lock (_lock) _accounts[account.AccountId] = account; _accountStorage.AddEntry(ar.AccountId, account.ToByteArray()); return(true); } if (type == CoreOperationTypes.ChainInfo) { var co = operation as ChainInfoOperation; { var ci = GetChainInfo(co.ChainId, false); if (co.IsNewChain && ci != null) { return(false); } if (!co.IsNewChain && ci == null) { return(false); } } ChainInfo chain; if (co.IsNewChain) { chain = new ChainInfo(co.ChainId, co.AccountId, co.Name, co.Website); } else { chain = GetChainInfo(co.ChainId); chain.UpdateInfo(co.Name, co.Website); } if (chain.ChainId != Protocol.CoreChainId) { var account = GetCoreAccount(co.AccountId); if (account == null) { return(false); } account.LastTransactionId = operation.OperationId; dirtyData.DirtyAccounts.Add(account.AccountId); } foreach (var endpoint in co.PublicEndpoints) { chain.AddPublicEndPoint(endpoint); } foreach (var endpoint in co.RemovePublicEndPoints) { chain.RemovePublicEndPoint(endpoint); } foreach (var chainKey in co.ChainKeys) { chain.AddChainKey(chainKey, co.Timestamp); } foreach (var chainKeyIndex in co.RevokeChainKeys) { chain.RevokeChainKey(chainKeyIndex, operation.Timestamp); } foreach (var purchase in co.Purchases) { chain.AddPurchase(purchase, co.Timestamp); } foreach (var item in co.RemovePurchaseItems) { chain.RemovePurchaseItem(item, operation.Timestamp); } lock (_lock) _chains[chain.ChainId] = chain; if (co.IsNewChain) { _chainInfoStorage.AddEntry(co.ChainId, chain.ToByteArray()); } else { dirtyData.DirtyChains.Add(co.ChainId); } return(true); } if (type == CoreOperationTypes.Revenue) { var rev = operation as ChainRevenueInfoOperation; var chainId = rev.ChainId; var chain = GetChainInfo(chainId); if (chain == null) { return(false); } chain.AddRevenueInfo(rev.Revenue, rev.RevenueAccountFactor, rev.Timestamp); dirtyData.DirtyChains.Add(chainId); return(true); } if (type == CoreOperationTypes.AccountUpdate) { var u = operation as AccountUpdateOperation; foreach (var item in u.Updates.Values) { var account = GetCoreAccount(item.AccountId, true); if (account == null) { return(false); } account.UpdateBalance(item.Balance); account.LastTransactionId = operation.OperationId; dirtyData.DirtyAccounts.Add(item.AccountId); foreach (var revenue in item.Revenues) { var chainId = revenue.ChainId; var c = GetChainInfo(chainId); c.AddTotalAccountPayout(revenue.Amount); dirtyData.DirtyChains.Add(chainId); } } return(true); } if (type == CoreOperationTypes.BlockState) { var bi = operation as BlockStateOperation; foreach (var state in bi.BlockStates.Values) { var chainId = state.ChainId; var chainInfo = GetChainInfo(chainId); if (chainInfo == null) { return(false); } chainInfo.Update(state); dirtyData.DirtyChains.Add(chainId); } return(true); } return(false); }