public uint HandleTransactionsFromPeer(IEnumerable <TransactionReceipt> transactions, ECDSAPublicKey publicKey) { lock (_txLock) { var txs = transactions.ToArray(); Logger.LogTrace($"Received {txs.Length} transactions from peer {publicKey.ToHex()}"); var persisted = 0u; foreach (var tx in txs) { if (tx.Signature.IsZero()) { Logger.LogTrace($"Received zero-signature transaction: {tx.Hash.ToHex()}"); if (_transactionPool.Add(tx, false) == OperatingError.Ok) { persisted++; } continue; } var error = _transactionManager.Verify(tx, HardforkHeights.IsHardfork_9Active(_blockManager.GetHeight() + 1)); if (error != OperatingError.Ok) { Logger.LogTrace($"Unable to verify transaction: {tx.Hash.ToHex()} ({error})"); continue; } error = _transactionPool.Add(tx, false); if (error == OperatingError.Ok) { persisted++; } else { Logger.LogTrace($"Transaction {tx.Hash.ToHex()} not persisted: {error}"); } } lock (_peerHasTransactions) Monitor.PulseAll(_peerHasTransactions); Logger.LogTrace($"Persisted {persisted} transactions from peer {publicKey.ToHex()}"); return(persisted); } }
public void HandlePeerHasBlocks(ulong blockHeight, ECDSAPublicKey publicKey) { Logger.Log(_logLevelForSync, $"Peer {publicKey.ToHex()} has height {blockHeight}"); lock (_peerHasBlocks) { if (_peerHeights.TryGetValue(publicKey, out var peerHeight) && blockHeight <= peerHeight) { return; } _peerHeights[publicKey] = blockHeight; Monitor.PulseAll(_peerHasBlocks); } }
private ClientWorker?CreateMsgChannel(ECDSAPublicKey publicKey) { if (_messageFactory.GetPublicKey().Equals(publicKey)) { return(null); } if (_clientWorkers.TryGetValue(publicKey, out var existingWorker)) { return(existingWorker); } Logger.LogTrace($"Connecting to peer {publicKey.ToHex()}"); var worker = new ClientWorker(publicKey, _messageFactory, _hubConnector); _clientWorkers.Add(publicKey, worker); worker.Start(); return(worker); }
public bool HandleBlockFromPeer(BlockInfo blockWithTransactions, ECDSAPublicKey publicKey) { Logger.LogTrace("HandleBlockFromPeer"); lock (_blocksLock) { var block = blockWithTransactions.Block; var receipts = blockWithTransactions.Transactions; Logger.LogDebug( $"Got block {block.Header.Index} with hash {block.Hash.ToHex()} from peer {publicKey.ToHex()}"); var myHeight = _blockManager.GetHeight(); if (block.Header.Index != myHeight + 1) { Logger.LogTrace( $"Skipped block {block.Header.Index} from peer {publicKey.ToHex()}: our height is {myHeight}"); return(false); } if (!block.TransactionHashes.ToHashSet().SetEquals(receipts.Select(r => r.Hash))) { try { var needHashes = string.Join(", ", block.TransactionHashes.Select(x => x.ToHex())); var gotHashes = string.Join(", ", receipts.Select(x => x.Hash.ToHex())); Logger.LogTrace( $"Skipped block {block.Header.Index} from peer {publicKey.ToHex()}: expected hashes [{needHashes}] got hashes [{gotHashes}]"); } catch (Exception e) { Logger.LogWarning($"Failed to get transaction receipts for tx hash: {e}"); } return(false); } var error = _blockManager.VerifySignatures(block, true); if (error != OperatingError.Ok) { Logger.LogTrace($"Skipped block {block.Header.Index} from peer {publicKey.ToHex()}: invalid multisig with error: {error}"); return(false); } // This is to tell consensus manager to terminate current era, since we trust given multisig OnSignedBlockReceived?.Invoke(this, block.Header.Index); error = _stateManager.SafeContext(() => { if (_blockManager.GetHeight() + 1 == block.Header.Index) { return(_blockManager.Execute(block, receipts, commit: true, checkStateHash: true)); } Logger.LogTrace( $"We have blockchain with height {_blockManager.GetHeight()} but got block {block.Header.Index}"); return(OperatingError.BlockAlreadyExists); }); if (error == OperatingError.BlockAlreadyExists) { Logger.LogTrace( $"Skipped block {block.Header.Index} from peer {publicKey.ToHex()}: block already exists"); return(true); } if (error != OperatingError.Ok) { Logger.LogWarning( $"Unable to persist block {block.Header.Index} (current height {_blockManager.GetHeight()}), got error {error}, dropping peer"); return(false); } lock (_peerHasBlocks) Monitor.PulseAll(_peerHasBlocks); return(true); } }