Пример #1
0
 public SuperConnectEventArgs(SuperNode superNode)
 {
     SuperNode = superNode;
 }
Пример #2
0
        private void Client_ReceiveBroadcast(object?sender, BroadcastEventArgs e)
        {
            // 只处理超级节点上线广播
            // 1 bytes: 0xff
            // 1 bytes: ip版本
            // 16,4 bytes: ip
            // 2 bytes: port
            // 4 bytes: 区块链时间戳(超过1小时丢弃)
            // 32 bytes: 随机数
            // 64 bytes: 超级节点公钥
            // 64 bytes: 签名
            if (e.Message.Length > 0 && e.Message[0] is 0xff)
            {
                ReadOnlyMemory <byte> data = e.Message.AsMemory(1);
                int       ipBytes;
                IPAddress ipAddress;
                if (data.Span[0] is 4)
                {
                    ipAddress = new IPAddress(data.Span.Slice(1, 4));
                    ipBytes   = 4;
                }
                else if (data.Span[0] is 6)
                {
                    ipAddress = new IPAddress(data.Span.Slice(1, 16));
                    ipBytes   = 16;
                }
                else
                {
                    goto CancelForward;
                }

                int port     = BinaryPrimitives.ReadUInt16BigEndian(data.Span.Slice(1 + ipBytes));
                var endPoint = new IPEndPoint(ipAddress, port);

                var time = BlockChainTimestamp.ToDateTime(BinaryPrimitives.ReadUInt32BigEndian(data.Span.Slice(3 + ipBytes)));
                if (DateTime.Now - time >= TimeSpan.FromHours(1) || time - DateTime.Now >= TimeSpan.FromMinutes(5))
                {
                    goto CancelForward;                                                                                                 // 过期,丢弃并阻断广播
                }
                var(publicKey, _) = Deserializer.PublicKeyStruct(data.Span.Slice(39 + ipBytes));
                var address = publicKey.ToAddress();
                if (!client.System.ImmutableCampaignNodes.TryGetValue(address, out SuperNode? oldSuperNode))
                {
                    goto CancelForward;                                                                                          // 非竞选节点,丢弃并阻断广播
                }
                var(sign, _) = Deserializer.Signature(data.Span.Slice(103 + ipBytes));
                if (!Ecdsa.Verify(publicKey, data.Span.Slice(0, 103 + ipBytes).MessageHash(), sign))
                {
                    goto CancelForward;                                                                                  // 错误的签名,丢弃并阻断广播
                }
                SuperNode superNode;
                if (endPoint.Equals(oldSuperNode?.IPEndPoint))   // IP 端口与本地保存的一致
                {
                    superNode = oldSuperNode;
                }
                else
                {
                    superNode = new SuperNode(publicKey, endPoint);
                    client.System.ImmutableCampaignNodes[address] = superNode;
                }

                if (client.System.IsProducer(address) && !superNode.Connected)
                {
                    e.Task = superNode.ConnectAsync().ContinueWith(task => {
                        task.Wait();
                    });
                }
            }
            return;

CancelForward:
            e.CancelForward();
        }
Пример #3
0
 public SuperEventArgs(NetworkStream stream, BDict dict, SuperNode node)
 {
     Stream = stream;
     Dict   = dict;
     Node   = node;
 }
Пример #4
0
        private async void HandleClient(Socket clientSocket)
        {
            try {
                clientSocket.NoDelay = true;

                using var stream = new NetworkStream(clientSocket, ownsSocket: true)
                      {
                          ReadTimeout  = 3000,
                          WriteTimeout = 3000,
                      };

                var messageBuffer = new byte[64];
                random.Value !.NextBytes(messageBuffer.AsSpan(0, 32));
                await stream.WriteAsync(messageBuffer.AsMemory(0, 32), cancellationTokenSource.Token);

                // 32字节另一半消息
                // 64字节公钥
                // 64字节签名
                var buffer = new byte[160];
                await stream.FillAsync(buffer, cancellationTokenSource.Token);

                buffer.AsSpan(0, 32).CopyTo(messageBuffer.AsSpan(32));
                byte[] messageHash = Sha256.ComputeHashToArray(messageBuffer);
                if (messageHash[0] != 0)
                {
                    return;                      // 工作量证明,hash前8位必须是0
                }
                var(pubkey, sign) = ReadPublicKeySignature(buffer.AsSpan(32));
                var superAddress = pubkey.ToAddress();
                if (!system.IsProducer(superAddress))
                {
                    return;
                }
                if (!Secp256k1.Secp256k1.Verify(pubkey, messageHash, sign))
                {
                    return;
                }

                // 认证通过,开始处理请求
                stream.ReadTimeout = -1;
                var clientNode = new SuperNode(pubkey, (IPEndPoint)clientSocket.RemoteEndPoint, isReadOnly: true)
                {
                    ClientSocket = clientSocket
                };
                ClientConnected?.Invoke(this, new SuperNodeEventArgs(clientNode, Array.Empty <byte>()));

                try {
                    var arrayPool = ArrayPool <byte> .Create(65536, 1);

                    while (cancellationTokenSource.IsCancellationRequested is false && clientSocket.Connected)
                    {
                        var packetLength = await stream.ReadStructAsync <int>(cancellationTokenSource.Token);

                        if (BitConverter.IsLittleEndian is false)
                        {
                            packetLength = BinaryPrimitives.ReverseEndianness(packetLength);
                        }
                        if (packetLength is 0 || packetLength > 10485760)
                        {
                            return;
                        }

                        byte[] packetBuffer = arrayPool.Rent(packetLength);
                        await stream.FillAsync(packetBuffer.AsMemory(0, packetLength), cancellationTokenSource.Token);

                        // TODO: 处理请求
                        DataArrived?.Invoke(this, new SuperNodeEventArgs(clientNode, packetBuffer.AsMemory(0, packetLength)));

                        arrayPool.Return(packetBuffer);
                    }
                } catch {
                }
                Closed?.Invoke(this, new SuperNodeEventArgs(clientNode, Array.Empty <byte>()));
            } catch {
            }
Пример #5
0
 public SuperNodeEventArgs(SuperNode superNode, ReadOnlyMemory <byte> data)
 {
     SuperNode = superNode;
     Data      = data;
 }