Improved Note Encryption

This commit is contained in:
Tornado Contrib 2024-10-26 20:22:22 +00:00
parent 48774c321e
commit 42e6b1713b
Signed by: tornadocontrib
GPG Key ID: 60B4DF1A076C64B1
5 changed files with 4346 additions and 1195 deletions

5295
dist/cli.js vendored

File diff suppressed because one or more lines are too long

@ -24,11 +24,13 @@
"updateEvents": "ts-node src/cli.ts updateEvents",
"relayers": "ts-node src/cli.ts relayers",
"createAccount": "ts-node src/cli.ts createAccount",
"decryptNotes": "ts-node src/cli.ts decryptNotes",
"decrypt": "ts-node src/cli.ts decrypt",
"send": "ts-node src/cli.ts send",
"balance": "ts-node src/cli.ts balance",
"sign": "ts-node src/cli.ts sign",
"broadcast": "ts-node src/cli.ts broadcast"
"broadcast": "ts-node src/cli.ts broadcast",
"proposals": "ts-node src/cli.ts proposals",
"delegates": "ts-node src/cli.ts delegates"
},
"author": "",
"license": "MIT",
@ -51,11 +53,11 @@
"optionalDependencies": {},
"devDependencies": {
"@colors/colors": "^1.6.0",
"@tornado/core": "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#9f4044d11033e99e0a863989864d1578a93de531",
"@tornado/core": "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#8041bd7f7801fd97a87d8c1945c0251b49032ec3",
"@typechain/ethers-v6": "^0.5.1",
"@types/figlet": "^1.7.0",
"@typescript-eslint/eslint-plugin": "^8.9.0",
"@typescript-eslint/parser": "^8.9.0",
"@typescript-eslint/eslint-plugin": "^8.11.0",
"@typescript-eslint/parser": "^8.11.0",
"bloomfilter.js": "^1.0.2",
"cli-table3": "^0.6.4",
"commander": "^12.0.0",

@ -622,7 +622,6 @@ export function tornadoProgram() {
const {
multicallContract,
routerContract,
echoContract,
nativeCurrency,
tokens: { [currency]: currencyConfig },
} = config;
@ -646,13 +645,7 @@ export function tornadoProgram() {
provider,
});
const noteAccount = accountKey
? new NoteAccount({
netId,
recoveryKey: accountKey,
Echoer: Echoer__factory.connect(echoContract, provider),
})
: undefined;
const noteAccount = accountKey ? new NoteAccount({ recoveryKey: accountKey }) : undefined;
if (!signer) {
throw new Error(
@ -764,7 +757,7 @@ export function tornadoProgram() {
const { options, fetchDataOptions } = await getProgramOptions(cmdOptions);
const { rpc } = options;
const { currency, amount, netId, commitment } = new Invoice(invoiceString);
const { currency, amount, netId, commitmentHex } = new Invoice(invoiceString);
const config = getConfig(netId);
@ -854,7 +847,7 @@ export function tornadoProgram() {
await programSendTransaction({
signer,
options,
populatedTransaction: await TornadoProxy.deposit.populateTransaction(instanceAddress, commitment, '0x', {
populatedTransaction: await TornadoProxy.deposit.populateTransaction(instanceAddress, commitmentHex, '0x', {
value: isEth ? denomination : BigInt(0),
}),
});
@ -1611,7 +1604,7 @@ export function tornadoProgram() {
const {
echoContract,
constants: { ['NOTE_ACCOUNT_BLOCK']: deployedBlock },
constants: { NOTE_ACCOUNT_BLOCK },
} = config;
const provider = await getProgramProvider(rpc, {
@ -1641,20 +1634,13 @@ export function tornadoProgram() {
/**
* Find for any existing note accounts
*/
const walletPublicKey = NoteAccount.getWalletPublicKey(signer);
const Echoer = Echoer__factory.connect(echoContract, provider);
const newAccount = new NoteAccount({
netId,
Echoer,
});
const echoService = new NodeEchoService({
netId,
provider,
Echoer,
deployedBlock,
deployedBlock: NOTE_ACCOUNT_BLOCK,
fetchDataOptions,
tovarishClient,
cacheDirectory: EVENTS_DIR,
@ -1665,9 +1651,7 @@ export function tornadoProgram() {
const echoEvents = (await echoService.updateEvents()).events;
const userEvents = echoEvents.filter(({ address }) => address === signer.address);
const existingAccounts = newAccount.decryptAccountsWithWallet(signer, userEvents);
const existingAccounts = await NoteAccount.decryptSignerNoteAccounts(signer, echoEvents);
const accountsTable = new Table();
@ -1683,6 +1667,8 @@ export function tornadoProgram() {
console.log(accountsTable.toString() + '\n');
} else {
const newAccount = new NoteAccount({});
accountsTable.push(
[{ colSpan: 1, content: `New Note Account (${netId})`, hAlign: 'center' }],
['noteAccount'].map((content) => ({ content: colors.red.bold(content) })),
@ -1702,7 +1688,9 @@ export function tornadoProgram() {
await promptConfirmation(options.nonInteractive);
const { data } = newAccount.getEncryptedAccount(walletPublicKey);
const signerPublicKey = await NoteAccount.getSignerPublicKey(signer);
const { data } = newAccount.getEncryptedAccount(signerPublicKey);
console.log('Sending encrypted note account backup transaction through wallet\n');
@ -1717,8 +1705,8 @@ export function tornadoProgram() {
});
program
.command('decryptNotes')
.description('Fetch notes from deposit events and decrypt them. \n\n' + 'Requires a valid account key to work')
.command('decrypt')
.description('Fetch encryption keys and encrypted notes from on-chain. \n\n')
.argument('<netId>', 'Network Chain ID to connect with (see https://chainlist.org for examples)', parseNumber)
.argument(
'[accountKey]',
@ -1737,7 +1725,7 @@ export function tornadoProgram() {
const {
routerContract,
echoContract,
constants: { ENCRYPTED_NOTES_BLOCK },
constants: { NOTE_ACCOUNT_BLOCK, ENCRYPTED_NOTES_BLOCK },
} = config;
const provider = await getProgramProvider(rpc, {
@ -1745,12 +1733,6 @@ export function tornadoProgram() {
...fetchDataOptions,
});
if (!accountKey) {
throw new Error(
'No account key find! Please supply correct account key from either UI or find one with createAccount command',
);
}
const tovarishClient = !disableTovarish
? (await getTovarishRelayer({ options, fetchDataOptions, netId })).relayerClient
: undefined;
@ -1761,10 +1743,15 @@ export function tornadoProgram() {
const Echoer = Echoer__factory.connect(echoContract, provider);
const noteAccount = new NoteAccount({
const echoService = new NodeEchoService({
netId,
recoveryKey: accountKey,
provider,
Echoer,
deployedBlock: NOTE_ACCOUNT_BLOCK,
fetchDataOptions,
tovarishClient,
cacheDirectory: EVENTS_DIR,
userDirectory: SAVED_DIR,
});
const encryptedNotesService = new NodeEncryptedNotesService({
@ -1778,22 +1765,65 @@ export function tornadoProgram() {
userDirectory: SAVED_DIR,
});
const encryptedNoteEvents = (await encryptedNotesService.updateEvents()).events;
const accounts = [];
if (accountKey) {
accounts.push(new NoteAccount({ recoveryKey: accountKey }));
}
// Recover encryption keys possibly encrypted by a signer
const signer = getProgramSigner({
options,
provider,
}) as TornadoWallet;
if (signer?.privateKey) {
const echoEvents = (await echoService.updateEvents()).events;
accounts.push(...(await NoteAccount.decryptSignerNoteAccounts(signer, echoEvents)));
}
if (!accounts.length) {
throw new Error(
'No encryption key find! Please supply encryption key from either UI or create one with createAccount command',
);
}
const accountsTable = new Table();
accountsTable.push(
[{ colSpan: 2, content: `Note Accounts (${netId})`, hAlign: 'center' }],
[{ colSpan: 2, content: `Account key: ${accountKey}`, hAlign: 'center' }],
['blockNumber', 'note'].map((content) => ({ content: colors.red.bold(content) })),
...noteAccount.decryptNotes(encryptedNoteEvents).map(({ blockNumber, address, noteHex }) => {
const { amount, currency } = getInstanceByAddress(config, address) || {};
return [blockNumber, `tornado-${currency}-${amount}-${netId}-${noteHex}`];
[{ colSpan: 2, content: `Backed up by: ${signer?.address}`, hAlign: 'center' }],
['blockNumber', 'noteAccount'].map((content) => ({ content: colors.red.bold(content) })),
...accounts.map(({ blockNumber, recoveryKey }) => {
return [blockNumber, recoveryKey];
}),
);
console.log('\n' + accountsTable.toString() + '\n');
// Decrypting notes
const encryptedNoteEvents = (await encryptedNotesService.updateEvents()).events;
const decryptedNotes = accounts
.map((noteAccount) => noteAccount.decryptNotes(encryptedNoteEvents))
.flat()
.map(({ blockNumber, address, noteHex }) => {
const { amount, currency } = getInstanceByAddress(config, address) || {};
return [blockNumber, `tornado-${currency}-${amount}-${netId}-${noteHex}`];
});
const notesTable = new Table();
notesTable.push(
[{ colSpan: 2, content: `Note Accounts (${netId})`, hAlign: 'center' }],
[{ colSpan: 2, content: `Account key: ${accountKey}`, hAlign: 'center' }],
['blockNumber', 'note'].map((content) => ({ content: colors.red.bold(content) })),
...decryptedNotes,
);
console.log(accountsTable.toString() + '\n');
console.log('\n' + notesTable.toString() + '\n');
process.exit(0);
});

Binary file not shown.

120
yarn.lock

@ -648,10 +648,10 @@
"@metamask/superstruct" "^3.1.0"
"@metamask/utils" "^9.0.0"
"@metamask/eth-sig-util@^7.0.3":
version "7.0.3"
resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-7.0.3.tgz#be9e444fe0b8474c04e2ff42fd983173767f6ac0"
integrity sha512-PAtGnOkYvh90k2lEZldq/FK7GTLF6WxE+2bV85PoA3pqlJnmJCAY62tuvxHSwnVngSKlc4mcNvjnUg2eYO6JGg==
"@metamask/eth-sig-util@^8.0.0":
version "8.0.0"
resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-8.0.0.tgz#6310d93cd1101cab3cc6bc2a1ff526290ed2695b"
integrity sha512-IwE6aoxUL39IhmsAgE4nk+OZbNo+ThFZRNsUjE1pjdEa4MFpWzm1Rue4zJ5DMy1oUyZBi/aiCLMhdMnjl2bh2Q==
dependencies:
"@ethereumjs/util" "^8.1.0"
"@metamask/abi-utils" "^2.0.4"
@ -777,20 +777,20 @@
"@noble/hashes" "~1.4.0"
"@scure/base" "~1.1.6"
"@tornado/contracts@git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#ece511f424dc811c3aec149a4bf0e3731c0598a4":
"@tornado/contracts@git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#1b1d707878c16a3dc60d295299d4f0e7ce6ba831":
version "1.0.2"
resolved "git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#ece511f424dc811c3aec149a4bf0e3731c0598a4"
resolved "git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#1b1d707878c16a3dc60d295299d4f0e7ce6ba831"
dependencies:
"@openzeppelin/contracts" "5.0.2"
"@openzeppelin/contracts-v3" "npm:@openzeppelin/contracts@3.2.0-rc.0"
ethers "^6.13.4"
"@tornado/core@git+https://git.tornado.ws/tornadocontrib/tornado-core.git#9f4044d11033e99e0a863989864d1578a93de531":
"@tornado/core@git+https://git.tornado.ws/tornadocontrib/tornado-core.git#8041bd7f7801fd97a87d8c1945c0251b49032ec3":
version "1.0.19"
resolved "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#9f4044d11033e99e0a863989864d1578a93de531"
resolved "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#8041bd7f7801fd97a87d8c1945c0251b49032ec3"
dependencies:
"@metamask/eth-sig-util" "^7.0.3"
"@tornado/contracts" "git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#ece511f424dc811c3aec149a4bf0e3731c0598a4"
"@metamask/eth-sig-util" "^8.0.0"
"@tornado/contracts" "git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#1b1d707878c16a3dc60d295299d4f0e7ce6ba831"
"@tornado/fixed-merkle-tree" "^0.7.3"
"@tornado/snarkjs" "^0.1.20"
"@tornado/websnark" "^0.0.4"
@ -907,62 +907,62 @@
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f"
integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==
"@typescript-eslint/eslint-plugin@^8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.9.0.tgz#bf0b25305b0bf014b4b194a6919103d7ac2a7907"
integrity sha512-Y1n621OCy4m7/vTXNlCbMVp87zSd7NH0L9cXD8aIpOaNlzeWxIK4+Q19A68gSmTNRZn92UjocVUWDthGxtqHFg==
"@typescript-eslint/eslint-plugin@^8.11.0":
version "8.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz#c3f087d20715fa94310b30666c08b3349e0ab084"
integrity sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==
dependencies:
"@eslint-community/regexpp" "^4.10.0"
"@typescript-eslint/scope-manager" "8.9.0"
"@typescript-eslint/type-utils" "8.9.0"
"@typescript-eslint/utils" "8.9.0"
"@typescript-eslint/visitor-keys" "8.9.0"
"@typescript-eslint/scope-manager" "8.11.0"
"@typescript-eslint/type-utils" "8.11.0"
"@typescript-eslint/utils" "8.11.0"
"@typescript-eslint/visitor-keys" "8.11.0"
graphemer "^1.4.0"
ignore "^5.3.1"
natural-compare "^1.4.0"
ts-api-utils "^1.3.0"
"@typescript-eslint/parser@^8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.9.0.tgz#0cecda6def8aef95d7c7098359c0fda5a362d6ad"
integrity sha512-U+BLn2rqTTHnc4FL3FJjxaXptTxmf9sNftJK62XLz4+GxG3hLHm/SUNaaXP5Y4uTiuYoL5YLy4JBCJe3+t8awQ==
"@typescript-eslint/parser@^8.11.0":
version "8.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.11.0.tgz#2ad1481388dc1c937f50b2d138c9ca57cc6c5cce"
integrity sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==
dependencies:
"@typescript-eslint/scope-manager" "8.9.0"
"@typescript-eslint/types" "8.9.0"
"@typescript-eslint/typescript-estree" "8.9.0"
"@typescript-eslint/visitor-keys" "8.9.0"
"@typescript-eslint/scope-manager" "8.11.0"
"@typescript-eslint/types" "8.11.0"
"@typescript-eslint/typescript-estree" "8.11.0"
"@typescript-eslint/visitor-keys" "8.11.0"
debug "^4.3.4"
"@typescript-eslint/scope-manager@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.9.0.tgz#c98fef0c4a82a484e6a1eb610a55b154d14d46f3"
integrity sha512-bZu9bUud9ym1cabmOYH9S6TnbWRzpklVmwqICeOulTCZ9ue2/pczWzQvt/cGj2r2o1RdKoZbuEMalJJSYw3pHQ==
"@typescript-eslint/scope-manager@8.11.0":
version "8.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz#9d399ce624118966732824878bc9a83593a30405"
integrity sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==
dependencies:
"@typescript-eslint/types" "8.9.0"
"@typescript-eslint/visitor-keys" "8.9.0"
"@typescript-eslint/types" "8.11.0"
"@typescript-eslint/visitor-keys" "8.11.0"
"@typescript-eslint/type-utils@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.9.0.tgz#aa86da3e4555fe7c8b42ab75e13561c4b5a8dfeb"
integrity sha512-JD+/pCqlKqAk5961vxCluK+clkppHY07IbV3vett97KOV+8C6l+CPEPwpUuiMwgbOz/qrN3Ke4zzjqbT+ls+1Q==
"@typescript-eslint/type-utils@8.11.0":
version "8.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz#b7f9e6120c1ddee8a1a07615646642ad85fc91b5"
integrity sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==
dependencies:
"@typescript-eslint/typescript-estree" "8.9.0"
"@typescript-eslint/utils" "8.9.0"
"@typescript-eslint/typescript-estree" "8.11.0"
"@typescript-eslint/utils" "8.11.0"
debug "^4.3.4"
ts-api-utils "^1.3.0"
"@typescript-eslint/types@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.9.0.tgz#b733af07fb340b32e962c6c63b1062aec2dc0fe6"
integrity sha512-SjgkvdYyt1FAPhU9c6FiYCXrldwYYlIQLkuc+LfAhCna6ggp96ACncdtlbn8FmnG72tUkXclrDExOpEYf1nfJQ==
"@typescript-eslint/types@8.11.0":
version "8.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.11.0.tgz#7c766250502097f49bbc2e651132e6bf489e20b8"
integrity sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==
"@typescript-eslint/typescript-estree@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.9.0.tgz#1714f167e9063062dc0df49c1d25afcbc7a96199"
integrity sha512-9iJYTgKLDG6+iqegehc5+EqE6sqaee7kb8vWpmHZ86EqwDjmlqNNHeqDVqb9duh+BY6WCNHfIGvuVU3Tf9Db0g==
"@typescript-eslint/typescript-estree@8.11.0":
version "8.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz#35fe5d3636fc5727c52429393415412e552e222b"
integrity sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==
dependencies:
"@typescript-eslint/types" "8.9.0"
"@typescript-eslint/visitor-keys" "8.9.0"
"@typescript-eslint/types" "8.11.0"
"@typescript-eslint/visitor-keys" "8.11.0"
debug "^4.3.4"
fast-glob "^3.3.2"
is-glob "^4.0.3"
@ -970,22 +970,22 @@
semver "^7.6.0"
ts-api-utils "^1.3.0"
"@typescript-eslint/utils@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.9.0.tgz#748bbe3ea5bee526d9786d9405cf1b0df081c299"
integrity sha512-PKgMmaSo/Yg/F7kIZvrgrWa1+Vwn036CdNUvYFEkYbPwOH4i8xvkaRlu148W3vtheWK9ckKRIz7PBP5oUlkrvQ==
"@typescript-eslint/utils@8.11.0":
version "8.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.11.0.tgz#4480d1e9f2bb18ea3510c79f870a1aefc118103d"
integrity sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==
dependencies:
"@eslint-community/eslint-utils" "^4.4.0"
"@typescript-eslint/scope-manager" "8.9.0"
"@typescript-eslint/types" "8.9.0"
"@typescript-eslint/typescript-estree" "8.9.0"
"@typescript-eslint/scope-manager" "8.11.0"
"@typescript-eslint/types" "8.11.0"
"@typescript-eslint/typescript-estree" "8.11.0"
"@typescript-eslint/visitor-keys@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.9.0.tgz#5f11f4d9db913f37da42776893ffe0dd1ae78f78"
integrity sha512-Ht4y38ubk4L5/U8xKUBfKNYGmvKvA1CANoxiTRMM+tOLk3lbF3DvzZCxJCRSE+2GdCMSh6zq9VZJc3asc1XuAA==
"@typescript-eslint/visitor-keys@8.11.0":
version "8.11.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz#273de1cbffe63d9f9cd7dfc20b5a5af66310cb92"
integrity sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==
dependencies:
"@typescript-eslint/types" "8.9.0"
"@typescript-eslint/types" "8.11.0"
eslint-visitor-keys "^3.4.3"
"@ungap/structured-clone@^1.2.0":