Skip to content

Commit

Permalink
contracts: use updated abi format
Browse files Browse the repository at this point in the history
  • Loading branch information
nhynes committed Dec 10, 2022
1 parent 12c7618 commit dbf6527
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 125 deletions.
1 change: 1 addition & 0 deletions contracts/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
typechain-types/
194 changes: 69 additions & 125 deletions contracts/contracts/Sapphire.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,31 @@ library Sapphire {
0x0100000000000000000000000000000000000003;
address private constant DECRYPT =
0x0100000000000000000000000000000000000004;
address private constant GENERATE_KEYPAIR =
0x0100000000000000000000000000000000000005;
address private constant SIGN_DIGEST =
0x0100000000000000000000000000000000000006;
address private constant VERIFY_DIGEST =
0x0100000000000000000000000000000000000007;

enum SigningAlg {
// Sentinel for an unset signing alg. Do not pass this into any precompiles.
Unknown,
// Ed25519 (using SHA-512).
Ed25519,
// EdDSA using SHA-512/256 and Curve25519 with a domain separator.
// Ccan be used to sign transactions for the Oasis consensus layer and SDK paratimes.
Ed25519Oasis,
// Secp256k1 using SHA-256.
Secp256k1,
// Secp256k1 using SHA-512/256 with a domain separator.
// Ccan be used to sign transactions for the Oasis consensus layer and SDK paratimes.
Secp256k1Oasis,
// Secp256k1 using Keccak256.
// Ccan be used to sign transactions for Ethereum-compatible networks.
Secp256k1Eth,
Sr25519
}

/**
* @dev Returns cryptographically secure random bytes.
Expand Down Expand Up @@ -95,141 +120,60 @@ library Sapphire {

/**
* @dev Generate a public/private key pair using the specified method and seed.
* @param method The method to use (0 - ed25519, 1 - secp256k1, 2 - sr25519).
* @param seed The seed to use for generating the key pair.
* @return (publicKey, privateKey) The generated key pair.
* @param alg The signing alg for which to generate a keypair.
* @param seed The seed to use for generating the key pair. You can use the `randomBytes` method if you don't already have a seed.
* @return publicKey The public half of the keypair.
* @return secretKey The secret half of the keypair.
*/
function generateKeyPair(uint method, bytes memory seed) internal view returns (bytes memory publicKey, bytes memory privateKey) {
assembly {
let buf := mload(0x40)
let seedLen := mload(seed)
mstore(buf, method)
mstore(add(buf, 0x20), seedLen)
for { let i := 0 } lt(i, seedLen) { i := add(i, 0x20) } {
mstore(add(buf, add(0x40, i)), mload(add(seed, add(0x20, i))))
}
let success := staticcall(gas(), 0x0100000000000000000000000000000000000005, buf, add(0x40, seedLen), buf, 0x40)
if iszero(success) {
revert(0, 0)
}

publicKey := mload(0x40)
returndatacopy(publicKey, 0, 0x20)
let publicKeyLen := mload(publicKey)
returndatacopy(add(publicKey, 0x20), 0x40, publicKeyLen)

let rounded := and(add(publicKeyLen, 0x1f), not(0x1f))
rounded := add(rounded, 0x20)
privateKey := add(publicKey, rounded)
returndatacopy(privateKey, 0x20, 0x20)
let privateKeyLen := mload(privateKey)
rounded := add(rounded, 0x20)
returndatacopy(add(privateKey, 0x20), rounded, privateKeyLen)

let total := and(add(privateKeyLen, 0x1f), not(0x1f))
total := add(rounded, total)
mstore(0x40, add(publicKey, total))
}
function generateKeyPair(SigningAlg alg, bytes memory seed)
internal
view
returns (bytes memory publicKey, bytes memory secretKey)
{
(bool success, bytes memory keypair) = GENERATE_KEYPAIR.staticcall(
abi.encode(alg, seed)
);
require(success, "generateKeyPair: failed");
return abi.decode(keypair, (bytes, bytes));
}

/**
* @dev Sign a message within the provided context using the specified method, and return the signature.
* @param method The method to use (0 - ed25519, 1 - secp256k1, 2 - sr25519).
* @param privateKey The private key to use for signing.
* @param context The context to add to the message before signing.
* @param message The message to sign.
* @dev Sign a message within the provided context using the specified algorithm, and return the signature.
* @param alg The signing algorithm to use.
* @param secretKey The secret key to use for signing. The key must be valid for use with the requested algorithm.
* @param digest The hash of the message to sign.
* @return signature The resulting signature.
*/
function signMessageWithContext(uint method, bytes memory privateKey, bytes memory context, bytes memory message) internal view returns (bytes memory signature) {
assembly {
let buf := mload(0x40)
let privateKeyLen := mload(privateKey)
let contextLen := mload(context)
let messageLen := mload(message)
mstore(buf, method)
mstore(add(buf, 0x20), privateKeyLen)
mstore(add(buf, 0x40), contextLen)
mstore(add(buf, 0x60), messageLen)
let offset := add(buf, 0x80)
privateKeyLen := add(privateKeyLen, 0x20)
for { let i := 0x20 } lt(i, privateKeyLen) { i := add(i, 0x20) } {
mstore(offset, mload(add(privateKey, i)))
offset := add(offset, 0x20)
}
contextLen := add(contextLen, 0x20)
for { let i := 0x20 } lt(i, contextLen) { i := add(i, 0x20) } {
mstore(offset, mload(add(context, i)))
offset := add(offset, 0x20)
}
messageLen := add(messageLen, 0x20)
for { let i := 0x20 } lt(i, messageLen) { i := add(i, 0x20) } {
mstore(add(offset, i), mload(add(message, i)))
offset := add(offset, 0x20)
}
let success := staticcall(gas(), 0x0100000000000000000000000000000000000006, buf, sub(offset, buf), buf, 0x40)
if iszero(success) {
revert(0, 0)
}

signature := mload(0x40)
let signatureLen := returndatasize()
mstore(signature, signatureLen)
returndatacopy(add(signature, 0x20), 0, signatureLen)
let rounded := and(add(signatureLen, 0x1f), not(0x1f))
mstore(0x40, add(signature, add(rounded, 0x20)))
}
function signDigest(
uint256 alg,
bytes memory secretKey,
bytes memory digest
) internal view returns (bytes memory signature) {
(bool success, bytes memory sig) = SIGN_DIGEST.staticcall(
abi.encode(alg, secretKey, digest)
);
require(success, "signDigest: failed");
return sig;
}

/**
* @dev Verify that the context and message correspond to the given signature.
* @param method The method to use (0 - ed25519, 1 - secp256k1, 2 - sr25519).
* @param publicKey The public key to use to check the signature.
* @dev Verifies that the provided digest was signed with using the secret key corresponding to the provided private key and the specified signing algorithm.
* @param alg The signing algorithm by which the signature was generated.
* @param publicKey The public key against which to check the signature.
* @param digest The hash of the message that was signed.
* @param signature The signature to check.
* @param context The context to add to the message before checking.
* @param message The message to check.
* @return result The result of the verification; `True` if the verification succeeded.
* @return verified Whether the signature is valid for the given parameters.
*/
function verifySignatureWithContext(uint method, bytes memory publicKey, bytes memory signature, bytes memory context, bytes memory message) internal view returns (bool result) {
assembly {
let buf := mload(0x40)
let publicKeyLen := mload(publicKey)
let signatureLen := mload(signature)
let contextLen := mload(context)
let messageLen := mload(message)
mstore(buf, method)
mstore(add(buf, 0x20), publicKeyLen)
mstore(add(buf, 0x40), signatureLen)
mstore(add(buf, 0x60), contextLen)
mstore(add(buf, 0x80), messageLen)
let offset := add(buf, 0xa0)
publicKeyLen := add(publicKeyLen, 0x20)
for { let i := 0x20 } lt(i, publicKeyLen) { i := add(i, 0x20) } {
mstore(offset, mload(add(publicKey, i)))
offset := add(offset, 0x20)
}
signatureLen := add(signatureLen, 0x20)
for { let i := 0x20 } lt(i, signatureLen) { i := add(i, 0x20) } {
mstore(offset, mload(add(signature, i)))
offset := add(offset, 0x20)
}
contextLen := add(contextLen, 0x20)
for { let i := 0x20 } lt(i, contextLen) { i := add(i, 0x20) } {
mstore(offset, mload(add(context, i)))
offset := add(offset, 0x20)
}
messageLen := add(messageLen, 0x20)
for { let i := 0x20 } lt(i, messageLen) { i := add(i, 0x20) } {
mstore(add(offset, i), mload(add(message, i)))
offset := add(offset, 0x20)
}
let success := staticcall(gas(), 0x0100000000000000000000000000000000000007, buf, sub(offset, buf), buf, 0x40)
if iszero(success) {
revert(0, 0)
}

buf := mload(0x40)
returndatacopy(buf, 0, returndatasize())
result := mload(buf)
}
function verifyDigestSignature(
SigningAlg alg,
bytes memory publicKey,
bytes memory digest,
bytes memory signature
) internal view returns (bool verified) {
(bool success, bytes memory v) = VERIFY_DIGEST.staticcall(
abi.encode(alg, publicKey, digest, signature)
);
require(success, "verifyDigestSignature: failed");
return abi.decode(v, (bool));
}
}

0 comments on commit dbf6527

Please sign in to comment.