Esempio n. 1
0
        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);
            }
        }
Esempio n. 2
0
 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);
     }
 }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
            }
        }