Skip to content

Commit

Permalink
feat: validate length and checksum of fetched masp param
Browse files Browse the repository at this point in the history
  • Loading branch information
jurevans committed Sep 27, 2024
1 parent 5df8577 commit 97b7792
Showing 1 changed file with 85 additions and 15 deletions.
100 changes: 85 additions & 15 deletions packages/shared/lib/src/sdk/mod.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,116 @@
const PREFIX = "Namada::SDK";

const sha256Hash = async (msg: Uint8Array): Promise<string> => {
const hashBuffer = await crypto.subtle.digest("SHA-256", msg);
const hashArray = Array.from(new Uint8Array(hashBuffer));
// Return hash as hex
return hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
};

enum MaspParam {
Output = "masp-output.params",
Convert = "masp-convert.params",
Spend = "masp-spend.params",
}

type MaspParamBytes = {
param: MaspParam;
bytes: Uint8Array;
};

const MASP_PARAM_ATTR: Record<
MaspParam,
{ length: number; sha256sum: string }
> = {
[MaspParam.Output]: {
length: 16398620,
sha256sum:
"ed8b5d354017d808cfaf7b31eca5c511936e65ef6d276770251f5234ec5328b8",
},
[MaspParam.Spend]: {
length: 49848572,
sha256sum:
"62b3c60ca54bd99eb390198e949660624612f7db7942db84595fa9f1b4a29fd8",
},
[MaspParam.Convert]: {
length: 22570940,
sha256sum:
"8e049c905e0e46f27662c7577a4e3480c0047ee1171f7f6d9c5b0de757bf71f1",
},
};

const validateMaspParamBytes = async ({
param,
bytes,
}: MaspParamBytes): Promise<Uint8Array> => {
const { length, sha256sum } = MASP_PARAM_ATTR[param];

// Reject if invalid length (incomplete download or invalid)
console.log(`Validating data length for ${param}, expecting ${length}...`);

if (length !== bytes.length) {
return Promise.reject(
`Invalid data length! Expected ${length}, received ${bytes.length}!`
);
}

// Reject if invalid hash (otherwise invalid data)
console.log(`Validating sha256sum for ${param}, expecting ${sha256sum}...`);
const hash = await sha256Hash(bytes);

if (hash !== sha256sum) {
return Promise.reject(
`Invalid sha256sum! Expected ${sha256sum}, received ${hash}!`
);
}

return bytes;
};

export async function hasMaspParams(): Promise<boolean> {
return (
(await has("masp-spend.params")) &&
(await has("masp-output.params")) &&
(await has("masp-convert.params"))
(await has(MaspParam.Spend)) &&
(await has(MaspParam.Output)) &&
(await has(MaspParam.Convert))
);
}

export async function fetchAndStoreMaspParams(
url?: string
): Promise<[void, void, void]> {
return Promise.all([
fetchAndStore("masp-spend.params", url),
fetchAndStore("masp-output.params", url),
fetchAndStore("masp-convert.params", url),
fetchAndStore(MaspParam.Spend, url),
fetchAndStore(MaspParam.Output, url),
fetchAndStore(MaspParam.Convert, url),
]);
}

export async function getMaspParams(): Promise<[unknown, unknown, unknown]> {
return Promise.all([
get("masp-spend.params"),
get("masp-output.params"),
get("masp-convert.params"),
get(MaspParam.Spend),
get(MaspParam.Output),
get(MaspParam.Convert),
]);
}

export async function fetchAndStore(
params: string,
param: MaspParam,
url?: string
): Promise<void> {
const data = await fetchParams(params, url);
await set(params, data);
const data = await fetchParams(param, url);
await set(param, data);
}

export async function fetchParams(
params: string,
param: MaspParam,
url: string = "https://github.com/anoma/masp-mpc/releases/download/namada-trusted-setup/"
): Promise<Uint8Array> {
return fetch(`${url}${params}`)
return fetch(`${url}${param}`)
.then((response) => response.arrayBuffer())
.then((ab) => new Uint8Array(ab));
.then((ab) => {
const bytes = new Uint8Array(ab);
return validateMaspParamBytes({ param, bytes });
});
}

function getDB(): Promise<IDBDatabase> {
Expand Down

0 comments on commit 97b7792

Please sign in to comment.