Beispiel #1
0
        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);
        }
Beispiel #2
0
        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());
            }
        }
Beispiel #3
0
        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();
        }
Beispiel #4
0
        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);
        }