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); }
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); } }
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; } } }
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); }