mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-29 15:09:22 +00:00
3f0f4d520d
If instead of intaking calls, we intake code, we can deploy a fresh contract which makes arbitrary calls *without* attempting to build our abstraction layer over the concept. This should have the same gas costs, as we still have one contract deployment. The new contract only has a constructor, so it should have no actual code and beat the Sandbox in that regard? We do have to call into ourselves to meter the gas, yet we already had to call into the deployed Sandbox to achieve that. Also re-defines the OutInstruction to include tokens, implements OutInstruction-specified gas amounts, bumps the Solidity version, and other such misc changes.
47 lines
1.7 KiB
Solidity
47 lines
1.7 KiB
Solidity
// SPDX-License-Identifier: AGPL-3.0-only
|
|
pragma solidity ^0.8.26;
|
|
|
|
// See https://github.com/noot/schnorr-verify for implementation details
|
|
library Schnorr {
|
|
// secp256k1 group order
|
|
uint256 constant private Q =
|
|
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;
|
|
|
|
// We fix the key to have:
|
|
// 1) An even y-coordinate
|
|
// 2) An x-coordinate < Q
|
|
uint8 constant private KEY_PARITY = 27;
|
|
|
|
// px := public key x-coordinate, where the public key has an even y-coordinate
|
|
// message := the message signed
|
|
// c := Schnorr signature challenge
|
|
// s := Schnorr signature solution
|
|
function verify(
|
|
bytes32 px,
|
|
bytes memory message,
|
|
bytes32 c,
|
|
bytes32 s
|
|
) internal pure returns (bool) {
|
|
// ecrecover = (m, v, r, s) -> key
|
|
// We instead pass the following to obtain the nonce (not the key)
|
|
// Then we hash it and verify it matches the challenge
|
|
bytes32 sa = bytes32(Q - mulmod(uint256(s), uint256(px), Q));
|
|
bytes32 ca = bytes32(Q - mulmod(uint256(c), uint256(px), Q));
|
|
|
|
/*
|
|
The ecrecover precompile checks `r` and `s` (`px` and `ca`) are non-zero,
|
|
banning the two keys with zero for their x-coordinate and zero challenge.
|
|
Each has negligible probability of occuring (assuming zero x-coordinates
|
|
are even on-curve in the first place).
|
|
|
|
`sa` is not checked to be non-zero yet it does not need to be. The inverse
|
|
of it is never taken.
|
|
*/
|
|
address R = ecrecover(sa, KEY_PARITY, px, ca);
|
|
// The ecrecover failed
|
|
if (R == address(0)) return false;
|
|
|
|
// Check the signature is correct by rebuilding the challenge
|
|
return c == keccak256(abi.encodePacked(R, px, message));
|
|
}
|
|
}
|