private byte[] PrepareEd25519PrecompileCall(HashProvider hashProvider, FfiWrapper cryptoContext, IPrivateKey signingPrivateKey, IPrivateKey otherPrivateKey) { var data = Encoding.UTF8.GetBytes("Testing testing 1 2 3"); var message = hashProvider.ComputeMultiHash(data).Digest; var signingContext = Encoding.UTF8.GetBytes("Testing testing 1 2 3 context"); var context = hashProvider.ComputeMultiHash(signingContext).Digest; ISignature signature = cryptoContext.Sign(signingPrivateKey, message, context); var signatureBytes = signature.SignatureBytes; var publicKeyBytes = otherPrivateKey.GetPublicKey().Bytes; // below verify check is not needed but allows for greater confidence for any person in the future // that would approach and debug test when it goes wrong // ===================================================== cryptoContext.Verify(signature, message, context) .Should().BeTrue("signature generated with private key should verify with corresponding public key"); // ===================================================== // save message hash in memory at position 0x00 string pushToMemoryAt0 = "7f" + message.ToHexString(false) + "600052"; // save first 32 bytes of the sig in memory starting from position 0x20 string pushToMemoryAt32 = "7f" + signatureBytes.AsSpan(0, 32).ToHexString(false) + "602052"; // save remaining 32 bytes of the sig in memory starting from position 0x40 string pushToMemoryAt64 = "7f" + signatureBytes.AsSpan(32, 32).ToHexString(false) + "604052"; // save context bytes in memory starting from position 0x60 (but this should be changed if context is smaller) string pushToMemoryAt96 = "7f" + context.ToHexString(false) + "606052"; // save public key bytes in memory starting from position 0x80 (but this should be changed if context is smaller) string pushToMemoryAt128 = "7f" + publicKeyBytes.ToHexString(false) + "608052"; // address of the precompile within Catalyst string addressCode = GetEd25519PrecompileAddressAsHex(); var byteCode = Bytes.FromHexString( pushToMemoryAt0 + pushToMemoryAt32 + pushToMemoryAt64 + pushToMemoryAt96 + pushToMemoryAt128 + // PUSH1 32 PUSH1 0 PUSH1 160 PUSH1 0 PUSH20 address GAS STATICCALL // make a call to precompile and pass [0,160) bytes of memory as an input // and store result at [0,1) of memory array // allow precompile to use all the gas required "6001600060a0600073" + addressCode + "45fa00"); TestContext.WriteLine(byteCode.ToHexString()); return(byteCode); }
public void Ed25519_precompile_can_verify_correct_sig() { HashProvider hashProvider = new HashProvider(HashingAlgorithm.GetAlgorithmMetadata("blake2b-256")); FfiWrapper cryptoContext = new FfiWrapper(); IPrivateKey signingPrivateKey = cryptoContext.GeneratePrivateKey(); var signingPublicKeyBytes = signingPrivateKey.GetPublicKey().Bytes; var byteCode = PrepareEd25519PrecompileCall(hashProvider, cryptoContext, signingPrivateKey, signingPrivateKey); GethLikeTxTracer txTracer = RunVirtualMachine(byteCode); EthereumJsonSerializer serializer = new EthereumJsonSerializer(); GethLikeTxTrace trace = txTracer.BuildResult(); TestContext.WriteLine(serializer.Serialize(trace, true)); trace.Entries.Last().Stack.First().Should().Be("0000000000000000000000000000000000000000000000000000000000000001"); trace.Entries.Last().Memory.First().Should().StartWith("01"); }