Skip to content
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

Feature/lit 1697 js sdk fix combine shares when above threshold #238

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
7 changes: 6 additions & 1 deletion packages/crypto/src/lib/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ export const combineEcdsaShares = (
sigShares: Array<SigShare>
): CombinedECDSASignature => {
const type = sigShares[0].sigType;

if (!type) {
throw new Error("Sig type is not defined! Here's your sigShares:", sigShares);
}

// the public key can come from any node - it obviously will be identical from each node
// const publicKey = sigShares[0].publicKey;
// const dataSigned = '0x' + sigShares[0].dataSigned;
Expand All @@ -190,7 +195,7 @@ export const combineEcdsaShares = (
if (val.signatureShare !== '') {
const newVal = _remapKeyShareForEcdsa(val);

if(!newVal.sig_name){
if (!newVal.sig_name) {
newVal.sig_name = 'sig-created-by-lit-sdk';
}

Expand Down
112 changes: 103 additions & 9 deletions packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -996,7 +996,9 @@ export class LitNodeClientNodeJs extends LitCore {

shares.sort((a: any, b: any) => a.shareIndex - b.shareIndex);

const sigShares: Array<SigShare> = shares.map((s: any) => {
const sigShares: Array<SigShare> = shares.map((s: any, index: number) => {

console.log("Original Share Struct:", s);
const share = this._getFlattenShare(s);

log("share:", share);
Expand All @@ -1006,9 +1008,15 @@ export class LitNodeClientNodeJs extends LitCore {
}

if (!share.bigr) {
throw new Error("bigR is missing");
throw new Error(`bigR is missing in share ${index}. share ${JSON.stringify(share)}`);
}

const sanitisedBigR = sanitise(share.bigr);
const sanitisedSigShare = sanitise(share.publicKey);

log("sanitisedBigR:", sanitisedBigR);
log("sanitisedSigShare:", sanitisedSigShare);

return {
sigType: share.sigType,
signatureShare: sanitise(share.signatureShare),
Expand Down Expand Up @@ -1085,15 +1093,50 @@ export class LitNodeClientNodeJs extends LitCore {
*/
getSignatures = (signedData: Array<any>): any => {
log(`getSignatures(): ${JSON.stringify(signedData, null, 2)}`);

const validatedSignedData = signedData.map((sigObj: any) => {

// -- detect whatever signature is available
let signature;
for (let key in sigObj) {
if (sigObj[key]) {
signature = sigObj[key];
break;
}
}

const requiredFields = ["signatureShare"];

for (const field of requiredFields) {
log("Checking signature:", signature);

if (!signature[field] || signature[field] === '') {
log(`Invalid signed data. ${field} is missing. Not a problem, we only need ${this.config.minNodeCount} nodes to sign the session key.`);
return null;
}
}

return sigObj
}).filter((sigObj) => sigObj !== null);


log("requested length:", signedData.length);
log("validated length:", validatedSignedData.length);
log("minimum required length:", this.config.minNodeCount);

if (validatedSignedData.length < this.config.minNodeCount) {
throw new Error(`not enough nodes to get the signatures. Expected ${this.config.minNodeCount}, got ${validatedSignedData.length}`);
}

// -- prepare
const signatures: any = {};

// TOOD: get keys of signedData
const keys = Object.keys(signedData[0]);
const keys = Object.keys(validatedSignedData[0]);

// -- execute
keys.forEach((key: any) => {
const shares = signedData.map((r: any) => r[key]);
const shares = validatedSignedData.map((r: any) => r[key]);

shares.sort((a: any, b: any) => a.shareIndex - b.shareIndex);

Expand All @@ -1113,6 +1156,29 @@ export class LitNodeClientNodeJs extends LitCore {

log('getSignatures - sigShares', sigShares);

const validatedSigShares = sigShares.filter((s: any) => {

const requiredFields = ['sigType', 'signatureShare'];

for (const field of requiredFields) {
if (!s[field] || s[field] === '') {
log(`Invalid signed data. ${field} is missing. Not a problem, we only need ${this.config.minNodeCount} nodes to sign the session key.`);
return null;
}
}

return s;

}).filter((s) => s !== null);

log("requested length:", signedData.length);
log("validated length:", validatedSigShares.length);
log("minimum required length:", this.config.minNodeCount);

if (validatedSigShares.length < this.config.minNodeCount) {
throw new Error(`not enough nodes to get the signatures. Expected ${this.config.minNodeCount}, got ${validatedSigShares.length}`);
}

const sigType = mostCommonString(sigShares.map((s: any) => s.sigType));

// -- validate if this.networkPubKeySet is null
Expand Down Expand Up @@ -1431,7 +1497,7 @@ export class LitNodeClientNodeJs extends LitCore {
authMethods,
};

log("XXX reqBody:", reqBody)
log("reqBody:", reqBody)

return this.getPkpSignExecutionShares(url, reqBody, requestId);
});
Expand Down Expand Up @@ -2031,7 +2097,7 @@ export class LitNodeClientNodeJs extends LitCore {
};


log('XXX signSessionKey body', body);
log('signSessionKey body', body);

const nodePromises = this.getNodePromises((url: string) => {
return this.getSignSessionKeyShares(
Expand All @@ -2052,7 +2118,7 @@ export class LitNodeClientNodeJs extends LitCore {
throw new Error(`Error when handling node promises: ${e}`);
}

log("XXX res:", res);
log("handleNodePromises res:", res);

// -- case: promises rejected
if (!this.#isSuccessNodePromises(res)) {
Expand All @@ -2069,9 +2135,37 @@ export class LitNodeClientNodeJs extends LitCore {
(r: any) => (r as SignedData).signedData
);

log('signedDataList', signedDataList)
log('signedDataList', signedDataList);

// -- checking if we have enough shares
const validatedSignedDataList = signedDataList.map((signedData: any) => {

const sessionSig = signedData['sessionSig'];

// each of this field cannot be empty
const requiredFields = ["sigType", 'dataSigned', 'signatureShare', 'bigr', 'publicKey', 'sigName', 'siweMessage'];

// check if all required fields are present
for (const field of requiredFields) {

if (!sessionSig[field] || sessionSig[field] === '') {
log(`Invalid signed data. ${field} is missing. Not a problem, we only need ${this.config.minNodeCount} nodes to sign the session key.`);
return null;
}
}

return signedData;
}).filter(item => item !== null);

log("requested length:", signedDataList.length);
log("validated length:", validatedSignedDataList.length);
log("minimum required length:", this.config.minNodeCount);

if (validatedSignedDataList.length < this.config.minNodeCount) {
throw new Error(`not enough nodes signed the session key. Expected ${this.config.minNodeCount}, got ${validatedSignedDataList.length}`);
}

const signatures = this.getSessionSignatures(signedDataList);
const signatures = this.getSessionSignatures(validatedSignedDataList);

const { sessionSig } = signatures;

Expand Down