Trying to implement TPU Client over MsQuic. Here is my code:
var quicClient = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions
{
DefaultStreamErrorCode = 0x0A,
DefaultCloseErrorCode = 0x0B,
RemoteEndPoint = IPEndPoint.Parse(firstLeader.Item2.TpuQuic!),
ClientAuthenticationOptions = new SslClientAuthenticationOptions
{
ClientCertificates = [mockedCert],
ApplicationProtocols = [new SslApplicationProtocol("solana-tpu")],
EnabledSslProtocols = SslProtocols.Tls13,
TargetHost = "server",
}
});
await using var streamSend = await quicClient.OpenOutboundStreamAsync(QuicStreamType.Unidirectional);
This code is failing with exception System.Net.Quic.QuicException: An internal error has occurred. Status code: QUIC_STATUS_HANDSHAKE_FAILURE
.
When I look further in Wireshark, I see slightly more informational error:
CONNECTION_CLOSE (Transport) Error code: CRYPTO_ERROR (Handshake Failure)
Frame Type: CONNECTION_CLOSE (Transport) (0x000000000000001c)
Error code: CRYPTO_ERROR (296)
TLS Alert Description: Handshake Failure (40)
Frame Type: 0
Reason phrase Length: 48
Reason phrase: peer is incompatible: NoSignatureSchemesInCommon
So I suppose, MsQuic doesn't provide such TLS Signature Algorithms, that Solana TPU Server use. There is signature algorithms from and cipher suites from my ClientHello:
Signature Hash Algorithms (12 algorithms)
Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
Signature Algorithm: rsa_pss_rsae_sha384 (0x0805)
Signature Algorithm: rsa_pss_rsae_sha512 (0x0806)
Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
Signature Algorithm: rsa_pkcs1_sha384 (0x0501)
Signature Algorithm: rsa_pkcs1_sha1 (0x0201)
Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
Signature Algorithm: ecdsa_secp384r1_sha384 (0x0503)
Signature Algorithm: ecdsa_sha1 (0x0203)
Signature Algorithm: SHA1 DSA (0x0202)
Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
Cipher Suites (2 suites)
Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
So, what can I do with it? As I can see, there is no other Quic implementations/binders (that are not outdated) in C#.
Or maybe something with my cert? I generated it once via nodejs':
import selfsigned from 'selfsigned';
const pems = selfsigned.generate([{name: 'commonName', value: 'Solana node'}, { name: "subjectAltName", value: [{ type: 7, value: "0.0.0.0" }]}], { days: 365, algorithm: 'ed25519', keySize: 2048 });
and combined it into one pfx like this:
openssl pkcs12 -export -in certificate.pem -inkey privatekey.pem -out cert-and-key.pfx
and impoting in C# like this:
var mockedCert = new X509Certificate2(@"C:\cert-and-key.pfx");
(.NET doesn't natively support Ed25519 yet)