/// <summary> /// First step of the connect/auth process. Used to initiate a connection. The provided payload should be the /// clients authentication information. When receiving this call, protocol dictates you send the client your auth /// information. The response says whether or not you can connect. /// </summary> public override async Task <ConnectReply> Connect(Handshake handshake, ServerCallContext context) { Logger.LogTrace($"{context.Peer} has initiated a connection request."); if (handshake?.HskData == null) { return new ConnectReply { Err = AuthError.InvalidHandshake } } ; // verify chain id if (handshake.HskData.ChainId != _blockChainService.GetChainId()) { return new ConnectReply { Err = AuthError.ChainMismatch } } ; // verify protocol if (handshake.HskData.Version != KernelConstants.ProtocolVersion) { return new ConnectReply { Err = AuthError.ProtocolMismatch } } ; // verify signature var validData = await _accountService.VerifySignatureAsync(handshake.Sig.ToByteArray(), Hash.FromMessage(handshake.HskData).ToByteArray(), handshake.HskData.PublicKey.ToByteArray()); if (!validData) { return new ConnectReply { Err = AuthError.WrongSig } } ; var peer = GrpcUrl.Parse(context.Peer); if (peer == null) { return new ConnectReply { Err = AuthError.InvalidPeer } } ; var peerAddress = peer.IpAddress + ":" + handshake.HskData.ListeningPort; Logger.LogDebug($"Attempting to create channel to {peerAddress}"); Channel channel = new Channel(peerAddress, ChannelCredentials.Insecure); var client = new PeerService.PeerServiceClient(channel.Intercept(metadata => { metadata.Add(GrpcConsts.PubkeyMetadataKey, AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex()); return(metadata); })); if (channel.State != ChannelState.Ready) { var c = channel.WaitForStateChangedAsync(channel.State); } var pubKey = handshake.HskData.PublicKey.ToHex(); var grpcPeer = new GrpcPeer(channel, client, pubKey, peerAddress); // Verify auth bool valid = _peerPool.IsAuthenticatePeer(pubKey); if (!valid) { await channel.ShutdownAsync(); Logger.LogDebug($"Failed to reach {grpcPeer}"); return(new ConnectReply { Err = AuthError.WrongAuth }); } // send our credentials var hsk = await _peerPool.GetHandshakeAsync(); // If auth ok -> add it to our peers _peerPool.AddPeer(grpcPeer); return(new ConnectReply { Handshake = hsk }); }