Skip to content

[rc-naga-2025-01-30] Compatibility #786

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 22 commits into
base: feat/naga-fix-bls-wasm-cleanup
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
756eb2c
add combiner for all
mikelodder7 Jan 27, 2025
eb24a01
fix generic-array version
mikelodder7 Jan 27, 2025
4ab5e93
remove unneeded code
mikelodder7 Jan 28, 2025
d3a198b
add tests for combine_and_verify that also print the results
mikelodder7 Jan 30, 2025
80b49b2
Merge pull request #779 from LIT-Protocol/ml/combine_all_signatures
Ansonhkg Jan 31, 2025
5d4ab05
feat: use rust unified combiner to support frost and multiple ecdsa s…
FedericoAmura Feb 11, 2025
63ac695
Merge branch 'refs/heads/feat/naga-fix-bls-wasm-cleanup' into feat/rc…
FedericoAmura Feb 12, 2025
e0b7b66
Merge branch 'refs/heads/feat/rc-naga-2025-01-30b' into feature/lit-4…
FedericoAmura Feb 12, 2025
fcc5757
feat: building fixes and cleanup
FedericoAmura Feb 12, 2025
6e736ff
feat: restore claims inside lit actions signature aggregation
FedericoAmura Feb 12, 2025
42a380f
feat: types unification
FedericoAmura Feb 12, 2025
d617a04
feat: removed unused types and executeJs return fixes
FedericoAmura Feb 12, 2025
f6213a4
feat: update PKPWallets with new signing schemes
FedericoAmura Feb 13, 2025
3112779
feat: linting fixes
FedericoAmura Feb 13, 2025
fe4c47b
feat: a missing linting fix that should complete ci check
FedericoAmura Feb 13, 2025
b04daad
fix: failing unit tests
FedericoAmura Feb 13, 2025
0f7a88e
fix: circular reference with PRODUCT_IDS
FedericoAmura Feb 14, 2025
341ea36
feat: clean ecdsa wasm
FedericoAmura Feb 14, 2025
b2734b7
feat: update pkpSign test to use verify all signing schemes and remov…
FedericoAmura Feb 14, 2025
976e3d7
feat: comment bls usage on pkpSign as it will not be supported yet
FedericoAmura Feb 14, 2025
685f759
feat: remove types import in constants
FedericoAmura Feb 17, 2025
df88cf5
Merge pull request #799 from LIT-Protocol/feature/lit-4007-js-sdk-add…
FedericoAmura Mar 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions local-tests/build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const createBuildConfig = (entry, outfile, globalName) => ({
format: 'esm',
inject: [getPath('./shim.mjs')],
mainFields: ['module', 'main'],
sourcemap: true,
...(globalName ? { globalName } : {}),
});

Expand Down
24 changes: 12 additions & 12 deletions local-tests/setup/tinny-environment.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { LitContracts } from '@lit-protocol/contracts-sdk';
import { LitNodeClient } from '@lit-protocol/lit-node-client';
import {
AuthSig,
LitContractContext,
LitContractResolverContext,
} from '@lit-protocol/types';
import { ProcessEnvs, TinnyEnvConfig } from './tinny-config';
import { TinnyPerson } from './tinny-person';
import { ethers, Signer } from 'ethers';

import { createSiweMessage, generateAuthSig } from '@lit-protocol/auth-helpers';
import {
CENTRALISATION_BY_NETWORK,
LIT_NETWORK,
LIT_NETWORK_VALUES,
PRODUCT_IDS,
RPC_URL_BY_NETWORK,
} from '@lit-protocol/constants';
import { ethers, Signer } from 'ethers';
import { LitContracts } from '@lit-protocol/contracts-sdk';
import { LitNodeClient } from '@lit-protocol/lit-node-client';
import {
AuthSig,
LitContractContext,
LitContractResolverContext,
} from '@lit-protocol/types';

import { ShivaClient, TestnetClient } from './shiva-client';
import { ProcessEnvs, TinnyEnvConfig } from './tinny-config';
import { TinnyPerson } from './tinny-person';
import { toErrorWithMessage } from './tinny-utils';

console.log('checking env', process.env['DEBUG']);
Expand Down Expand Up @@ -49,7 +49,7 @@ export class TinnyEnvironment {
DEBUG: process.env['DEBUG'] === 'true',
REQUEST_PER_KILOSECOND:
parseInt(process.env['REQUEST_PER_KILOSECOND']) ||
(process.env['NETWORK'] as LIT_NETWORK_VALUES) === 'datil-dev'
(process.env['NETWORK'] as LIT_NETWORK_VALUES) === LIT_NETWORK.NagaDev
? 1
: 200,
LIT_RPC_URL: process.env['LIT_RPC_URL'],
Expand Down
10 changes: 4 additions & 6 deletions local-tests/setup/tinny-person.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ export class TinnyPerson {
public authMethodOwnedPkp: PKPInfo;

// Pass this to data to sign
public loveLetter: Uint8Array = ethers.utils.arrayify(
ethers.utils.keccak256([1, 2, 3, 4, 5])
);
public loveLetter: Uint8Array = new Uint8Array([1, 2, 3, 4, 5]);

public provider: ethers.providers.StaticJsonRpcProvider;

Expand Down Expand Up @@ -156,9 +154,9 @@ export class TinnyPerson {
this.pkp = walletMintRes.pkp;

/**
* ====================================
* Mint a PKP wiuth eth wallet auth method
* ====================================
* ======================================
* Mint a PKP with eth wallet auth method
* ======================================
*/
console.log(
'[𐬺🧪 Tinny Person𐬺] Minting a PKP with eth wallet auth method...'
Expand Down
246 changes: 185 additions & 61 deletions local-tests/tests/testUseEoaSessionSigsToPkpSign.ts
Original file line number Diff line number Diff line change
@@ -1,86 +1,210 @@
import { ethers } from 'ethers';
import { p256 } from '@noble/curves/p256';
import { p384 } from '@noble/curves/p384';
import { secp256k1 } from '@noble/curves/secp256k1';
import { hexToBytes } from '@noble/hashes/utils';

import {
UnknownSignatureError,
EcdsaSigType,
SigType,
} from '@lit-protocol/constants';
import { hashLitMessage } from '@lit-protocol/crypto';
import { log } from '@lit-protocol/misc';

import { getEoaAuthContext } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';

interface SigningSchemeConfig {
hasRecoveryId?: boolean;
hashesMessage: boolean;
recoversPublicKey?: boolean;
signingScheme: SigType;
}

// Map the right curve function per signing scheme
export const ecdsaCurveFunctions: Record<EcdsaSigType, any> = {
EcdsaK256Sha256: secp256k1,
EcdsaP256Sha256: p256,
EcdsaP384Sha384: p384,
} as const;

/**
* Test Commands:
* ✅ NETWORK=datil-dev yarn test:local --filter=testUseEoaSessionSigsToPkpSign
* ✅ NETWORK=datil-test yarn test:local --filter=testUseEoaSessionSigsToPkpSign
* ✅ NETWORK=naga-dev yarn test:local --filter=testUseEoaSessionSigsToPkpSign
* ✅ NETWORK=naga-test yarn test:local --filter=testUseEoaSessionSigsToPkpSign
* ✅ NETWORK=custom yarn test:local --filter=testUseEoaSessionSigsToPkpSign
*/
export const testUseEoaSessionSigsToPkpSign = async (
devEnv: TinnyEnvironment
) => {
const alice = await devEnv.createRandomPerson();
const signingSchemeConfigs: SigningSchemeConfig[] = [
// BLS
// {
// signingScheme: 'Bls12381', // TODO nodes accept this signing scheme but they throw an unexpected error
// hashesMessage: false,
// },
// {
// signingScheme: 'Bls12381G1ProofOfPossession',
// hashesMessage: false,
// },
// ECDSA
{
hasRecoveryId: true,
hashesMessage: true,
recoversPublicKey: true,
signingScheme: 'EcdsaK256Sha256',
},
{
hasRecoveryId: true,
hashesMessage: true,
recoversPublicKey: true,
signingScheme: 'EcdsaP256Sha256',
},
{
hasRecoveryId: true,
hashesMessage: true,
recoversPublicKey: true,
signingScheme: 'EcdsaP384Sha384',
},
// FROST
{
signingScheme: 'SchnorrEd25519Sha512',
hashesMessage: false,
},
{
signingScheme: 'SchnorrK256Sha256',
hashesMessage: false,
},
{
signingScheme: 'SchnorrP256Sha256',
hashesMessage: false,
},
{
signingScheme: 'SchnorrP384Sha384',
hashesMessage: false,
},
{
signingScheme: 'SchnorrRistretto25519Sha512',
hashesMessage: false,
},
{
signingScheme: 'SchnorrEd448Shake256',
hashesMessage: false,
},
{
signingScheme: 'SchnorrRedJubjubBlake2b512',
hashesMessage: false,
},
{
signingScheme: 'SchnorrK256Taproot',
hashesMessage: false,
},
{
signingScheme: 'SchnorrRedDecaf377Blake2b512',
hashesMessage: false,
},
{
signingScheme: 'SchnorrkelSubstrate',
hashesMessage: false,
},
];

// const eoaSessionSigs = await getEoaSessionSigs(devEnv, alice);
const runWithSessionSigs = await devEnv.litNodeClient.pkpSign({
toSign: alice.loveLetter,
pubKey: alice.pkp.publicKey,
authContext: getEoaAuthContext(devEnv, alice),
});
for (const signingSchemeConfig of signingSchemeConfigs) {
try {
const signingScheme = signingSchemeConfig.signingScheme;
log(`Checking testUseEoaSessionSigsToPkpSign for ${signingSchemeConfig}`);

devEnv.releasePrivateKeyFromUser(alice);
const pkpSignature = await devEnv.litNodeClient.pkpSign({
pubKey: alice.pkp.publicKey,
authContext: getEoaAuthContext(devEnv, alice),
messageToSign: alice.loveLetter,
signingScheme,
});

// Expected output:
// {
// r: "25fc0d2fecde8ed801e9fee5ad26f2cf61d82e6f45c8ad1ad1e4798d3b747fd9",
// s: "549fe745b4a09536e6e7108d814cf7e44b93f1d73c41931b8d57d1b101833214",
// recid: 1,
// signature: "0x25fc0d2fecde8ed801e9fee5ad26f2cf61d82e6f45c8ad1ad1e4798d3b747fd9549fe745b4a09536e6e7108d814cf7e44b93f1d73c41931b8d57d1b1018332141c",
// publicKey: "04A3CD53CCF63597D3FFCD1DF1E8236F642C7DF8196F532C8104625635DC55A1EE59ABD2959077432FF635DF2CED36CC153050902B71291C4D4867E7DAAF964049",
// dataSigned: "7D87C5EA75F7378BB701E404C50639161AF3EFF66293E9F375B5F17EB50476F4",
// }
devEnv.releasePrivateKeyFromUser(alice);

// -- assertions
// r, s, dataSigned, and public key should be present
if (!runWithSessionSigs.r) {
throw new Error(`Expected "r" in runWithSessionSigs`);
}
if (!runWithSessionSigs.s) {
throw new Error(`Expected "s" in runWithSessionSigs`);
}
if (!runWithSessionSigs.dataSigned) {
throw new Error(`Expected "dataSigned" in runWithSessionSigs`);
}
if (!runWithSessionSigs.publicKey) {
throw new Error(`Expected "publicKey" in runWithSessionSigs`);
}
// -- Combined signature format assertions
for (const hexString of [
'signature',
'verifyingKey',
'signedData',
'publicKey',
]) {
if (
!pkpSignature[hexString] ||
!pkpSignature[hexString].startsWith('0x')
) {
throw new Error(
`Expected "${hexString}" hex string in pkpSignature. Signing Scheme: ${signingScheme}`
);
}
}
// Verify correct recoveryId
if (
signingSchemeConfig.hasRecoveryId
? ![0, 1].includes(pkpSignature.recoveryId)
: pkpSignature.recoveryId !== null
) {
throw new Error(
`Expected "recoveryId" to be 0/1 for ECDSA and "null" for the rest of curves. Signing Scheme: ${signingScheme}`
);
}

// signature must start with 0x
if (!runWithSessionSigs.signature.startsWith('0x')) {
throw new Error(`Expected "signature" to start with 0x`);
}
if (signingSchemeConfig.recoversPublicKey) {
const curve = ecdsaCurveFunctions[signingScheme];
const signatureBytes = hexToBytes(
pkpSignature.signature.replace(/^0x/, '')
);
const signature = curve.Signature.fromCompact(
signatureBytes
).addRecoveryBit(pkpSignature.recoveryId);

// recid must be parseable as a number
if (isNaN(runWithSessionSigs.recid)) {
throw new Error(`Expected "recid" to be parseable as a number`);
}
const msgHash = hexToBytes(pkpSignature.signedData.replace(/^0x/, ''));
const recoveredPubKeyBytes = signature.recoverPublicKey(msgHash);
const recoveredPubKey = recoveredPubKeyBytes.toHex(false);

const signature = ethers.utils.joinSignature({
r: '0x' + runWithSessionSigs.r,
s: '0x' + runWithSessionSigs.s,
recoveryParam: runWithSessionSigs.recid,
});
const recoveredPubKey = ethers.utils.recoverPublicKey(
alice.loveLetter,
signature
);
if (pkpSignature.publicKey.replace('0x', '') !== recoveredPubKey) {
throw new Error(
`Expected recovered public key to match nodesPublicKey`
);
}
// PKP public key lives in k256, it cannot be directly compared in any other curve
if (
signingScheme === 'EcdsaK256Sha256' &&
alice.pkp.publicKey !== recoveredPubKey
) {
throw new Error(
`Expected recovered public key to match alice.pkp.publicKey. Signing Scheme: ${signingSchemeConfig}`
);
}
}

console.log('recoveredPubKey:', recoveredPubKey);
const messageHash = signingSchemeConfig.hashesMessage
? hashLitMessage(signingScheme as EcdsaSigType, alice.loveLetter)
: alice.loveLetter;
const messageHashHex = Buffer.from(messageHash).toString('hex');
if (pkpSignature.signedData.replace('0x', '') !== messageHashHex) {
throw new Error(
`Expected signed data to match hashLitMessage(signingScheme, alice.loveLetter). Signing Scheme: ${signingScheme}`
);
}

if (recoveredPubKey !== `0x${runWithSessionSigs.publicKey.toLowerCase()}`) {
throw new Error(
`Expected recovered public key to match runWithSessionSigs.publicKey`
);
}
if (recoveredPubKey !== `0x${alice.pkp.publicKey.toLowerCase()}`) {
throw new Error(
`Expected recovered public key to match alice.pkp.publicKey`
);
log(`✅ testUseEoaSessionSigsToPkpSign - ${signingScheme}`);
} catch (e) {
throw new UnknownSignatureError(
{
info: {
signingSchemeConfig,
message: alice.loveLetter,
pkp: alice.pkp,
},
cause: e,
},
`Signature failed with signing scheme ${signingSchemeConfig.signingScheme}`
);
}
}

log('✅ testUseEoaSessionSigsToPkpSign');
log('✅ testUseEoaSessionSigsToPkpSign all signing schemes');
};
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@lit-protocol/contracts": "^0.0.86",
"@metamask/eth-sig-util": "5.0.2",
"@mysten/sui.js": "^0.37.1",
"@noble/curves": "^1.8.1",
"@openagenda/verror": "^3.1.4",
"@simplewebauthn/browser": "^7.2.0",
"@simplewebauthn/typescript-types": "^7.0.0",
Expand All @@ -60,6 +61,7 @@
"cross-fetch": "3.1.8",
"date-and-time": "^2.4.1",
"depd": "^2.0.0",
"elliptic": "^6.6.1",
"ethers": "^5.7.1",
"jose": "^4.14.4",
"micromodal": "^0.4.10",
Expand All @@ -70,7 +72,8 @@
"tslib": "^2.7.0",
"tweetnacl": "^1.0.3",
"tweetnacl-util": "^0.15.1",
"uint8arrays": "^4.0.3"
"uint8arrays": "^4.0.3",
"zod": "^3.24.1"
},
"devDependencies": {
"@nx/devkit": "17.3.0",
Expand All @@ -86,6 +89,7 @@
"@nx/web": "17.3.0",
"@solana/web3.js": "1.95.3",
"@types/depd": "^1.1.36",
"@types/elliptic": "^6.4.18",
"@types/events": "^3.0.3",
"@types/jest": "27.4.1",
"@types/node": "18.19.18",
Expand Down
4 changes: 0 additions & 4 deletions packages/constants/src/lib/constants/constants.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import depd from 'depd';

import { LITChain, LITCosmosChain, LITEVMChain, LITSVMChain } from './types';

const deprecated = depd('lit-js-sdk:constants:constants');

/**
* Lit Protocol Network Public Key
*/
Expand Down
Loading