Пример #1
0
        private void OnResults(UInt32 seq, BkResult msg)
        {
            if (PendingSourceRequests.TryGetValue(seq, out DAPRequest sourceReq))
            {
                PendingSourceRequests.Remove(seq);
                Stream.SendReply(sourceReq, $"Fetch failed: {msg.StatusCode}");
            }

            Evaluator.OnResultsReceived(seq, msg);
        }
Пример #2
0
        public void OnResultsReceived(UInt32 seq, BkResult msg)
        {
            if (PendingEvalRequests.TryGetValue(seq, out EvalRequestHandlerDelegate handler))
            {
                PendingEvalRequests.Remove(seq);
                handler(seq, msg.StatusCode, null);
            }

            if (PendingGetVariablesRequests.TryGetValue(seq, out GetVariablesRequestHandlerDelegate varHandler))
            {
                PendingGetVariablesRequests.Remove(seq);
                varHandler(seq, msg.StatusCode, null);
            }
        }
Пример #3
0
        void Reorg()
        {
            var originalTip = _BlockChain.Tip;

            Keyed <Types.Block> fork = null;
            var newMainChain         = GetNewMainChainStartFromForkToLeaf(new Keyed <Types.Block>(_BkHash, _Bk), out fork);

            _BlockChain.ChainTip.Context(_DbTx).Value = fork.Key;
            _BlockChain.Tip = fork;
            _BlockChain.InitBlockTimestamps(_DbTx);

            var oldMainChain = GetOldMainChainStartFromLeafToFork(fork, originalTip.Key);

            foreach (var block in oldMainChain)
            {
                UndoBlock(block.Value, block.Key);
            }

            //append new chain
            foreach (var _bk in newMainChain)
            {
                var action = new BlockVerificationHelper(
                    _BlockChain,
                    _DbTx,
                    _bk.Key,
                    _bk.Value,
                    false,
                    true,
                    ConfirmedTxs,
                    UnconfirmedTxs,
                    QueueActions);

                BlockChainTrace.Information($"new main chain bk {_bk.Value.header.blockNumber} {action.Result.BkResultEnum}", _bk.Value);

                if (action.Result.BkResultEnum == BkResultEnum.Rejected)
                {
                    _BlockChain.ChainTip.Context(_DbTx).Value = originalTip.Key;
                    _BlockChain.Tip = originalTip;
                    _BlockChain.InitBlockTimestamps(_DbTx);

                    BlockChainTrace.Information("reorganization undo", _bk.Value);
                    Result = new BkResult(BkResultEnum.Rejected);
                    return;
                }
            }
        }
Пример #4
0
        public BlockVerificationHelper(
            BlockChain blockChain,
            TransactionContext dbTx,
            byte[] bkHash,
            Types.Block bk,
            bool handleOrphan = false,
            bool handleBranch = false,
            HashDictionary <TransactionValidation.PointedTransaction> confirmedTxs = null,
            HashDictionary <Types.Transaction> invalidatedTxs = null,
            List <QueueAction> queuedActions = null
            )
        {
            ConfirmedTxs   = confirmedTxs ?? new HashDictionary <TransactionValidation.PointedTransaction>();
            UnconfirmedTxs = invalidatedTxs ?? new HashDictionary <Types.Transaction>();            //todo: refactor to set as new obj by default
            QueueActions   = queuedActions ?? new List <QueueAction>();

            _BlockChain = blockChain;
            _DbTx       = dbTx;
            _BkHash     = bkHash;
            _Bk         = bk;

            if (!IsValid())
            {
                BlockChainTrace.Information($"block {_Bk.header.blockNumber} is invalid", _Bk);
                Result = new BkResult(BkResultEnum.Rejected);
                return;
            }

            if (IsInStore())
            {
                var    reject        = false;
                byte[] missingParent = null;
                var    location      = blockChain.BlockStore.GetLocation(dbTx, bkHash);

                switch (location)
                {
                case LocationEnum.Branch:
                    reject = !handleBranch;
                    break;

                case LocationEnum.Orphans:
                    missingParent = GetMissingParent();

                    reject = !handleOrphan && !handleBranch;
                    break;

                default:
                    reject = true;
                    break;
                }

                if (reject)
                {
                    BlockChainTrace.Information($"Block {_Bk.header.blockNumber} already in store ({location})", bk);
                    Result = new BkResult(BkResultEnum.Rejected, missingParent);
                    return;
                }
            }

            if (bk.transactions.Count() == 0)
            {
                BlockChainTrace.Information("empty tx list", bk);
                Result = new BkResult(BkResultEnum.Rejected);
                return;
            }

            if (!IsValidTime())
            {
                BlockChainTrace.Information("invalid time", bk);
                Result = new BkResult(BkResultEnum.Rejected);
                return;
            }

            //TODO:

            /*
             * 3. Transaction list must be non - empty
             * 4. Block hash must satisfy claimed nBits proof of work
             * 5. Block timestamp must not be more than two hours in the future
             * 6. First transaction must be coinbase, the rest must not be
             * 7. For each transaction, apply "tx" checks 2 - 4
             * 8. (omitted)
             * 9. (omitted)
             * 10. Verify Merkle hash
             */

            if (IsGenesis())
            {
                if (!IsGenesisValid())
                {
                    BlockChainTrace.Information("invalid genesis block", bk);
                    Result = new BkResult(BkResultEnum.Rejected);
                    return;
                }
                else
                {
                    blockChain.Timestamps.Init(bk.header.timestamp);
                    ExtendMain(QueueActions, 0, true);
                    Result = new BkResult(BkResultEnum.Accepted);
                    BlockChainTrace.Information("accepted genesis block", bk);
                    return;
                }
            }

            if (IsOrphan())
            {
                var missingParent = GetMissingParent();
                blockChain.BlockStore.Put(dbTx, bkHash, bk, LocationEnum.Orphans, 0);
                BlockChainTrace.Information($"block {_Bk.header.blockNumber} added as orphan", bk);
                Result = new BkResult(BkResultEnum.AcceptedOrphan, missingParent);
                return;
            }

            //12. Check that nBits value matches the difficulty rules

            if (!IsValidDifficulty() || !IsValidBlockNumber() || !IsValidTimeStamp())
            {
                BlockChainTrace.Information($"block {_Bk.header.blockNumber} rejected", bk);
                Result = new BkResult(BkResultEnum.Rejected);
                return;
            }

            //14. For certain old blocks(i.e.on initial block download) check that hash matches known values

            var totalWork = TotalWork();

            UtxoLookup = _BlockChain.UtxoLookupFactory(_DbTx, true);


            if (handleBranch)             // make a branch block main
            {
                if (!ExtendMain(QueueActions, totalWork))
                {
                    Result = new BkResult(BkResultEnum.Rejected);
                    return;
                }
            }
            else if (!IsNewGreatestWork(totalWork))
            {
                blockChain.BlockStore.Put(dbTx, bkHash, bk, LocationEnum.Branch, totalWork);
            }
            else if (blockChain.BlockStore.IsLocation(dbTx, bk.header.parent, LocationEnum.Main))
            {
                if (!ExtendMain(QueueActions, totalWork))
                {
                    BlockChainTrace.Information($"block {_Bk.header.blockNumber} rejected", bk);
                    Result = new BkResult(BkResultEnum.Rejected);
                    return;
                }
            }
            else
            {
                BlockChainTrace.Information($"block {bk.header.blockNumber} extends a branch with new difficulty", bk);

                Reorg();
            }

            BlockChainTrace.Information($"block {bk.header.blockNumber} accepted", bk);
            Result = new BkResult(BkResultEnum.Accepted);
        }