From a8462e24e792b4a5043c80dea306d0f212599667 Mon Sep 17 00:00:00 2001 From: Daniel Porteous Date: Tue, 6 May 2025 13:14:35 +0100 Subject: [PATCH] Overhaul tests to work with more networks --- confidential-assets/package.json | 3 +- confidential-assets/src/confidentialAsset.ts | 28 +- .../src/confidentialKeyRotation.ts | 47 +- .../src/confidentialNormalization.ts | 35 +- .../src/confidentialTransfer.ts | 25 +- .../src/confidentialWithdraw.ts | 40 +- confidential-assets/src/consts.ts | 4 - confidential-assets/src/index.ts | 24 +- confidential-assets/src/twistedEd25519.ts | 15 +- confidential-assets/src/utils.ts | 16 +- confidential-assets/tests/README.MD | 30 +- .../{units => }/api/checkBalances.test.ts | 5 +- .../{units => }/api/checkIsFrozen.test.ts | 4 +- .../{units => }/api/checkIsNormalized.test.ts | 4 +- .../{units => }/api/checkIsRegistered.test.ts | 4 +- .../tests/{units => }/api/deposit.test.ts | 7 +- .../{units => }/api/getAssetAuditor.test.ts | 4 +- .../{units => }/api/negativeNormalize.test.ts | 42 +- .../{units => }/api/negativeTransfer.test.ts | 40 +- .../{units => }/api/negativeWithdraw.test.ts | 34 +- .../tests/{units => }/api/normalize.test.ts | 10 +- .../tests/{units => }/api/register.test.ts | 13 +- .../{units => }/api/safelyRollover.test.ts | 13 +- .../{units => }/api/safelyRotateKey.test.ts | 13 +- .../tests/{units => }/api/transfer.test.ts | 14 +- .../api/transferWithAuditor.test.ts | 12 +- .../tests/{units => }/api/withdraw.test.ts | 10 +- .../tests/e2e/confidentialCoin.test.ts | 221 ++++---- confidential-assets/tests/helpers/e2e.ts | 184 ++++++ confidential-assets/tests/helpers/index.ts | 117 +--- .../tests/helpers/wasmPollardKangaroo.ts | 2 +- .../tests/helpers/wasmRangeProof.ts | 2 +- confidential-assets/tests/move/README.md | 1 + .../tests/units/confidentialProofs.test.ts | 525 +++++++++++------- package.json | 2 +- 35 files changed, 891 insertions(+), 659 deletions(-) rename confidential-assets/tests/{units => }/api/checkBalances.test.ts (88%) rename confidential-assets/tests/{units => }/api/checkIsFrozen.test.ts (76%) rename confidential-assets/tests/{units => }/api/checkIsNormalized.test.ts (73%) rename confidential-assets/tests/{units => }/api/checkIsRegistered.test.ts (71%) rename confidential-assets/tests/{units => }/api/deposit.test.ts (69%) rename confidential-assets/tests/{units => }/api/getAssetAuditor.test.ts (66%) rename confidential-assets/tests/{units => }/api/negativeNormalize.test.ts (81%) rename confidential-assets/tests/{units => }/api/negativeTransfer.test.ts (77%) rename confidential-assets/tests/{units => }/api/negativeWithdraw.test.ts (78%) rename confidential-assets/tests/{units => }/api/normalize.test.ts (83%) rename confidential-assets/tests/{units => }/api/register.test.ts (70%) rename confidential-assets/tests/{units => }/api/safelyRollover.test.ts (72%) rename confidential-assets/tests/{units => }/api/safelyRotateKey.test.ts (84%) rename confidential-assets/tests/{units => }/api/transfer.test.ts (83%) rename confidential-assets/tests/{units => }/api/transferWithAuditor.test.ts (82%) rename confidential-assets/tests/{units => }/api/withdraw.test.ts (82%) create mode 100644 confidential-assets/tests/helpers/e2e.ts create mode 100644 confidential-assets/tests/move/README.md diff --git a/confidential-assets/package.json b/confidential-assets/package.json index 19fe55e4b..2ebccccb4 100644 --- a/confidential-assets/package.json +++ b/confidential-assets/package.json @@ -36,7 +36,8 @@ "build:types": "tsc -p tsconfig.build.json --outDir ./dist/types --declaration --emitDeclarationOnly", "build:cjs": "npx swc src -d ./dist/cjs --config-file .swcrc -C module.type=commonjs --strip-leading-paths --copy-files", "build:esm": "npx swc src -d ./dist/esm --config-file .swcrc -C module.type=es6 isModule=true --strip-leading-paths --copy-files", - "test": "pnpm jest ./tests/**/*.test.ts --testPathIgnorePatterns={./tests/units/api,./tests/e2e} --passWithNoTests" + "test:units": "pnpm jest tests/units", + "test:e2e": "pnpm jest tests/e2e" }, "dependencies": { "@aptos-labs/confidential-asset-wasm-bindings": "^0.0.2", diff --git a/confidential-assets/src/confidentialAsset.ts b/confidential-assets/src/confidentialAsset.ts index 5aff3be6e..a692d994a 100644 --- a/confidential-assets/src/confidentialAsset.ts +++ b/confidential-assets/src/confidentialAsset.ts @@ -1,7 +1,21 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -import { Account, AccountAddress, AccountAddressInput, AnyNumber, Aptos, AptosConfig, CommittedTransactionResponse, HexInput, InputGenerateSingleSignerRawTransactionArgs, InputGenerateTransactionPayloadData, LedgerVersionArg, MoveStructId, SimpleTransaction } from "@aptos-labs/ts-sdk"; +import { + Account, + AccountAddress, + AccountAddressInput, + AnyNumber, + Aptos, + AptosConfig, + CommittedTransactionResponse, + HexInput, + InputGenerateSingleSignerRawTransactionArgs, + InputGenerateTransactionPayloadData, + LedgerVersionArg, + MoveStructId, + SimpleTransaction, +} from "@aptos-labs/ts-sdk"; import { TwistedElGamalCiphertext } from "./twistedElGamal"; import { ConfidentialNormalization, CreateConfidentialNormalizationOpArgs } from "./confidentialNormalization"; import { ConfidentialKeyRotation, CreateConfidentialKeyRotationOpArgs } from "./confidentialKeyRotation"; @@ -11,7 +25,10 @@ import { ConfidentialAmount } from "./confidentialAmount"; import { CreateConfidentialTransferOpArgs, ConfidentialTransfer } from "./confidentialTransfer"; import { CreateConfidentialWithdrawOpArgs, ConfidentialWithdraw } from "./confidentialWithdraw"; import { TwistedEd25519PublicKey, TwistedEd25519PrivateKey } from "./twistedEd25519"; -import { DEFAULT_CONFIDENTIAL_COIN_MODULE_ADDRESS, MODULE_NAME } from "./consts"; + +/** For now we only deploy to devnet as part of aptos-experimental, which lives at 0x7. */ +const DEFAULT_CONFIDENTIAL_COIN_MODULE_ADDRESS = "0x7"; +const MODULE_NAME = "confidential_asset"; export type ConfidentialBalanceResponse = { chunks: { @@ -32,7 +49,12 @@ export class ConfidentialAsset { client: Aptos; confidentialAssetModuleAddress: string; - constructor(readonly config: AptosConfig, { confidentialAssetModuleAddress = DEFAULT_CONFIDENTIAL_COIN_MODULE_ADDRESS }: { confidentialAssetModuleAddress?: string } = {}) { + constructor( + readonly config: AptosConfig, + { + confidentialAssetModuleAddress = DEFAULT_CONFIDENTIAL_COIN_MODULE_ADDRESS, + }: { confidentialAssetModuleAddress?: string } = {}, + ) { this.client = new Aptos(config); this.confidentialAssetModuleAddress = confidentialAssetModuleAddress; } diff --git a/confidential-assets/src/confidentialKeyRotation.ts b/confidential-assets/src/confidentialKeyRotation.ts index 83a9de699..dde8126d1 100644 --- a/confidential-assets/src/confidentialKeyRotation.ts +++ b/confidential-assets/src/confidentialKeyRotation.ts @@ -108,26 +108,12 @@ export class ConfidentialKeyRotation { const alpha2 = proofArr[3]; const alpha3 = proofArr[4]; const alpha4 = proofArr[5]; - const alpha5List = proofArr.slice( - 6, - 6 + ConfidentialAmount.CHUNKS_COUNT, - ); - const X1 = proofArr[ - 6 + ConfidentialAmount.CHUNKS_COUNT - ]; - const X2 = proofArr[ - 7 + ConfidentialAmount.CHUNKS_COUNT - ]; - const X3 = proofArr[ - 8 + ConfidentialAmount.CHUNKS_COUNT - ]; - const X4List = proofArr.slice( - 8 + ConfidentialAmount.CHUNKS_COUNT, - 8 + 2 * ConfidentialAmount.CHUNKS_COUNT, - ); - const X5List = proofArr.slice( - 8 + 2 * ConfidentialAmount.CHUNKS_COUNT, - ); + const alpha5List = proofArr.slice(6, 6 + ConfidentialAmount.CHUNKS_COUNT); + const X1 = proofArr[6 + ConfidentialAmount.CHUNKS_COUNT]; + const X2 = proofArr[7 + ConfidentialAmount.CHUNKS_COUNT]; + const X3 = proofArr[8 + ConfidentialAmount.CHUNKS_COUNT]; + const X4List = proofArr.slice(8 + ConfidentialAmount.CHUNKS_COUNT, 8 + 2 * ConfidentialAmount.CHUNKS_COUNT); + const X5List = proofArr.slice(8 + 2 * ConfidentialAmount.CHUNKS_COUNT); return { alpha1List, @@ -159,11 +145,11 @@ export class ConfidentialKeyRotation { ed25519modN( x1List.reduce((acc, el, i) => { const coef = 2n ** (BigInt(i) * ConfidentialAmount.CHUNK_BITS_BI); - const x1i = el * coef + const x1i = el * coef; return acc + x1i; - }, 0n) - ) + }, 0n), + ), ).add( this.currEncryptedBalance .reduce( @@ -178,11 +164,11 @@ export class ConfidentialKeyRotation { const x1iG = RistrettoPoint.BASE.multiply(el); const x5iH = H_RISTRETTO.multiply(x5List[index]); - return x1iG.add(x5iH) + return x1iG.add(x5iH); }); const X5List = x5List.map((el) => { - const Pnew = RistrettoPoint.fromHex(this.newDecryptionKey.publicKey().toUint8Array()) - return Pnew.multiply(el) + const Pnew = RistrettoPoint.fromHex(this.newDecryptionKey.publicKey().toUint8Array()); + return Pnew.multiply(el); }); const p = genFiatShamirChallenge( @@ -216,7 +202,7 @@ export class ConfidentialKeyRotation { const alpha5List = x5List.map((el, i) => { const pri = ed25519modN(p * this.randomness[i]); - return ed25519modN(el - pri) + return ed25519modN(el - pri); }); return { @@ -282,10 +268,11 @@ export class ConfidentialKeyRotation { const a1i = el * coef; return acc + a1i; - }, 0n) - ) + }, 0n), + ), ) - .add(DOldSum.multiply(alpha2LE)).add(COldSum.multiply(p)); + .add(DOldSum.multiply(alpha2LE)) + .add(COldSum.multiply(p)); const X2 = H_RISTRETTO.multiply(alpha3LE).add(pkOldRist.multiply(p)); const X3 = H_RISTRETTO.multiply(alpha4LE).add(pkNewRist.multiply(p)); const X4List = alpha1LEList.map((el, i) => { diff --git a/confidential-assets/src/confidentialNormalization.ts b/confidential-assets/src/confidentialNormalization.ts index 4d5eda16d..8129e8642 100644 --- a/confidential-assets/src/confidentialNormalization.ts +++ b/confidential-assets/src/confidentialNormalization.ts @@ -97,16 +97,9 @@ export class ConfidentialNormalization { const alpha1List = proofArr.slice(0, 3); const alpha2 = proofArr[3]; const alpha3 = proofArr[4]; - const alpha4List = proofArr.slice( - 5, - 5 + ConfidentialAmount.CHUNKS_COUNT, - ); - const X1 = proofArr[ - 5 + 2 * ConfidentialAmount.CHUNKS_COUNT - ]; - const X2 = proofArr[ - 5 + 2 * ConfidentialAmount.CHUNKS_COUNT + 1 - ]; + const alpha4List = proofArr.slice(5, 5 + ConfidentialAmount.CHUNKS_COUNT); + const X1 = proofArr[5 + 2 * ConfidentialAmount.CHUNKS_COUNT]; + const X2 = proofArr[5 + 2 * ConfidentialAmount.CHUNKS_COUNT + 1]; const X3List = proofArr.slice( 5 + 2 * ConfidentialAmount.CHUNKS_COUNT + 2, 5 + 3 * ConfidentialAmount.CHUNKS_COUNT + 2, @@ -143,11 +136,11 @@ export class ConfidentialNormalization { ed25519modN( x1List.reduce((acc, el, i) => { const coef = 2n ** (BigInt(i) * ConfidentialAmount.CHUNK_BITS_BI); - const x1i = el * coef + const x1i = el * coef; - return acc + x1i - }, 0n) - ) + return acc + x1i; + }, 0n), + ), ).add( this.unnormalizedEncryptedBalance .reduce( @@ -162,7 +155,7 @@ export class ConfidentialNormalization { const x4iH = H_RISTRETTO.multiply(x4List[index]); - return x1iG.add(x4iH) + return x1iG.add(x4iH); }); const X4List = x4List.map((el) => RistrettoPoint.fromHex(this.decryptionKey.publicKey().toUint8Array()).multiply(el), @@ -197,7 +190,7 @@ export class ConfidentialNormalization { const alpha4List = x4List.map((el, i) => { const pri = ed25519modN(p * this.randomness[i]); - return ed25519modN(el - pri) + return ed25519modN(el - pri); }); return { @@ -261,8 +254,10 @@ export class ConfidentialNormalization { const alpha1i = el * coef; return acc + alpha1i; }, 0n), - ) - ).add(alpha2D).add(pBalOld); + ), + ) + .add(alpha2D) + .add(pBalOld); const X2 = alpha3H.add(pP); const X3List = alpha1LEList.map((el, i) => { const a1iG = RistrettoPoint.BASE.multiply(el); @@ -272,9 +267,9 @@ export class ConfidentialNormalization { }); const X4List = alpha4LEList.map((el, i) => { const a4iP = RistrettoPoint.fromHex(publicKeyU8).multiply(el); - const pDnew = opts.normalizedEncryptedBalance[i].D.multiply(p) + const pDnew = opts.normalizedEncryptedBalance[i].D.multiply(p); - return a4iP.add(pDnew) + return a4iP.add(pDnew); }); return ( diff --git a/confidential-assets/src/confidentialTransfer.ts b/confidential-assets/src/confidentialTransfer.ts index f2872f46f..7e9f14971 100644 --- a/confidential-assets/src/confidentialTransfer.ts +++ b/confidential-assets/src/confidentialTransfer.ts @@ -182,14 +182,11 @@ export class ConfidentialTransfer { const alpha1List = baseProofArray.slice(0, half); const alpha2 = baseProofArray[half]; - const alpha3List = baseProofArray.slice( - half + 1, - half + 1 + ConfidentialAmount.CHUNKS_COUNT, - ) + const alpha3List = baseProofArray.slice(half + 1, half + 1 + ConfidentialAmount.CHUNKS_COUNT); const alpha4List = baseProofArray.slice( half + 1 + ConfidentialAmount.CHUNKS_COUNT, half + 1 + ConfidentialAmount.CHUNKS_COUNT * 2, - ) + ); const alpha5 = baseProofArray[half + 1 + ConfidentialAmount.CHUNKS_COUNT * 2]; const X1 = baseProofArray[half + 1 + ConfidentialAmount.CHUNKS_COUNT * 3]; @@ -270,11 +267,11 @@ export class ConfidentialTransfer { ed25519modN( x1List.reduce((acc, el, i) => { const coef = 2n ** (BigInt(i) * ConfidentialAmount.CHUNK_BITS_BI); - const x1i = el * coef + const x1i = el * coef; - return acc + x1i - }, 0n) - ) + return acc + x1i; + }, 0n), + ), ) .add(DBal.multiply(x2)) .subtract(DNewBal.multiply(x2)) @@ -298,7 +295,7 @@ export class ConfidentialTransfer { const x1iG = RistrettoPoint.BASE.multiply(el); const x3iH = H_RISTRETTO.multiply(x3List[idx]); - return x1iG.add(x3iH).toRawBytes() + return x1iG.add(x3iH).toRawBytes(); }); const X7List = @@ -329,7 +326,9 @@ export class ConfidentialTransfer { const sLE = bytesToNumberLE(this.senderDecryptionKey.toUint8Array()); const invertSLE = ed25519InvertN(sLE); - const alpha1List = x1List.map((x1, idx) => ed25519modN(x1 - ed25519modN(p * this.confidentialAmountAfterTransfer.amountChunks[idx]))); + const alpha1List = x1List.map((x1, idx) => + ed25519modN(x1 - ed25519modN(p * this.confidentialAmountAfterTransfer.amountChunks[idx])), + ); const alpha2 = ed25519modN(x2 - p * sLE); const alpha3List = x3List.map((el, idx) => ed25519modN(BigInt(el) - BigInt(p) * BigInt(this.randomness[idx]))); const alpha4List = x4List @@ -438,8 +437,8 @@ export class ConfidentialTransfer { const a1i = curr * coef; return acc + a1i; - }, 0n) - ) + }, 0n), + ), ) .add(oldDSum.multiply(alpha2LE)) .subtract(newDSum.multiply(alpha2LE)) diff --git a/confidential-assets/src/confidentialWithdraw.ts b/confidential-assets/src/confidentialWithdraw.ts index 8b6c216e0..c9d2bb523 100644 --- a/confidential-assets/src/confidentialWithdraw.ts +++ b/confidential-assets/src/confidentialWithdraw.ts @@ -144,21 +144,20 @@ export class ConfidentialWithdraw { const x1i = el * coef; return acc + x1i; - }, 0n) - ) - ) - .add( - this.encryptedActualBalanceAmount.reduce((acc, el, i) => { - const { D } = el; - const coef = 2n ** (BigInt(i) * ConfidentialAmount.CHUNK_BITS_BI); + }, 0n), + ), + ).add( + this.encryptedActualBalanceAmount.reduce((acc, el, i) => { + const { D } = el; + const coef = 2n ** (BigInt(i) * ConfidentialAmount.CHUNK_BITS_BI); - const DCoef = D.multiply(coef); + const DCoef = D.multiply(coef); - const DCoefX2 = DCoef.multiply(x2); + const DCoefX2 = DCoef.multiply(x2); - return acc.add(DCoefX2); - }, RistrettoPoint.ZERO), - ); + return acc.add(DCoefX2); + }, RistrettoPoint.ZERO), + ); const X2 = H_RISTRETTO.multiply(x3); const X3List = x1List.map((item, idx) => RistrettoPoint.BASE.multiply(item).add(H_RISTRETTO.multiply(x4List[idx]))); const X4List = x4List.map((item) => @@ -185,8 +184,8 @@ export class ConfidentialWithdraw { const psInvert = ed25519modN(p * invertSLE); const alpha1List = x1List.map((el, i) => { - const pChunk = ed25519modN(p * this.confidentialAmountAfterWithdraw.amountChunks[i]) - return ed25519modN(el - pChunk) + const pChunk = ed25519modN(p * this.confidentialAmountAfterWithdraw.amountChunks[i]); + return ed25519modN(el - pChunk); }); const alpha2 = ed25519modN(x2 - ps); const alpha3 = ed25519modN(x3 - psInvert); @@ -255,8 +254,8 @@ export class ConfidentialWithdraw { const elCoef = el * coef; return acc + elCoef; - }, 0n) - ) + }, 0n), + ), ) .add(DOldSum.multiply(alpha2LE)) .add(COldSum.multiply(p)) @@ -270,13 +269,12 @@ export class ConfidentialWithdraw { return a1iG.add(a4iH).add(pC); }); const X4List = alpha4LEList.map((el, i) => { - const a4iP = RistrettoPoint.fromHex(publicKeyU8).multiply(el) + const a4iP = RistrettoPoint.fromHex(publicKeyU8).multiply(el); - const pDNew = opts.encryptedActualBalanceAfterWithdraw[i].D.multiply(p) + const pDNew = opts.encryptedActualBalanceAfterWithdraw[i].D.multiply(p); - return a4iP.add(pDNew) - }, - ); + return a4iP.add(pDNew); + }); return ( X1.equals(RistrettoPoint.fromHex(opts.sigmaProof.X1)) && diff --git a/confidential-assets/src/consts.ts b/confidential-assets/src/consts.ts index 0076fb33e..7d4e5e4fc 100644 --- a/confidential-assets/src/consts.ts +++ b/confidential-assets/src/consts.ts @@ -7,7 +7,3 @@ export const SIGMA_PROOF_TRANSFER_SIZE = PROOF_CHUNK_SIZE * 33; // bytes export const SIGMA_PROOF_KEY_ROTATION_SIZE = PROOF_CHUNK_SIZE * 23; // bytes export const SIGMA_PROOF_NORMALIZATION_SIZE = PROOF_CHUNK_SIZE * 21; // bytes - -/** For now we only deploy to devnet as part of aptos-experimental, which lives at 0x7. */ -export const DEFAULT_CONFIDENTIAL_COIN_MODULE_ADDRESS = "0x7"; -export const MODULE_NAME = "confidential_asset"; diff --git a/confidential-assets/src/index.ts b/confidential-assets/src/index.ts index f77f72506..169e4e6a9 100644 --- a/confidential-assets/src/index.ts +++ b/confidential-assets/src/index.ts @@ -1,12 +1,12 @@ -export * from './confidentialAmount' -export * from './confidentialAsset' -export * from './confidentialKeyRotation' -export * from './confidentialNormalization' -export * from './confidentialTransfer' -export * from './confidentialWithdraw' -export * from './consts' -export * from './helpers' -export * from './rangeProof' -export * from './twistedEd25519' -export * from './twistedElGamal' -export * from './utils' +export * from "./confidentialAmount"; +export * from "./confidentialAsset"; +export * from "./confidentialKeyRotation"; +export * from "./confidentialNormalization"; +export * from "./confidentialTransfer"; +export * from "./confidentialWithdraw"; +export * from "./consts"; +export * from "./helpers"; +export * from "./rangeProof"; +export * from "./twistedEd25519"; +export * from "./twistedElGamal"; +export * from "./utils"; diff --git a/confidential-assets/src/twistedEd25519.ts b/confidential-assets/src/twistedEd25519.ts index 07f209773..d7e457465 100644 --- a/confidential-assets/src/twistedEd25519.ts +++ b/confidential-assets/src/twistedEd25519.ts @@ -4,7 +4,20 @@ import { ed25519, RistrettoPoint } from "@noble/curves/ed25519"; import { bytesToNumberLE, numberToBytesLE } from "@noble/curves/abstract/utils"; import { ed25519InvertN, ed25519modN } from "./utils"; -import { HexInput, Hex, Serializable, isValidHardenedPath, mnemonicToSeed, Ed25519Signature, HARDENED_OFFSET, deriveKey, splitPath, CKDPriv, Serializer, Deserializer } from "@aptos-labs/ts-sdk"; +import { + HexInput, + Hex, + Serializable, + isValidHardenedPath, + mnemonicToSeed, + Ed25519Signature, + HARDENED_OFFSET, + deriveKey, + splitPath, + CKDPriv, + Serializer, + Deserializer, +} from "@aptos-labs/ts-sdk"; export { RistrettoPoint } from "@noble/curves/ed25519"; export type RistPoint = InstanceType; diff --git a/confidential-assets/src/utils.ts b/confidential-assets/src/utils.ts index 7f5746ca9..08817fd76 100644 --- a/confidential-assets/src/utils.ts +++ b/confidential-assets/src/utils.ts @@ -7,26 +7,26 @@ import { randomBytes } from "@noble/hashes/utils"; * Number modulo order of curve ed25519 */ export function ed25519modN(a: bigint): bigint { - return mod(a, ed25519.CURVE.n); + return mod(a, ed25519.CURVE.n); } /* * Inverses number over modulo of curve ed25519 */ export function ed25519InvertN(a: bigint): bigint { - return invert(a, ed25519.CURVE.n); + return invert(a, ed25519.CURVE.n); } /* * Generate random number less then order of curve ed25519 */ export function ed25519GenRandom(): bigint { - let rand: bigint; - do { - rand = bytesToNumberBE(randomBytes(32)); - } while (rand > ed25519.CURVE.n); + let rand: bigint; + do { + rand = bytesToNumberBE(randomBytes(32)); + } while (rand > ed25519.CURVE.n); - return rand; + return rand; } /** @@ -34,5 +34,5 @@ export function ed25519GenRandom(): bigint { * @param len - chunks count */ export function ed25519GenListOfRandom(len: number) { - return new Array(len).fill(0n).map(() => ed25519GenRandom()); + return new Array(len).fill(0n).map(() => ed25519GenRandom()); } diff --git a/confidential-assets/tests/README.MD b/confidential-assets/tests/README.MD index 8d8653bed..2cf53a229 100644 --- a/confidential-assets/tests/README.MD +++ b/confidential-assets/tests/README.MD @@ -2,8 +2,9 @@ This directory contains tests for the Aptos confidential assets functionality. The tests are organized into: -- `e2e/`: End-to-end tests that verify the complete workflows of confidential assets -- `units/`: Unit tests for individual components and functionality +- `e2e/`: End-to-end tests that verify the complete workflows of confidential assets. +- `units/`: Unit tests for individual components and functionality. These do not test anything against a network. +- `api/`: Tests that verify single pieces of the API. These tests are not run by default becuase the tests are not self contained. Use these only when you want to test specific behaviour of each operation. - `helpers/`: Helper functions and utilities for testing ## Prerequisites @@ -18,21 +19,25 @@ Before running the tests, ensure you have: The tests use environment variables to determine which accounts to use: -- `TESTNET_PK`: Private key for the Aptos account used in tests -- `TESTNET_DK`: Private key for the TwistedEd25519 account used in tests +- `TESTNET_PK`: Private key for the Aptos account used in tests. If not provided we will generate a random account, though this will not work on testnet. +- `TESTNET_DK`: Private key for the TwistedEd25519 account used in tests. You do not generally need to set this. Even if you set `TESTNET_PK` we will derive `TESTNET_DK` from `TESTNET_PK`. -### Configuration +You may also set the following environment variables to configure the testing network and confidential assets module address: -To use specific accounts for testing: +- `TESTING_NETWORK`: The network to use for testing. Defaults to `devnet`. +- `CONFIDENTIAL_ASSETS_MODULE_ADDRESS`: The address of the confidential assets module. Will use the default from the SDK if not set. -1. Create a file named `.env.development` in the confidential-assets directory -2. Add the following variables to the file: +For example, to run the E2E tests against testnet: ``` -TESTNET_PK=your_private_key_here -TESTNET_DK=your_twisted_ed25519_private_key_here +TESTING_NETWORK=testnet TESTNET_PK= pnpm test:e2e ``` -If these environment variables are not provided, the tests will automatically generate random accounts for testing purposes. +As you can see, we set the private key for the account we use in testing since we're testing against testnet. + +Make sure the mock token is deployed at the default address, or you can set the address by setting the `MOCK_TOKEN_ADDRESS` environment variable. If you haven't deployed the mock token, you can do so like this: +``` +todo +``` ## Running Tests @@ -42,9 +47,6 @@ To run a specific test file: pnpm jest path/to/test/file.test.ts ``` -### !important -`./tests/units/api` - is not for CI or e2e testing. Use these test only when you want to test specific behaviour of each operation. - ## Test Coverage After running tests, coverage reports will be generated in the `coverage` directory. You can view detailed coverage information by opening `coverage/lcov-report/index.html` in your browser. diff --git a/confidential-assets/tests/units/api/checkBalances.test.ts b/confidential-assets/tests/api/checkBalances.test.ts similarity index 88% rename from confidential-assets/tests/units/api/checkBalances.test.ts rename to confidential-assets/tests/api/checkBalances.test.ts index 47db021f9..1de928d09 100644 --- a/confidential-assets/tests/units/api/checkBalances.test.ts +++ b/confidential-assets/tests/api/checkBalances.test.ts @@ -1,5 +1,6 @@ -import { getBalances, getTestAccount, getTestConfidentialAccount, longTestTimeout } from "../../helpers"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; +import { getBalances, getTestAccount, getTestConfidentialAccount } from "../helpers/e2e"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; +import { longTestTimeout } from "../helpers"; describe("Check balance", () => { const alice = getTestAccount(); diff --git a/confidential-assets/tests/units/api/checkIsFrozen.test.ts b/confidential-assets/tests/api/checkIsFrozen.test.ts similarity index 76% rename from confidential-assets/tests/units/api/checkIsFrozen.test.ts rename to confidential-assets/tests/api/checkIsFrozen.test.ts index 12e0ad329..bf8efb1ad 100644 --- a/confidential-assets/tests/units/api/checkIsFrozen.test.ts +++ b/confidential-assets/tests/api/checkIsFrozen.test.ts @@ -1,4 +1,4 @@ -import { confidentialAsset, getTestAccount, TOKEN_ADDRESS } from "../../helpers"; +import { confidentialAsset, getTestAccount, MOCK_TOKEN_DATA } from "../helpers/e2e"; describe("should check if user confidential account is frozen", () => { const alice = getTestAccount(); @@ -6,7 +6,7 @@ describe("should check if user confidential account is frozen", () => { it("should check if user confidential account is frozen", async () => { const isFrozen = await confidentialAsset.isBalanceFrozen({ accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); console.log(`${alice.accountAddress.toString()} frozen status is:`, isFrozen); diff --git a/confidential-assets/tests/units/api/checkIsNormalized.test.ts b/confidential-assets/tests/api/checkIsNormalized.test.ts similarity index 73% rename from confidential-assets/tests/units/api/checkIsNormalized.test.ts rename to confidential-assets/tests/api/checkIsNormalized.test.ts index 9153b9d94..fd5b2d4d4 100644 --- a/confidential-assets/tests/units/api/checkIsNormalized.test.ts +++ b/confidential-assets/tests/api/checkIsNormalized.test.ts @@ -1,4 +1,4 @@ -import { confidentialAsset, getTestAccount, TOKEN_ADDRESS } from "../../helpers"; +import { confidentialAsset, getTestAccount, MOCK_TOKEN_DATA } from "../helpers/e2e"; describe("Check is normalized", () => { const alice = getTestAccount(); @@ -6,7 +6,7 @@ describe("Check is normalized", () => { it("should check if user confidential balance is normalized", async () => { const isAliceBalanceNormalized = await confidentialAsset.isUserBalanceNormalized({ accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); expect(isAliceBalanceNormalized).toBeDefined(); diff --git a/confidential-assets/tests/units/api/checkIsRegistered.test.ts b/confidential-assets/tests/api/checkIsRegistered.test.ts similarity index 71% rename from confidential-assets/tests/units/api/checkIsRegistered.test.ts rename to confidential-assets/tests/api/checkIsRegistered.test.ts index 97e39fad1..4f9d3d861 100644 --- a/confidential-assets/tests/units/api/checkIsRegistered.test.ts +++ b/confidential-assets/tests/api/checkIsRegistered.test.ts @@ -1,4 +1,4 @@ -import { confidentialAsset, getTestAccount, TOKEN_ADDRESS } from "../../helpers"; +import { confidentialAsset, getTestAccount, MOCK_TOKEN_DATA } from "../helpers/e2e"; describe("Check Registration status", () => { const alice = getTestAccount(); @@ -6,7 +6,7 @@ describe("Check Registration status", () => { it("should return true if the user is registered", async () => { const isAliceRegistered = await confidentialAsset.hasUserRegistered({ accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); expect(isAliceRegistered).toBeTruthy(); diff --git a/confidential-assets/tests/units/api/deposit.test.ts b/confidential-assets/tests/api/deposit.test.ts similarity index 69% rename from confidential-assets/tests/units/api/deposit.test.ts rename to confidential-assets/tests/api/deposit.test.ts index fe21dd9a2..5c19e7a16 100644 --- a/confidential-assets/tests/units/api/deposit.test.ts +++ b/confidential-assets/tests/api/deposit.test.ts @@ -1,5 +1,6 @@ -import { confidentialAsset, getTestAccount, longTestTimeout, mintFungibleTokens, sendAndWaitTx, TOKEN_ADDRESS } from "../../helpers"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; +import { confidentialAsset, getTestAccount, mintFungibleTokens, sendAndWaitTx, MOCK_TOKEN_DATA } from "../helpers/e2e"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; +import { longTestTimeout } from "../helpers"; describe("Deposit", () => { const alice = getTestAccount(); @@ -18,7 +19,7 @@ describe("Deposit", () => { const depositTx = await confidentialAsset.deposit({ sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, amount: DEPOSIT_AMOUNT, }); const resp = await sendAndWaitTx(depositTx, alice); diff --git a/confidential-assets/tests/units/api/getAssetAuditor.test.ts b/confidential-assets/tests/api/getAssetAuditor.test.ts similarity index 66% rename from confidential-assets/tests/units/api/getAssetAuditor.test.ts rename to confidential-assets/tests/api/getAssetAuditor.test.ts index ad04c373e..8cafa0210 100644 --- a/confidential-assets/tests/units/api/getAssetAuditor.test.ts +++ b/confidential-assets/tests/api/getAssetAuditor.test.ts @@ -1,9 +1,9 @@ -import { confidentialAsset, TOKEN_ADDRESS } from "../../helpers"; +import { confidentialAsset, MOCK_TOKEN_DATA } from "../helpers/e2e"; describe("Global auditor", () => { it("it should get global auditor", async () => { const [{ vec }] = await confidentialAsset.getAssetAuditor({ - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); console.log(vec); diff --git a/confidential-assets/tests/units/api/negativeNormalize.test.ts b/confidential-assets/tests/api/negativeNormalize.test.ts similarity index 81% rename from confidential-assets/tests/units/api/negativeNormalize.test.ts rename to confidential-assets/tests/api/negativeNormalize.test.ts index a3cf2499f..b749654f0 100644 --- a/confidential-assets/tests/units/api/negativeNormalize.test.ts +++ b/confidential-assets/tests/api/negativeNormalize.test.ts @@ -4,30 +4,32 @@ import { confidentialAsset, getBalances, getTestConfidentialAccount, - longTestTimeout, sendAndWaitBatchTxs, sendAndWaitTx, -} from "../../helpers"; +} from "../helpers/e2e"; import { numberToBytesLE, bytesToNumberLE } from "@noble/curves/abstract/utils"; import { bytesToHex } from "@noble/hashes/utils"; -import { ed25519modN, ConfidentialAmount } from "../../../src"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; - +import { ed25519modN, ConfidentialAmount } from "../../src"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; +import { longTestTimeout } from "../helpers"; describe("Transfer", () => { const alice = Account.generate(); const aliceConfidential = getTestConfidentialAccount(alice); const coinType = "0x1::aptos_coin::AptosCoin"; - const tokenAddress = '0x000000000000000000000000000000000000000000000000000000000000000a'; + const tokenAddress = "0x000000000000000000000000000000000000000000000000000000000000000a"; const fundAmount = 1 * 10 ** 8; const depositAmount = 0.5 * 10 ** 8; const recipientAccAddr = "0x82094619a5e8621f2bf9e6479a62ed694dca9b8fd69b0383fce359a3070aa0d4"; const normalizeAmount = -BigInt(depositAmount); - console.log("pk", alice.privateKey.toString()) - console.log("dk", aliceConfidential.toString()) - console.log("ek", aliceConfidential.publicKey().toString()) - console.log("dk(move)", bytesToHex(numberToBytesLE(ed25519modN(bytesToNumberLE(aliceConfidential.toUint8Array())), 32))) + console.log("pk", alice.privateKey.toString()); + console.log("dk", aliceConfidential.toString()); + console.log("ek", aliceConfidential.publicKey().toString()); + console.log( + "dk(move)", + bytesToHex(numberToBytesLE(ed25519modN(bytesToNumberLE(aliceConfidential.toUint8Array())), 32)), + ); it( "Pre load wasm table map", @@ -41,8 +43,8 @@ describe("Transfer", () => { await aptos.fundAccount({ accountAddress: alice.accountAddress, amount: fundAmount, - }) - }) + }); + }); it("should register Alice's balance", async () => { const aliceRegisterVBTxBody = await confidentialAsset.registerBalance({ @@ -54,7 +56,7 @@ describe("Transfer", () => { const aliceTxResp = await sendAndWaitTx(aliceRegisterVBTxBody, alice); console.log("gas used:", aliceTxResp.gas_used); - }) + }); it("should deposit money to Alice's account", async () => { const depositTx = await confidentialAsset.depositCoin({ @@ -66,28 +68,28 @@ describe("Transfer", () => { const resp = await sendAndWaitTx(depositTx, alice); console.log("gas used:", resp.gas_used); - }) + }); it("Should rollover the balance", async () => { const rolloverTxs = await confidentialAsset.safeRolloverPendingCB({ sender: alice.accountAddress, tokenAddress, decryptionKey: aliceConfidential, - }) + }); const txResponses = await sendAndWaitBatchTxs(rolloverTxs, alice); console.log("gas used:", txResponses.map((el) => `${el.hash} - ${el.gas_used}`).join("\n")); expect(txResponses.every((el) => el.success)).toBeTruthy(); - }) + }); it("should transfer money from Alice actual to pending balance", async () => { const balances = await getBalances(aliceConfidential, alice.accountAddress, tokenAddress); - console.log({ balances }) + console.log({ balances }); - const fakeBalance = ConfidentialAmount.fromAmount(normalizeAmount) + const fakeBalance = ConfidentialAmount.fromAmount(normalizeAmount); fakeBalance.encrypt(aliceConfidential.publicKey()); const recipientEncKey = await confidentialAsset.getEncryptionByAddr({ @@ -95,7 +97,7 @@ describe("Transfer", () => { tokenAddress, }); - console.log({ recipientEncKey: recipientEncKey.toString() }) + console.log({ recipientEncKey: recipientEncKey.toString() }); const normalizeTx = await confidentialAsset.normalizeUserBalance({ tokenAddress, @@ -112,7 +114,7 @@ describe("Transfer", () => { const balancesAfterTransfer = await getBalances(aliceConfidential, alice.accountAddress, tokenAddress); - console.log(balancesAfterTransfer.actual) + console.log(balancesAfterTransfer.actual); expect(txResp.success).toBeTruthy(); }); diff --git a/confidential-assets/tests/units/api/negativeTransfer.test.ts b/confidential-assets/tests/api/negativeTransfer.test.ts similarity index 77% rename from confidential-assets/tests/units/api/negativeTransfer.test.ts rename to confidential-assets/tests/api/negativeTransfer.test.ts index 197461527..b42fdf8f6 100644 --- a/confidential-assets/tests/units/api/negativeTransfer.test.ts +++ b/confidential-assets/tests/api/negativeTransfer.test.ts @@ -1,32 +1,28 @@ import { Account, AccountAddress } from "@aptos-labs/ts-sdk"; -import { - aptos, - confidentialAsset, - getBalances, - getTestConfidentialAccount, - longTestTimeout, - sendAndWaitTx, -} from "../../helpers"; +import { aptos, confidentialAsset, getBalances, getTestConfidentialAccount, sendAndWaitTx } from "../helpers/e2e"; import { numberToBytesLE, bytesToNumberLE } from "@noble/curves/abstract/utils"; import { bytesToHex } from "@noble/hashes/utils"; -import { ed25519modN, TwistedEd25519PublicKey } from "../../../src"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; - +import { ed25519modN, TwistedEd25519PublicKey } from "../../src"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; +import { longTestTimeout } from "../helpers"; describe("Transfer", () => { const alice = Account.generate(); const aliceConfidential = getTestConfidentialAccount(alice); const coinType = "0x1::aptos_coin::AptosCoin"; - const tokenAddress = '0x000000000000000000000000000000000000000000000000000000000000000a'; + const tokenAddress = "0x000000000000000000000000000000000000000000000000000000000000000a"; const fundAmount = 1 * 10 ** 8; const depositAmount = 0.5 * 10 ** 8; const recipientAccAddr = "0x82094619a5e8621f2bf9e6479a62ed694dca9b8fd69b0383fce359a3070aa0d4"; const transferAmount = BigInt(0.1 * 10 ** 8); - console.log("pk", alice.privateKey.toString()) - console.log("dk", aliceConfidential.toString()) - console.log("ek", aliceConfidential.publicKey().toString()) - console.log("dk(move)", bytesToHex(numberToBytesLE(ed25519modN(bytesToNumberLE(aliceConfidential.toUint8Array())), 32))) + console.log("pk", alice.privateKey.toString()); + console.log("dk", aliceConfidential.toString()); + console.log("ek", aliceConfidential.publicKey().toString()); + console.log( + "dk(move)", + bytesToHex(numberToBytesLE(ed25519modN(bytesToNumberLE(aliceConfidential.toUint8Array())), 32)), + ); it( "Pre load wasm table map", @@ -40,8 +36,8 @@ describe("Transfer", () => { await aptos.fundAccount({ accountAddress: alice.accountAddress, amount: fundAmount, - }) - }) + }); + }); it("should register Alice's balance", async () => { const aliceRegisterVBTxBody = await confidentialAsset.registerBalance({ @@ -53,7 +49,7 @@ describe("Transfer", () => { const aliceTxResp = await sendAndWaitTx(aliceRegisterVBTxBody, alice); console.log("gas used:", aliceTxResp.gas_used); - }) + }); it.skip("should deposit money to Alice's account", async () => { const depositTx = await confidentialAsset.depositCoin({ @@ -65,7 +61,7 @@ describe("Transfer", () => { const resp = await sendAndWaitTx(depositTx, alice); console.log("gas used:", resp.gas_used); - }) + }); it("should transfer money from Alice actual to pending balance", async () => { const balances = await getBalances(aliceConfidential, alice.accountAddress, tokenAddress); @@ -75,7 +71,7 @@ describe("Transfer", () => { tokenAddress, }); - console.log({ recipientEncKey: recipientEncKey.toString() }) + console.log({ recipientEncKey: recipientEncKey.toString() }); const transferTx = await confidentialAsset.transferCoin({ senderDecryptionKey: aliceConfidential, @@ -92,7 +88,7 @@ describe("Transfer", () => { const balancesAfterTransfer = await getBalances(aliceConfidential, alice.accountAddress, tokenAddress); - console.log(balancesAfterTransfer.actual) + console.log(balancesAfterTransfer.actual); expect(txResp.success).toBeTruthy(); }); diff --git a/confidential-assets/tests/units/api/negativeWithdraw.test.ts b/confidential-assets/tests/api/negativeWithdraw.test.ts similarity index 78% rename from confidential-assets/tests/units/api/negativeWithdraw.test.ts rename to confidential-assets/tests/api/negativeWithdraw.test.ts index fbf4e0e7d..00a8d1288 100644 --- a/confidential-assets/tests/units/api/negativeWithdraw.test.ts +++ b/confidential-assets/tests/api/negativeWithdraw.test.ts @@ -5,29 +5,31 @@ import { getBalances, getTestAccount, getTestConfidentialAccount, - longTestTimeout, sendAndWaitTx, -} from "../../helpers"; +} from "../helpers/e2e"; import { numberToBytesLE, bytesToNumberLE } from "@noble/curves/abstract/utils"; import { bytesToHex } from "@noble/hashes/utils"; -import { ed25519modN } from "../../../src"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; - +import { ed25519modN } from "../../src"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; +import { longTestTimeout } from "../helpers"; describe("Negative withdraw", () => { const alice = getTestAccount(); - const aliceConfidential = getTestConfidentialAccount(alice) + const aliceConfidential = getTestConfidentialAccount(alice); const coinType = "0x1::aptos_coin::AptosCoin"; - const tokenAddress = '0x000000000000000000000000000000000000000000000000000000000000000a'; + const tokenAddress = "0x000000000000000000000000000000000000000000000000000000000000000a"; const fundAmount = 1 * 10 ** 8; const depositAmount = 0.5 * 10 ** 8; const recipientAccAddr = "0x82094619a5e8621f2bf9e6479a62ed694dca9b8fd69b0383fce359a3070aa0d4"; const withdrawAmount = BigInt(0.1 * 10 ** 8); - console.log("pk", alice.privateKey.toString()) - console.log("dk", aliceConfidential.toString()) - console.log("ek", aliceConfidential.publicKey().toString()) - console.log("dk(move)", bytesToHex(numberToBytesLE(ed25519modN(bytesToNumberLE(aliceConfidential.toUint8Array())), 32))) + console.log("pk", alice.privateKey.toString()); + console.log("dk", aliceConfidential.toString()); + console.log("ek", aliceConfidential.publicKey().toString()); + console.log( + "dk(move)", + bytesToHex(numberToBytesLE(ed25519modN(bytesToNumberLE(aliceConfidential.toUint8Array())), 32)), + ); it( "Pre load wasm table map", @@ -41,8 +43,8 @@ describe("Negative withdraw", () => { await aptos.fundAccount({ accountAddress: alice.accountAddress, amount: fundAmount, - }) - }) + }); + }); it("should register Alice's balance", async () => { const aliceRegisterVBTxBody = await confidentialAsset.registerBalance({ @@ -54,7 +56,7 @@ describe("Negative withdraw", () => { const aliceTxResp = await sendAndWaitTx(aliceRegisterVBTxBody, alice); console.log("gas used:", aliceTxResp.gas_used); - }) + }); it("should deposit money to Alice's account", async () => { const depositTx = await confidentialAsset.depositCoin({ @@ -66,7 +68,7 @@ describe("Negative withdraw", () => { const resp = await sendAndWaitTx(depositTx, alice); console.log("gas used:", resp.gas_used); - }) + }); it("should throw error withdrawing money from Alice actual balance", async () => { const balances = await getBalances(aliceConfidential, alice.accountAddress, tokenAddress); @@ -76,7 +78,7 @@ describe("Negative withdraw", () => { tokenAddress, }); - console.log({ recipientEncKey: recipientEncKey.toString() }) + console.log({ recipientEncKey: recipientEncKey.toString() }); const withdrawTx = await confidentialAsset.withdraw({ sender: alice.accountAddress, diff --git a/confidential-assets/tests/units/api/normalize.test.ts b/confidential-assets/tests/api/normalize.test.ts similarity index 83% rename from confidential-assets/tests/units/api/normalize.test.ts rename to confidential-assets/tests/api/normalize.test.ts index c74542f54..397893131 100644 --- a/confidential-assets/tests/units/api/normalize.test.ts +++ b/confidential-assets/tests/api/normalize.test.ts @@ -1,13 +1,13 @@ +import { longTestTimeout } from "../helpers"; import { confidentialAsset, getBalances, getTestAccount, getTestConfidentialAccount, - longTestTimeout, sendAndWaitTx, - TOKEN_ADDRESS, -} from "../../helpers"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; + MOCK_TOKEN_DATA, +} from "../helpers/e2e"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; describe("Normalize", () => { const alice = getTestAccount(); @@ -27,7 +27,7 @@ describe("Normalize", () => { const balances = await getBalances(aliceConfidential, alice.accountAddress); const normalizeTx = await confidentialAsset.normalizeUserBalance({ - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, decryptionKey: aliceConfidential, unnormalizedEncryptedBalance: balances.actual.amountEncrypted!, balanceAmount: balances.actual.amount, diff --git a/confidential-assets/tests/units/api/register.test.ts b/confidential-assets/tests/api/register.test.ts similarity index 70% rename from confidential-assets/tests/units/api/register.test.ts rename to confidential-assets/tests/api/register.test.ts index 31f5ee361..81f5ee4d6 100644 --- a/confidential-assets/tests/units/api/register.test.ts +++ b/confidential-assets/tests/api/register.test.ts @@ -1,5 +1,12 @@ -import { confidentialAsset, getTestAccount, getTestConfidentialAccount, longTestTimeout, sendAndWaitTx, TOKEN_ADDRESS } from "../../helpers"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; +import { + confidentialAsset, + getTestAccount, + getTestConfidentialAccount, + sendAndWaitTx, + MOCK_TOKEN_DATA, +} from "../helpers/e2e"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; +import { longTestTimeout } from "../helpers"; describe("Register", () => { const alice = getTestAccount(); @@ -18,7 +25,7 @@ describe("Register", () => { async () => { const aliceRegisterVBTxBody = await confidentialAsset.registerBalance({ sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, publicKey: aliceConfidential.publicKey(), }); diff --git a/confidential-assets/tests/units/api/safelyRollover.test.ts b/confidential-assets/tests/api/safelyRollover.test.ts similarity index 72% rename from confidential-assets/tests/units/api/safelyRollover.test.ts rename to confidential-assets/tests/api/safelyRollover.test.ts index 230382c5f..b6faf03b0 100644 --- a/confidential-assets/tests/units/api/safelyRollover.test.ts +++ b/confidential-assets/tests/api/safelyRollover.test.ts @@ -1,5 +1,12 @@ -import { confidentialAsset, getTestAccount, getTestConfidentialAccount, longTestTimeout, sendAndWaitBatchTxs, TOKEN_ADDRESS } from "../../helpers"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; +import { longTestTimeout } from "../helpers"; +import { + confidentialAsset, + getTestAccount, + getTestConfidentialAccount, + sendAndWaitBatchTxs, + MOCK_TOKEN_DATA, +} from "../helpers/e2e"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; describe("Safely Rollover", () => { const alice = getTestAccount(); @@ -16,7 +23,7 @@ describe("Safely Rollover", () => { it("Should safely rollover Alice confidential balance", async () => { const rolloverTxPayloads = await confidentialAsset.safeRolloverPendingCB({ sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, withFreezeBalance: false, decryptionKey: aliceConfidential, }); diff --git a/confidential-assets/tests/units/api/safelyRotateKey.test.ts b/confidential-assets/tests/api/safelyRotateKey.test.ts similarity index 84% rename from confidential-assets/tests/units/api/safelyRotateKey.test.ts rename to confidential-assets/tests/api/safelyRotateKey.test.ts index d3a81c96a..73a292c1e 100644 --- a/confidential-assets/tests/units/api/safelyRotateKey.test.ts +++ b/confidential-assets/tests/api/safelyRotateKey.test.ts @@ -1,15 +1,14 @@ -import { TwistedEd25519PrivateKey } from "../../../src"; +import { TwistedEd25519PrivateKey } from "../../src"; import { - addNewContentLineToFile, aptos, confidentialAsset, getBalances, getTestAccount, getTestConfidentialAccount, - longTestTimeout, - TOKEN_ADDRESS, -} from "../../helpers"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; + MOCK_TOKEN_DATA, +} from "../helpers/e2e"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; +import { addNewContentLineToFile, longTestTimeout } from "../helpers"; describe("Safely rotate Alice's confidential balance key", () => { const alice = getTestAccount(); @@ -36,7 +35,7 @@ describe("Safely rotate Alice's confidential balance key", () => { currEncryptedBalance: balances.actual.amountEncrypted!, withUnfreezeBalance: true, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); console.log("gas used:", keyRotationAndUnfreezeTxResponse.gas_used); diff --git a/confidential-assets/tests/units/api/transfer.test.ts b/confidential-assets/tests/api/transfer.test.ts similarity index 83% rename from confidential-assets/tests/units/api/transfer.test.ts rename to confidential-assets/tests/api/transfer.test.ts index 6d8ad5ce3..85b6ee17c 100644 --- a/confidential-assets/tests/units/api/transfer.test.ts +++ b/confidential-assets/tests/api/transfer.test.ts @@ -1,15 +1,15 @@ import { AccountAddress } from "@aptos-labs/ts-sdk"; -import { TwistedEd25519PublicKey } from "../../../src"; +import { TwistedEd25519PublicKey } from "../../src"; import { confidentialAsset, getBalances, getTestAccount, getTestConfidentialAccount, - longTestTimeout, sendAndWaitTx, - TOKEN_ADDRESS, -} from "../../helpers"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; + MOCK_TOKEN_DATA, +} from "../helpers/e2e"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; +import { longTestTimeout } from "../helpers"; describe("Transfer", () => { const alice = getTestAccount(); @@ -33,7 +33,7 @@ describe("Transfer", () => { const recipientEncKey = await confidentialAsset.getEncryptionByAddr({ accountAddress: AccountAddress.from(recipientAccAddr), - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); console.log("recipientEncKey", recipientEncKey); @@ -44,7 +44,7 @@ describe("Transfer", () => { encryptedActualBalance: balances.actual.amountEncrypted!, amountToTransfer: TRANSFER_AMOUNT, sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, recipientAddress: recipientAccAddr, }); const txResp = await sendAndWaitTx(transferTx, alice); diff --git a/confidential-assets/tests/units/api/transferWithAuditor.test.ts b/confidential-assets/tests/api/transferWithAuditor.test.ts similarity index 82% rename from confidential-assets/tests/units/api/transferWithAuditor.test.ts rename to confidential-assets/tests/api/transferWithAuditor.test.ts index 538b9c17e..3aa5f7987 100644 --- a/confidential-assets/tests/units/api/transferWithAuditor.test.ts +++ b/confidential-assets/tests/api/transferWithAuditor.test.ts @@ -1,14 +1,14 @@ -import { TwistedEd25519PrivateKey } from "../../../src"; +import { TwistedEd25519PrivateKey } from "../../src"; import { confidentialAsset, getBalances, getTestAccount, getTestConfidentialAccount, - longTestTimeout, sendAndWaitTx, - TOKEN_ADDRESS, -} from "../../helpers"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; + MOCK_TOKEN_DATA, +} from "../helpers/e2e"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; +import { longTestTimeout } from "../helpers"; describe("Transfer with auditor", () => { const alice = getTestAccount(); @@ -33,7 +33,7 @@ describe("Transfer with auditor", () => { encryptedActualBalance: balances.actual.amountEncrypted!, amountToTransfer: TRANSFER_AMOUNT, sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, recipientAddress: alice.accountAddress, auditorEncryptionKeys: [AUDITOR.publicKey()], }); diff --git a/confidential-assets/tests/units/api/withdraw.test.ts b/confidential-assets/tests/api/withdraw.test.ts similarity index 82% rename from confidential-assets/tests/units/api/withdraw.test.ts rename to confidential-assets/tests/api/withdraw.test.ts index d928b8ec6..5ec4a644e 100644 --- a/confidential-assets/tests/units/api/withdraw.test.ts +++ b/confidential-assets/tests/api/withdraw.test.ts @@ -3,11 +3,11 @@ import { getBalances, getTestAccount, getTestConfidentialAccount, - longTestTimeout, sendAndWaitTx, - TOKEN_ADDRESS, -} from "../../helpers"; -import { preloadTables } from "../../helpers/wasmPollardKangaroo"; + MOCK_TOKEN_DATA, +} from "../helpers/e2e"; +import { preloadTables } from "../helpers/wasmPollardKangaroo"; +import { longTestTimeout } from "../helpers"; describe("Withdraw", () => { const alice = getTestAccount(); @@ -27,7 +27,7 @@ describe("Withdraw", () => { const withdrawTx = await confidentialAsset.withdraw({ sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, decryptionKey: aliceConfidential, encryptedActualBalance: balances.actual.amountEncrypted!, amountToWithdraw: WITHDRAW_AMOUNT, diff --git a/confidential-assets/tests/e2e/confidentialCoin.test.ts b/confidential-assets/tests/e2e/confidentialCoin.test.ts index 53d253a28..c836774c1 100644 --- a/confidential-assets/tests/e2e/confidentialCoin.test.ts +++ b/confidential-assets/tests/e2e/confidentialCoin.test.ts @@ -1,14 +1,35 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -import { ConfidentialBalance, ConfidentialAmount, TwistedEd25519PublicKey, TwistedEd25519PrivateKey, TwistedElGamalCiphertext } from "../../src"; -import { getTestAccount, getTestConfidentialAccount, aptos, TOKEN_ADDRESS, sendAndWaitTx, mintFungibleTokens, sendAndWaitBatchTxs, addNewContentLineToFile, longTestTimeout, confidentialAsset } from "../helpers"; +import { + ConfidentialBalance, + ConfidentialAmount, + TwistedEd25519PublicKey, + TwistedEd25519PrivateKey, + TwistedElGamalCiphertext, +} from "../../src"; +import { addNewContentLineToFile, longTestTimeout } from "../helpers"; +import { + getTestAccount, + getTestConfidentialAccount, + aptos, + MOCK_TOKEN_DATA, + sendAndWaitTx, + mintFungibleTokens, + sendAndWaitBatchTxs, + confidentialAsset, + preCheck, +} from "../helpers/e2e"; import { preloadTables } from "../helpers/wasmPollardKangaroo"; describe("Confidential balance api", () => { const alice = getTestAccount(); const aliceConfidential = getTestConfidentialAccount(alice); + beforeAll(async () => { + await preCheck(); + }); + test( "Pre load wasm table map", async () => { @@ -33,14 +54,12 @@ describe("Confidential balance api", () => { let isAliceRegistered = false; test( - "it should check Alice confidential balance registered", + "it should check if Alice's confidential balance is registered already", async () => { isAliceRegistered = await confidentialAsset.hasUserRegistered({ accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); - - expect(isAliceRegistered).toBeTruthy(); }, longTestTimeout, ); @@ -55,7 +74,7 @@ describe("Confidential balance api", () => { const aliceRegisterVBTxBody = await confidentialAsset.registerBalance({ sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, publicKey: aliceConfidential.publicKey(), }); @@ -66,12 +85,24 @@ describe("Confidential balance api", () => { longTestTimeout, ); + test( + "it should confirm that Alice's confidential balance is registered now", + async () => { + const isAliceRegisteredNow = await confidentialAsset.hasUserRegistered({ + accountAddress: alice.accountAddress, + tokenAddress: MOCK_TOKEN_DATA.address, + }); + expect(isAliceRegisteredNow).toBeTruthy(); + }, + longTestTimeout, + ); + let aliceConfidentialBalances: ConfidentialBalance; test( "it should check Alice confidential balances", async () => { const [aliceVB] = await Promise.all([ - confidentialAsset.getBalance({ accountAddress: alice.accountAddress, tokenAddress: TOKEN_ADDRESS }), + confidentialAsset.getBalance({ accountAddress: alice.accountAddress, tokenAddress: MOCK_TOKEN_DATA.address }), ]); aliceConfidentialBalances = aliceVB; @@ -115,7 +146,7 @@ describe("Confidential balance api", () => { async () => { const depositTx = await confidentialAsset.deposit({ sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, amount: DEPOSIT_AMOUNT, }); const resp = await sendAndWaitTx(depositTx, alice); @@ -130,7 +161,7 @@ describe("Confidential balance api", () => { async () => { const aliceChunkedConfidentialBalance = await confidentialAsset.getBalance({ accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); aliceConfidentialBalances = aliceChunkedConfidentialBalance; @@ -144,12 +175,84 @@ describe("Confidential balance api", () => { longTestTimeout, ); + let isAliceBalanceNormalized = true; + let unnormalizedAliceEncryptedBalance: TwistedElGamalCiphertext[]; + test( + "it should check if Alice's confidential balance is normalized already", + async () => { + isAliceBalanceNormalized = await confidentialAsset.isUserBalanceNormalized({ + accountAddress: alice.accountAddress, + tokenAddress: MOCK_TOKEN_DATA.address, + }); + + if (!isAliceBalanceNormalized) { + const unnormalizedAliceBalances = await confidentialAsset.getBalance({ + accountAddress: alice.accountAddress, + tokenAddress: MOCK_TOKEN_DATA.address, + }); + + unnormalizedAliceEncryptedBalance = unnormalizedAliceBalances.actual; + } + }, + longTestTimeout, + ); + + test( + "it should normalize Alice's confidential balance if necessary", + async () => { + if (unnormalizedAliceEncryptedBalance && !isAliceBalanceNormalized) { + const unnormalizedConfidentialAmount = await ConfidentialAmount.fromEncrypted( + unnormalizedAliceEncryptedBalance, + aliceConfidential, + { + chunksCount: 2, + }, + ); + + const normalizeTx = await confidentialAsset.normalizeUserBalance({ + tokenAddress: MOCK_TOKEN_DATA.address, + decryptionKey: aliceConfidential, + unnormalizedEncryptedBalance: unnormalizedAliceEncryptedBalance, + balanceAmount: unnormalizedConfidentialAmount.amount, + + sender: alice.accountAddress, + }); + + const txResp = await sendAndWaitTx(normalizeTx, alice); + + expect(txResp.success).toBeTruthy(); + } else { + expect(true).toBeTruthy(); + } + }, + longTestTimeout, + ); + + test( + "it should check Alice's confidential balance after normalization", + async () => { + const aliceChunkedConfidentialBalance = await confidentialAsset.getBalance({ + accountAddress: alice.accountAddress, + tokenAddress: MOCK_TOKEN_DATA.address, + }); + aliceConfidentialBalances = aliceChunkedConfidentialBalance; + + const aliceConfidentialAmount = await ConfidentialAmount.fromEncrypted( + aliceChunkedConfidentialBalance.pending, + aliceConfidential, + ); + + expect(aliceConfidentialAmount.amount).toBeDefined(); + }, + longTestTimeout, + ); + test( "it should safely rollover Alice's confidential balance", async () => { const rolloverTxPayloads = await confidentialAsset.safeRolloverPendingCB({ sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, withFreezeBalance: false, decryptionKey: aliceConfidential, }); @@ -166,7 +269,7 @@ describe("Confidential balance api", () => { async () => { const aliceChunkedConfidentialBalance = await confidentialAsset.getBalance({ accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); aliceConfidentialBalances = aliceChunkedConfidentialBalance; @@ -191,7 +294,7 @@ describe("Confidential balance api", () => { const withdrawTx = await confidentialAsset.withdraw({ sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, decryptionKey: aliceConfidential, encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, amountToWithdraw: WITHDRAW_AMOUNT, @@ -208,7 +311,7 @@ describe("Confidential balance api", () => { async () => { const aliceChunkedConfidentialBalance = await confidentialAsset.getBalance({ accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); aliceConfidentialBalances = aliceChunkedConfidentialBalance; @@ -226,7 +329,7 @@ describe("Confidential balance api", () => { "it should get global auditor", async () => { const [{ vec }] = await confidentialAsset.getAssetAuditor({ - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); const globalAuditorAddress = new TwistedEd25519PublicKey(vec); @@ -245,7 +348,7 @@ describe("Confidential balance api", () => { encryptedActualBalance: aliceConfidentialBalances.actual, amountToTransfer: TRANSFER_AMOUNT, sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, recipientAddress: alice.accountAddress, }); const txResp = await sendAndWaitTx(transferTx, alice); @@ -260,7 +363,7 @@ describe("Confidential balance api", () => { async () => { const aliceChunkedConfidentialBalance = await confidentialAsset.getBalance({ accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); aliceConfidentialBalances = aliceChunkedConfidentialBalance; @@ -284,7 +387,7 @@ describe("Confidential balance api", () => { encryptedActualBalance: aliceConfidentialBalances.actual, amountToTransfer: TRANSFER_AMOUNT, sender: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, recipientAddress: alice.accountAddress, auditorEncryptionKeys: [AUDITOR.publicKey()], }); @@ -300,7 +403,7 @@ describe("Confidential balance api", () => { async () => { const aliceChunkedConfidentialBalance = await confidentialAsset.getBalance({ accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); aliceConfidentialBalances = aliceChunkedConfidentialBalance; @@ -319,7 +422,7 @@ describe("Confidential balance api", () => { async () => { const isFrozen = await confidentialAsset.isBalanceFrozen({ accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); expect(isFrozen).toBeFalsy(); @@ -327,80 +430,6 @@ describe("Confidential balance api", () => { longTestTimeout, ); - let isAliceBalanceNormalized = true; - let unnormalizedAliceEncryptedBalance: TwistedElGamalCiphertext[]; - test( - "it should check Alice's confidential balance is normalized", - async () => { - isAliceBalanceNormalized = await confidentialAsset.isUserBalanceNormalized({ - accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, - }); - - if (!isAliceBalanceNormalized) { - const unnormalizedAliceBalances = await confidentialAsset.getBalance({ - accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, - }); - - unnormalizedAliceEncryptedBalance = unnormalizedAliceBalances.actual; - } - - expect(isAliceBalanceNormalized).toBeTruthy(); - }, - longTestTimeout, - ); - - test( - "it should normalize Alice's confidential balance", - async () => { - if (unnormalizedAliceEncryptedBalance && !isAliceBalanceNormalized) { - const unnormalizedConfidentialAmount = await ConfidentialAmount.fromEncrypted( - unnormalizedAliceEncryptedBalance, - aliceConfidential, - { - chunksCount: 2, - }, - ); - - const normalizeTx = await confidentialAsset.normalizeUserBalance({ - tokenAddress: TOKEN_ADDRESS, - decryptionKey: aliceConfidential, - unnormalizedEncryptedBalance: unnormalizedAliceEncryptedBalance, - balanceAmount: unnormalizedConfidentialAmount.amount, - - sender: alice.accountAddress, - }); - - const txResp = await sendAndWaitTx(normalizeTx, alice); - - expect(txResp.success).toBeTruthy(); - } else { - expect(true).toBeTruthy(); - } - }, - longTestTimeout, - ); - - test( - "it should check Alice's confidential balance after normalization", - async () => { - const aliceChunkedConfidentialBalance = await confidentialAsset.getBalance({ - accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, - }); - aliceConfidentialBalances = aliceChunkedConfidentialBalance; - - const aliceConfidentialAmount = await ConfidentialAmount.fromEncrypted( - aliceChunkedConfidentialBalance.pending, - aliceConfidential, - ); - - expect(aliceConfidentialAmount.amount).toBeDefined(); - }, - longTestTimeout, - ); - const ALICE_NEW_CONFIDENTIAL_PRIVATE_KEY = TwistedEd25519PrivateKey.generate(); test.skip( "it should safely rotate Alice's confidential balance key", @@ -414,7 +443,7 @@ describe("Confidential balance api", () => { currEncryptedBalance: aliceConfidentialBalances.actual, withUnfreezeBalance: true, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); /* eslint-disable no-console */ @@ -436,7 +465,7 @@ describe("Confidential balance api", () => { async () => { const aliceChunkedConfidentialBalance = await confidentialAsset.getBalance({ accountAddress: alice.accountAddress, - tokenAddress: TOKEN_ADDRESS, + tokenAddress: MOCK_TOKEN_DATA.address, }); aliceConfidentialBalances = aliceChunkedConfidentialBalance; diff --git a/confidential-assets/tests/helpers/e2e.ts b/confidential-assets/tests/helpers/e2e.ts new file mode 100644 index 000000000..a7e45d206 --- /dev/null +++ b/confidential-assets/tests/helpers/e2e.ts @@ -0,0 +1,184 @@ +/** + * This file contains helpers for E2E tests, generally meaning they interact with a network. + */ + +import { + Network, + NetworkToNetworkName, + AptosConfig, + Aptos, + AccountAddress, + AnyRawTransaction, + Account, + CommittedTransactionResponse, + InputGenerateTransactionPayloadData, + TransactionWorkerEventsEnum, + Ed25519PrivateKey, + PrivateKey, + PrivateKeyVariants, + Ed25519Account, +} from "@aptos-labs/ts-sdk"; +import { ConfidentialAmount } from "../../src/confidentialAmount"; +import { ConfidentialAsset } from "../../src/confidentialAsset"; +import { TwistedEd25519PrivateKey } from "../../src/twistedEd25519"; + +export const TESTING_NETWORK = process.env.TESTING_NETWORK || Network.TESTNET; + +export type MockTokenData = { + address: string; + mintingPayload: InputGenerateTransactionPayloadData; +}; + +function getMockTokenData(): MockTokenData { + if (TESTING_NETWORK === Network.TESTNET) { + return { + address: "0xd5d0d561493ea2b9410f67da804653ae44e793c2423707d4f11edb2e38192050", + mintingPayload: { + function: `0x24246c14448a5994d9f23e3b978da2a354e64b6dfe54220debb8850586c448cc::usdt::faucet`, + functionArguments: [5000000], + }, + }; + } + + throw new Error(`No default token data for network ${TESTING_NETWORK}, set MOCK_TOKEN_ADDRESS`); +} + +function getConfidentialAssetModuleAddress(): string { + if (process.env.CONFIDENTIAL_ASSETS_MODULE_ADDRESS) { + return process.env.CONFIDENTIAL_ASSETS_MODULE_ADDRESS; + } + + if (TESTING_NETWORK === Network.TESTNET) { + return "0x7571d0b7084d07cbc74b8a6c904d9bea6e1e9c5c4fdcf61b77cecd7f471421bc"; + } + + throw new Error( + `No default confidential asset module address for network ${TESTING_NETWORK}, set CONFIDENTIAL_ASSETS_MODULE_ADDRESS`, + ); +} + +export const MOCK_TOKEN_DATA = getMockTokenData(); +export const CONFIDENTIAL_ASSETS_MODULE_ADDRESS = getConfidentialAssetModuleAddress(); + +const APTOS_NETWORK: Network = NetworkToNetworkName[TESTING_NETWORK]; +const config = new AptosConfig({ network: APTOS_NETWORK }); +export const confidentialAsset = new ConfidentialAsset(config, { + confidentialAssetModuleAddress: CONFIDENTIAL_ASSETS_MODULE_ADDRESS, +}); +export const aptos = new Aptos(config); + +/** Catch common issues, particularly with trying to test against testnet. */ +export async function preCheck() { + if (TESTING_NETWORK === Network.TESTNET) { + if (!process.env.TESTNET_PK) { + throw new Error("TESTNET_PK must be set if the network is testnet"); + } + + const privateKey = new Ed25519PrivateKey(process.env.TESTNET_PK); + const account = Account.fromPrivateKey({ privateKey }); + try { + const aptBalance = await aptos.account.getAccountAPTAmount({ accountAddress: account.accountAddress }); + if (aptBalance === 0) { + throw new Error( + "TESTNET_PK does not correspond to an account with APT, please use a valid testnet private key", + ); + } + } catch (e) { + throw new Error("TESTNET_PK does not correspond to an existing account, please use a valid testnet private key"); + } + } +} + +export const getBalances = async ( + decryptionKey: TwistedEd25519PrivateKey, + accountAddress: AccountAddress, + tokenAddress = MOCK_TOKEN_DATA.address, +) => { + const aliceChunkedConfidentialBalance = await confidentialAsset.getBalance({ + accountAddress, + tokenAddress, + }); + + const aliceConfidentialAmountPending = await ConfidentialAmount.fromEncrypted( + aliceChunkedConfidentialBalance.pending, + decryptionKey, + ); + const aliceConfidentialAmountActual = await ConfidentialAmount.fromEncrypted( + aliceChunkedConfidentialBalance.actual, + decryptionKey, + ); + + return { + pending: aliceConfidentialAmountPending, + actual: aliceConfidentialAmountActual, + }; +}; + +export const sendAndWaitTx = async ( + transaction: AnyRawTransaction, + signer: Account, +): Promise => { + const pendingTxn = await aptos.signAndSubmitTransaction({ signer, transaction }); + return aptos.waitForTransaction({ transactionHash: pendingTxn.hash }); +}; + +export const sendAndWaitBatchTxs = async ( + txPayloads: InputGenerateTransactionPayloadData[], + sender: Account, +): Promise => { + aptos.transaction.batch.forSingleAccount({ + sender, + data: txPayloads, + }); + + let allTxSentPromiseResolve: (value: void | PromiseLike) => void; + + const txHashes: string[] = []; + aptos.transaction.batch.on(TransactionWorkerEventsEnum.TransactionSent, async (data) => { + txHashes.push(data.transactionHash); + + if (txHashes.length === txPayloads.length) { + allTxSentPromiseResolve(); + } + }); + + await new Promise((resolve) => { + allTxSentPromiseResolve = resolve; + }); + + return Promise.all(txHashes.map((txHash) => aptos.waitForTransaction({ transactionHash: txHash }))); +}; + +export const getTestAccount = () => { + if (process.env.TESTNET_PK) { + return Account.fromPrivateKey({ + privateKey: new Ed25519PrivateKey( + PrivateKey.formatPrivateKey(process.env.TESTNET_PK, PrivateKeyVariants.Ed25519), + ), + }); + } + + return Account.generate(); +}; + +export const getTestConfidentialAccount = (account?: Ed25519Account) => { + if (process.env.TESTNET_DK) { + return new TwistedEd25519PrivateKey(process.env.TESTNET_DK); + } + + if (!account) return TwistedEd25519PrivateKey.generate(); + + const signature = account.sign(TwistedEd25519PrivateKey.decryptionKeyDerivationMessage); + + return TwistedEd25519PrivateKey.fromSignature(signature); +}; + +/** This mints USDt. Only tested with testnet. */ +export const mintFungibleTokens = async (account: Account) => { + const transaction = await aptos.transaction.build.simple({ + sender: account.accountAddress, + data: MOCK_TOKEN_DATA.mintingPayload, + }); + const pendingTxn = await aptos.signAndSubmitTransaction({ signer: account, transaction }); + return aptos.waitForTransaction({ transactionHash: pendingTxn.hash }); +}; diff --git a/confidential-assets/tests/helpers/index.ts b/confidential-assets/tests/helpers/index.ts index ee1b454bf..9665d4b3e 100644 --- a/confidential-assets/tests/helpers/index.ts +++ b/confidential-assets/tests/helpers/index.ts @@ -1,129 +1,18 @@ import path from "path"; import fs from "fs"; import { genBatchRangeZKP, generateRangeZKP, verifyBatchRangeZKP, verifyRangeZKP } from "./wasmRangeProof"; -import { Network, NetworkToNetworkName, AptosConfig, Aptos, AccountAddress, AnyRawTransaction, Account, CommittedTransactionResponse, InputGenerateTransactionPayloadData, TransactionWorkerEventsEnum, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants, Ed25519Account } from "@aptos-labs/ts-sdk"; -import { ConfidentialAmount } from "../../src/confidentialAmount"; -import { ConfidentialAsset } from "../../src/confidentialAsset"; import { RangeProofExecutor } from "../../src/rangeProof"; -import { TwistedEd25519PrivateKey } from "../../src/twistedEd25519"; -import { DEFAULT_CONFIDENTIAL_COIN_MODULE_ADDRESS } from "../../src"; export const longTestTimeout = 120 * 1000; -/** - * Address of the mocked fungible token on the testnet - */ -export const TOKEN_ADDRESS = "0x8b4dd7ebf8150f349675dde8bd2e9daa66461107b181a67e764de85d82bbac21"; -// export const TOKEN_ADDRESS = "0xb63fe2a70847e0b34b309eab304fc8854b482a2e8eb2ebfb8080c511def0dacf"; - -const APTOS_NETWORK: Network = NetworkToNetworkName[Network.DEVNET]; -const config = new AptosConfig({ network: APTOS_NETWORK }); -export const confidentialAsset = new ConfidentialAsset(config); -export const aptos = new Aptos(config); - const rootDir = path.resolve(__dirname, "../../../"); export const addNewContentLineToFile = (filename: string, data: string) => { - const filePath = path.resolve(rootDir, filename); - - const content = `\n#TESTNET_DK=${data}\n`; - - fs.appendFileSync(filePath, content); -}; - -export const getBalances = async (decryptionKey: TwistedEd25519PrivateKey, accountAddress: AccountAddress, tokenAddress = TOKEN_ADDRESS) => { - const aliceChunkedConfidentialBalance = await confidentialAsset.getBalance({ - accountAddress, - tokenAddress, - }); - - const aliceConfidentialAmountPending = await ConfidentialAmount.fromEncrypted( - aliceChunkedConfidentialBalance.pending, - decryptionKey, - ); - const aliceConfidentialAmountActual = await ConfidentialAmount.fromEncrypted( - aliceChunkedConfidentialBalance.actual, - decryptionKey, - ); - - return { - pending: aliceConfidentialAmountPending, - actual: aliceConfidentialAmountActual, - }; -}; - -export const sendAndWaitTx = async ( - transaction: AnyRawTransaction, - signer: Account, -): Promise => { - const pendingTxn = await aptos.signAndSubmitTransaction({ signer, transaction }); - return aptos.waitForTransaction({ transactionHash: pendingTxn.hash }); -}; - -export const sendAndWaitBatchTxs = async ( - txPayloads: InputGenerateTransactionPayloadData[], - sender: Account, -): Promise => { - aptos.transaction.batch.forSingleAccount({ - sender, - data: txPayloads, - }); - - let allTxSentPromiseResolve: (value: void | PromiseLike) => void; + const filePath = path.resolve(rootDir, filename); - const txHashes: string[] = []; - aptos.transaction.batch.on(TransactionWorkerEventsEnum.TransactionSent, async (data) => { - txHashes.push(data.transactionHash); - - if (txHashes.length === txPayloads.length) { - allTxSentPromiseResolve(); - } - }); - - await new Promise((resolve) => { - allTxSentPromiseResolve = resolve; - }); - - return Promise.all(txHashes.map((txHash) => aptos.waitForTransaction({ transactionHash: txHash }))); -}; - -export const getTestAccount = () => { - if (process.env.TESTNET_PK) { - return Account.fromPrivateKey({ - privateKey: new Ed25519PrivateKey(PrivateKey.formatPrivateKey(process.env.TESTNET_PK, PrivateKeyVariants.Ed25519)), - }); - } - - return Account.generate(); -}; - -export const getTestConfidentialAccount = (account?: Ed25519Account) => { - if (process.env.TESTNET_DK) { - return new TwistedEd25519PrivateKey(process.env.TESTNET_DK); - } - - if (!account) return TwistedEd25519PrivateKey.generate(); - - const signature = account.sign(TwistedEd25519PrivateKey.decryptionKeyDerivationMessage); - - return TwistedEd25519PrivateKey.fromSignature(signature); -}; + const content = `\n#TESTNET_DK=${data}\n`; -/** - * TOKEN_ADDRESS is binded to ConfidentialCoin.CONFIDENTIAL_COIN_MODULE_ADDRESS mock token, be aware of that when minting tokens - * Make sure you are minting the token that is actual TOKEN_ADDRESS - * @param account - */ -export const mintFungibleTokens = async (account: Account) => { - const transaction = await aptos.transaction.build.simple({ - sender: account.accountAddress, - data: { - function: `${DEFAULT_CONFIDENTIAL_COIN_MODULE_ADDRESS}::mock_token::mint_to`, - functionArguments: [500], - }, - }); - const pendingTxn = await aptos.signAndSubmitTransaction({ signer: account, transaction }); - return aptos.waitForTransaction({ transactionHash: pendingTxn.hash }); + fs.appendFileSync(filePath, content); }; RangeProofExecutor.setGenBatchRangeZKP(genBatchRangeZKP); diff --git a/confidential-assets/tests/helpers/wasmPollardKangaroo.ts b/confidential-assets/tests/helpers/wasmPollardKangaroo.ts index 7a1a28e16..62a37245a 100644 --- a/confidential-assets/tests/helpers/wasmPollardKangaroo.ts +++ b/confidential-assets/tests/helpers/wasmPollardKangaroo.ts @@ -7,7 +7,7 @@ import { bytesToNumberLE } from "@noble/curves/abstract/utils"; import { ConfidentialAmount, TwistedEd25519PrivateKey, TwistedElGamal, TwistedElGamalCiphertext } from "../../src"; const POLLARD_KANGAROO_WASM_URL = - 'https://unpkg.com/@aptos-labs/confidential-asset-wasm-bindings@0.0.2/pollard-kangaroo/aptos_pollard_kangaroo_wasm_bg.wasm'; + "https://unpkg.com/@aptos-labs/confidential-asset-wasm-bindings@0.0.2/pollard-kangaroo/aptos_pollard_kangaroo_wasm_bg.wasm"; export async function createKangaroo(secret_size: number) { await initWasm({ module_or_path: POLLARD_KANGAROO_WASM_URL }); diff --git a/confidential-assets/tests/helpers/wasmRangeProof.ts b/confidential-assets/tests/helpers/wasmRangeProof.ts index c8e7b80c8..62b60a817 100644 --- a/confidential-assets/tests/helpers/wasmRangeProof.ts +++ b/confidential-assets/tests/helpers/wasmRangeProof.ts @@ -15,7 +15,7 @@ import { } from "../../src"; const RANGE_PROOF_WASM_URL = - 'https://unpkg.com/@aptos-labs/confidential-asset-wasm-bindings@0.0.2/range-proofs/aptos_rp_wasm_bg.wasm'; + "https://unpkg.com/@aptos-labs/confidential-asset-wasm-bindings@0.0.2/range-proofs/aptos_rp_wasm_bg.wasm"; /** * Generate range Zero Knowledge Proof diff --git a/confidential-assets/tests/move/README.md b/confidential-assets/tests/move/README.md new file mode 100644 index 000000000..b51d8596e --- /dev/null +++ b/confidential-assets/tests/move/README.md @@ -0,0 +1 @@ +See the README in the parent directory for what to do with this. diff --git a/confidential-assets/tests/units/confidentialProofs.test.ts b/confidential-assets/tests/units/confidentialProofs.test.ts index 4b2a0304f..852a36682 100644 --- a/confidential-assets/tests/units/confidentialProofs.test.ts +++ b/confidential-assets/tests/units/confidentialProofs.test.ts @@ -1,4 +1,17 @@ -import { ConfidentialAmount, ConfidentialKeyRotation, ConfidentialKeyRotationSigmaProof, ConfidentialNormalization, ConfidentialNormalizationSigmaProof, ConfidentialTransfer, ConfidentialTransferRangeProof, ConfidentialTransferSigmaProof, ConfidentialWithdraw, ConfidentialWithdrawSigmaProof, toTwistedEd25519PrivateKey, TwistedEd25519PrivateKey } from "../../src"; +import { + ConfidentialAmount, + ConfidentialKeyRotation, + ConfidentialKeyRotationSigmaProof, + ConfidentialNormalization, + ConfidentialNormalizationSigmaProof, + ConfidentialTransfer, + ConfidentialTransferRangeProof, + ConfidentialTransferSigmaProof, + ConfidentialWithdraw, + ConfidentialWithdrawSigmaProof, + toTwistedEd25519PrivateKey, + TwistedEd25519PrivateKey, +} from "../../src"; import { preloadTables } from "../helpers/wasmPollardKangaroo"; import { longTestTimeout } from "../helpers"; @@ -22,206 +35,278 @@ describe("Generate 'confidential coin' proofs", () => { const WITHDRAW_AMOUNT = 2n ** 16n; let confidentialWithdraw: ConfidentialWithdraw; let confidentialWithdrawSigmaProof: ConfidentialWithdrawSigmaProof; - test("Generate withdraw sigma proof", async () => { - confidentialWithdraw = await ConfidentialWithdraw.create({ - decryptionKey: toTwistedEd25519PrivateKey(aliceConfidentialDecryptionKey), - encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, - amountToWithdraw: WITHDRAW_AMOUNT, - }); - - confidentialWithdrawSigmaProof = await confidentialWithdraw.genSigmaProof(); - - expect(confidentialWithdrawSigmaProof).toBeDefined(); - }, longTestTimeout); - - test("Verify withdraw sigma proof", async () => { - const isValid = ConfidentialWithdraw.verifySigmaProof({ - publicKey: aliceConfidentialDecryptionKey.publicKey(), - encryptedActualBalance: confidentialWithdraw.encryptedActualBalanceAmount, - encryptedActualBalanceAfterWithdraw: confidentialWithdraw.confidentialAmountAfterWithdraw!.amountEncrypted!, - amountToWithdraw: WITHDRAW_AMOUNT, - sigmaProof: confidentialWithdrawSigmaProof, - }); - - expect(isValid).toBeTruthy(); - }, longTestTimeout); + test( + "Generate withdraw sigma proof", + async () => { + confidentialWithdraw = await ConfidentialWithdraw.create({ + decryptionKey: toTwistedEd25519PrivateKey(aliceConfidentialDecryptionKey), + encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, + amountToWithdraw: WITHDRAW_AMOUNT, + }); + + confidentialWithdrawSigmaProof = await confidentialWithdraw.genSigmaProof(); + + expect(confidentialWithdrawSigmaProof).toBeDefined(); + }, + longTestTimeout, + ); + + test( + "Verify withdraw sigma proof", + async () => { + const isValid = ConfidentialWithdraw.verifySigmaProof({ + publicKey: aliceConfidentialDecryptionKey.publicKey(), + encryptedActualBalance: confidentialWithdraw.encryptedActualBalanceAmount, + encryptedActualBalanceAfterWithdraw: confidentialWithdraw.confidentialAmountAfterWithdraw!.amountEncrypted!, + amountToWithdraw: WITHDRAW_AMOUNT, + sigmaProof: confidentialWithdrawSigmaProof, + }); + + expect(isValid).toBeTruthy(); + }, + longTestTimeout, + ); let confidentialWithdrawRangeProof: Uint8Array; - test("Generate withdraw range proof", async () => { - confidentialWithdrawRangeProof = await confidentialWithdraw.genRangeProof(); - }, longTestTimeout); - test("Verify withdraw range proof", async () => { - const isValid = ConfidentialWithdraw.verifyRangeProof({ - rangeProof: confidentialWithdrawRangeProof, - encryptedActualBalanceAfterWithdraw: confidentialWithdraw.confidentialAmountAfterWithdraw!.amountEncrypted!, - }); - - expect(isValid).toBeTruthy(); - }, longTestTimeout); + test( + "Generate withdraw range proof", + async () => { + confidentialWithdrawRangeProof = await confidentialWithdraw.genRangeProof(); + }, + longTestTimeout, + ); + test( + "Verify withdraw range proof", + async () => { + const isValid = ConfidentialWithdraw.verifyRangeProof({ + rangeProof: confidentialWithdrawRangeProof, + encryptedActualBalanceAfterWithdraw: confidentialWithdraw.confidentialAmountAfterWithdraw!.amountEncrypted!, + }); + + expect(isValid).toBeTruthy(); + }, + longTestTimeout, + ); const TRANSFER_AMOUNT = 10n; let confidentialTransfer: ConfidentialTransfer; let confidentialTransferSigmaProof: ConfidentialTransferSigmaProof; - test("Generate transfer sigma proof", async () => { - confidentialTransfer = await ConfidentialTransfer.create({ - senderDecryptionKey: aliceConfidentialDecryptionKey, - encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, - amountToTransfer: TRANSFER_AMOUNT, - recipientEncryptionKey: bobConfidentialDecryptionKey.publicKey(), - }); - - confidentialTransferSigmaProof = await confidentialTransfer.genSigmaProof(); - - expect(confidentialTransferSigmaProof).toBeDefined(); - }, longTestTimeout); - - test("Verify transfer sigma proof", () => { - const isValid = ConfidentialTransfer.verifySigmaProof({ - senderPrivateKey: aliceConfidentialDecryptionKey, - recipientPublicKey: bobConfidentialDecryptionKey.publicKey(), - encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, - encryptedActualBalanceAfterTransfer: confidentialTransfer.confidentialAmountAfterTransfer?.amountEncrypted!, - encryptedTransferAmountByRecipient: confidentialTransfer.encryptedAmountByRecipient, - sigmaProof: confidentialTransferSigmaProof, - }); - - expect(isValid).toBeTruthy(); - }, longTestTimeout); + test( + "Generate transfer sigma proof", + async () => { + confidentialTransfer = await ConfidentialTransfer.create({ + senderDecryptionKey: aliceConfidentialDecryptionKey, + encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, + amountToTransfer: TRANSFER_AMOUNT, + recipientEncryptionKey: bobConfidentialDecryptionKey.publicKey(), + }); + + confidentialTransferSigmaProof = await confidentialTransfer.genSigmaProof(); + + expect(confidentialTransferSigmaProof).toBeDefined(); + }, + longTestTimeout, + ); + + test( + "Verify transfer sigma proof", + () => { + const isValid = ConfidentialTransfer.verifySigmaProof({ + senderPrivateKey: aliceConfidentialDecryptionKey, + recipientPublicKey: bobConfidentialDecryptionKey.publicKey(), + encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, + encryptedActualBalanceAfterTransfer: confidentialTransfer.confidentialAmountAfterTransfer?.amountEncrypted!, + encryptedTransferAmountByRecipient: confidentialTransfer.encryptedAmountByRecipient, + sigmaProof: confidentialTransferSigmaProof, + }); + + expect(isValid).toBeTruthy(); + }, + longTestTimeout, + ); let confidentialTransferRangeProofs: ConfidentialTransferRangeProof; - test("Generate transfer range proofs", async () => { - confidentialTransferRangeProofs = await confidentialTransfer.genRangeProof(); - }, longTestTimeout); - test("Verify transfer range proofs", async () => { - const isValid = await ConfidentialTransfer.verifyRangeProof({ - encryptedAmountByRecipient: confidentialTransfer.encryptedAmountByRecipient, - encryptedActualBalanceAfterTransfer: confidentialTransfer.confidentialAmountAfterTransfer!.amountEncrypted!, - rangeProofAmount: confidentialTransferRangeProofs.rangeProofAmount, - rangeProofNewBalance: confidentialTransferRangeProofs.rangeProofNewBalance, - }); - - expect(isValid).toBeTruthy(); - }, longTestTimeout); + test( + "Generate transfer range proofs", + async () => { + confidentialTransferRangeProofs = await confidentialTransfer.genRangeProof(); + }, + longTestTimeout, + ); + test( + "Verify transfer range proofs", + async () => { + const isValid = await ConfidentialTransfer.verifyRangeProof({ + encryptedAmountByRecipient: confidentialTransfer.encryptedAmountByRecipient, + encryptedActualBalanceAfterTransfer: confidentialTransfer.confidentialAmountAfterTransfer!.amountEncrypted!, + rangeProofAmount: confidentialTransferRangeProofs.rangeProofAmount, + rangeProofNewBalance: confidentialTransferRangeProofs.rangeProofNewBalance, + }); + + expect(isValid).toBeTruthy(); + }, + longTestTimeout, + ); const auditor = TwistedEd25519PrivateKey.generate(); let confidentialTransferWithAuditors: ConfidentialTransfer; let confidentialTransferWithAuditorsSigmaProof: ConfidentialTransferSigmaProof; - test("Generate transfer with auditors sigma proof", async () => { - confidentialTransferWithAuditors = await ConfidentialTransfer.create({ - senderDecryptionKey: aliceConfidentialDecryptionKey, - encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, - amountToTransfer: TRANSFER_AMOUNT, - recipientEncryptionKey: bobConfidentialDecryptionKey.publicKey(), - auditorEncryptionKeys: [auditor.publicKey()], - }); - - confidentialTransferWithAuditorsSigmaProof = await confidentialTransferWithAuditors.genSigmaProof(); - - expect(confidentialTransferWithAuditorsSigmaProof).toBeDefined(); - }, longTestTimeout); - test("Verify transfer with auditors sigma proof", () => { - const isValid = ConfidentialTransfer.verifySigmaProof({ - senderPrivateKey: aliceConfidentialDecryptionKey, - recipientPublicKey: bobConfidentialDecryptionKey.publicKey(), - encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, - encryptedActualBalanceAfterTransfer: - confidentialTransferWithAuditors.confidentialAmountAfterTransfer!.amountEncrypted!, - encryptedTransferAmountByRecipient: confidentialTransferWithAuditors.encryptedAmountByRecipient, - sigmaProof: confidentialTransferWithAuditorsSigmaProof, - auditors: { - publicKeys: [auditor.publicKey()], - auditorsCBList: confidentialTransferWithAuditors.auditorsCBList!, - }, - }); - - expect(isValid).toBeTruthy(); - }, longTestTimeout); - test("Should fail transfer sigma proof verification with wrong auditors", () => { - const invalidAuditor = TwistedEd25519PrivateKey.generate(); - - const isValid = ConfidentialTransfer.verifySigmaProof({ - senderPrivateKey: aliceConfidentialDecryptionKey, - recipientPublicKey: bobConfidentialDecryptionKey.publicKey(), - encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, - encryptedActualBalanceAfterTransfer: - confidentialTransferWithAuditors.confidentialAmountAfterTransfer!.amountEncrypted!, - encryptedTransferAmountByRecipient: confidentialTransferWithAuditors.encryptedAmountByRecipient, - sigmaProof: confidentialTransferWithAuditorsSigmaProof, - auditors: { - publicKeys: [invalidAuditor.publicKey()], - // decryptionKeys: auditorsDList, - auditorsCBList: confidentialTransferWithAuditors.auditorsCBList!, - }, - }); - - expect(isValid).toBeFalsy(); - }, longTestTimeout); + test( + "Generate transfer with auditors sigma proof", + async () => { + confidentialTransferWithAuditors = await ConfidentialTransfer.create({ + senderDecryptionKey: aliceConfidentialDecryptionKey, + encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, + amountToTransfer: TRANSFER_AMOUNT, + recipientEncryptionKey: bobConfidentialDecryptionKey.publicKey(), + auditorEncryptionKeys: [auditor.publicKey()], + }); + + confidentialTransferWithAuditorsSigmaProof = await confidentialTransferWithAuditors.genSigmaProof(); + + expect(confidentialTransferWithAuditorsSigmaProof).toBeDefined(); + }, + longTestTimeout, + ); + test( + "Verify transfer with auditors sigma proof", + () => { + const isValid = ConfidentialTransfer.verifySigmaProof({ + senderPrivateKey: aliceConfidentialDecryptionKey, + recipientPublicKey: bobConfidentialDecryptionKey.publicKey(), + encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, + encryptedActualBalanceAfterTransfer: + confidentialTransferWithAuditors.confidentialAmountAfterTransfer!.amountEncrypted!, + encryptedTransferAmountByRecipient: confidentialTransferWithAuditors.encryptedAmountByRecipient, + sigmaProof: confidentialTransferWithAuditorsSigmaProof, + auditors: { + publicKeys: [auditor.publicKey()], + auditorsCBList: confidentialTransferWithAuditors.auditorsCBList!, + }, + }); + + expect(isValid).toBeTruthy(); + }, + longTestTimeout, + ); + test( + "Should fail transfer sigma proof verification with wrong auditors", + () => { + const invalidAuditor = TwistedEd25519PrivateKey.generate(); + + const isValid = ConfidentialTransfer.verifySigmaProof({ + senderPrivateKey: aliceConfidentialDecryptionKey, + recipientPublicKey: bobConfidentialDecryptionKey.publicKey(), + encryptedActualBalance: aliceConfidentialAmount.amountEncrypted!, + encryptedActualBalanceAfterTransfer: + confidentialTransferWithAuditors.confidentialAmountAfterTransfer!.amountEncrypted!, + encryptedTransferAmountByRecipient: confidentialTransferWithAuditors.encryptedAmountByRecipient, + sigmaProof: confidentialTransferWithAuditorsSigmaProof, + auditors: { + publicKeys: [invalidAuditor.publicKey()], + // decryptionKeys: auditorsDList, + auditorsCBList: confidentialTransferWithAuditors.auditorsCBList!, + }, + }); + + expect(isValid).toBeFalsy(); + }, + longTestTimeout, + ); let confidentialTransferWithAuditorsRangeProofs: ConfidentialTransferRangeProof; - test("Generate transfer with auditors range proofs", async () => { - confidentialTransferWithAuditorsRangeProofs = await confidentialTransferWithAuditors.genRangeProof(); - - expect(confidentialTransferWithAuditorsRangeProofs).toBeDefined(); - }, longTestTimeout); - test("Verify transfer with auditors range proofs", async () => { - const isValid = await ConfidentialTransfer.verifyRangeProof({ - encryptedAmountByRecipient: confidentialTransferWithAuditors.encryptedAmountByRecipient, - encryptedActualBalanceAfterTransfer: - confidentialTransferWithAuditors.confidentialAmountAfterTransfer!.amountEncrypted!, - rangeProofAmount: confidentialTransferWithAuditorsRangeProofs.rangeProofAmount, - rangeProofNewBalance: confidentialTransferWithAuditorsRangeProofs.rangeProofNewBalance, - }); - - expect(isValid).toBeTruthy(); - }, longTestTimeout); + test( + "Generate transfer with auditors range proofs", + async () => { + confidentialTransferWithAuditorsRangeProofs = await confidentialTransferWithAuditors.genRangeProof(); + + expect(confidentialTransferWithAuditorsRangeProofs).toBeDefined(); + }, + longTestTimeout, + ); + test( + "Verify transfer with auditors range proofs", + async () => { + const isValid = await ConfidentialTransfer.verifyRangeProof({ + encryptedAmountByRecipient: confidentialTransferWithAuditors.encryptedAmountByRecipient, + encryptedActualBalanceAfterTransfer: + confidentialTransferWithAuditors.confidentialAmountAfterTransfer!.amountEncrypted!, + rangeProofAmount: confidentialTransferWithAuditorsRangeProofs.rangeProofAmount, + rangeProofNewBalance: confidentialTransferWithAuditorsRangeProofs.rangeProofNewBalance, + }); + + expect(isValid).toBeTruthy(); + }, + longTestTimeout, + ); const newAliceConfidentialPrivateKey = TwistedEd25519PrivateKey.generate(); let confidentialKeyRotation: ConfidentialKeyRotation; let confidentialKeyRotationSigmaProof: ConfidentialKeyRotationSigmaProof; - test("Generate key rotation sigma proof", async () => { - confidentialKeyRotation = await ConfidentialKeyRotation.create({ - currDecryptionKey: aliceConfidentialDecryptionKey, - currEncryptedBalance: aliceConfidentialAmount.amountEncrypted!, - newDecryptionKey: newAliceConfidentialPrivateKey, - }); - - confidentialKeyRotationSigmaProof = await confidentialKeyRotation.genSigmaProof(); - - expect(confidentialKeyRotationSigmaProof).toBeDefined(); - }, longTestTimeout); - test("Verify key rotation sigma proof", () => { - const isValid = ConfidentialKeyRotation.verifySigmaProof({ - sigmaProof: confidentialKeyRotationSigmaProof, - currPublicKey: aliceConfidentialDecryptionKey.publicKey(), - newPublicKey: newAliceConfidentialPrivateKey.publicKey(), - currEncryptedBalance: aliceConfidentialAmount.amountEncrypted!, - newEncryptedBalance: confidentialKeyRotation.newConfidentialAmount.amountEncrypted!, - }); - - expect(isValid).toBeTruthy(); - }, longTestTimeout); + test( + "Generate key rotation sigma proof", + async () => { + confidentialKeyRotation = await ConfidentialKeyRotation.create({ + currDecryptionKey: aliceConfidentialDecryptionKey, + currEncryptedBalance: aliceConfidentialAmount.amountEncrypted!, + newDecryptionKey: newAliceConfidentialPrivateKey, + }); + + confidentialKeyRotationSigmaProof = await confidentialKeyRotation.genSigmaProof(); + + expect(confidentialKeyRotationSigmaProof).toBeDefined(); + }, + longTestTimeout, + ); + test( + "Verify key rotation sigma proof", + () => { + const isValid = ConfidentialKeyRotation.verifySigmaProof({ + sigmaProof: confidentialKeyRotationSigmaProof, + currPublicKey: aliceConfidentialDecryptionKey.publicKey(), + newPublicKey: newAliceConfidentialPrivateKey.publicKey(), + currEncryptedBalance: aliceConfidentialAmount.amountEncrypted!, + newEncryptedBalance: confidentialKeyRotation.newConfidentialAmount.amountEncrypted!, + }); + + expect(isValid).toBeTruthy(); + }, + longTestTimeout, + ); let confidentialKeyRotationRangeProof: Uint8Array; - test("Generate key rotation range proof", async () => { - confidentialKeyRotationRangeProof = await confidentialKeyRotation.genRangeProof(); + test( + "Generate key rotation range proof", + async () => { + confidentialKeyRotationRangeProof = await confidentialKeyRotation.genRangeProof(); - expect(confidentialKeyRotationRangeProof).toBeDefined(); - }, longTestTimeout); - test("Verify key rotation range proof", async () => { - const isValid = ConfidentialKeyRotation.verifyRangeProof({ - rangeProof: confidentialKeyRotationRangeProof, - newEncryptedBalance: confidentialKeyRotation.newConfidentialAmount!.amountEncrypted!, - }); + expect(confidentialKeyRotationRangeProof).toBeDefined(); + }, + longTestTimeout, + ); + test( + "Verify key rotation range proof", + async () => { + const isValid = ConfidentialKeyRotation.verifyRangeProof({ + rangeProof: confidentialKeyRotationRangeProof, + newEncryptedBalance: confidentialKeyRotation.newConfidentialAmount!.amountEncrypted!, + }); - expect(isValid).toBeTruthy(); - }, longTestTimeout); + expect(isValid).toBeTruthy(); + }, + longTestTimeout, + ); - test("Authorize Key Rotation", async () => { - const [{ sigmaProof, rangeProof }, newVB] = await confidentialKeyRotation.authorizeKeyRotation(); + test( + "Authorize Key Rotation", + async () => { + const [{ sigmaProof, rangeProof }, newVB] = await confidentialKeyRotation.authorizeKeyRotation(); - expect(sigmaProof).toBeDefined(); - expect(rangeProof).toBeDefined(); - expect(newVB).toBeDefined(); - }, longTestTimeout); + expect(sigmaProof).toBeDefined(); + expect(rangeProof).toBeDefined(); + expect(newVB).toBeDefined(); + }, + longTestTimeout, + ); const unnormalizedAliceConfidentialAmount = ConfidentialAmount.fromChunks([ ...Array.from({ length: ConfidentialAmount.CHUNKS_COUNT - 1 }, () => 2n ** ConfidentialAmount.CHUNK_BITS_BI + 100n), @@ -231,39 +316,55 @@ describe("Generate 'confidential coin' proofs", () => { let confidentialNormalization: ConfidentialNormalization; let confidentialNormalizationSigmaProof: ConfidentialNormalizationSigmaProof; - test("Generate normalization sigma proof", async () => { - confidentialNormalization = await ConfidentialNormalization.create({ - decryptionKey: aliceConfidentialDecryptionKey, - unnormalizedEncryptedBalance: unnormalizedAliceConfidentialAmount.amountEncrypted!, - balanceAmount: unnormalizedAliceConfidentialAmount.amount, - }); - - confidentialNormalizationSigmaProof = await confidentialNormalization.genSigmaProof(); - - expect(confidentialNormalizationSigmaProof).toBeDefined(); - }, longTestTimeout); - test("Verify normalization sigma proof", () => { - const isValid = ConfidentialNormalization.verifySigmaProof({ - publicKey: aliceConfidentialDecryptionKey.publicKey(), - sigmaProof: confidentialNormalizationSigmaProof, - unnormalizedEncryptedBalance: unnormalizedAliceConfidentialAmount.amountEncrypted!, - normalizedEncryptedBalance: confidentialNormalization.normalizedConfidentialAmount!.amountEncrypted!, - }); - - expect(isValid).toBeTruthy(); - }, longTestTimeout); + test( + "Generate normalization sigma proof", + async () => { + confidentialNormalization = await ConfidentialNormalization.create({ + decryptionKey: aliceConfidentialDecryptionKey, + unnormalizedEncryptedBalance: unnormalizedAliceConfidentialAmount.amountEncrypted!, + balanceAmount: unnormalizedAliceConfidentialAmount.amount, + }); + + confidentialNormalizationSigmaProof = await confidentialNormalization.genSigmaProof(); + + expect(confidentialNormalizationSigmaProof).toBeDefined(); + }, + longTestTimeout, + ); + test( + "Verify normalization sigma proof", + () => { + const isValid = ConfidentialNormalization.verifySigmaProof({ + publicKey: aliceConfidentialDecryptionKey.publicKey(), + sigmaProof: confidentialNormalizationSigmaProof, + unnormalizedEncryptedBalance: unnormalizedAliceConfidentialAmount.amountEncrypted!, + normalizedEncryptedBalance: confidentialNormalization.normalizedConfidentialAmount!.amountEncrypted!, + }); + + expect(isValid).toBeTruthy(); + }, + longTestTimeout, + ); let confidentialNormalizationRangeProof: Uint8Array; - test("Generate normalization range proof", async () => { - confidentialNormalizationRangeProof = await confidentialNormalization.genRangeProof(); - - expect(confidentialNormalizationRangeProof).toBeDefined(); - }, longTestTimeout); - test("Verify normalization range proof", async () => { - const isValid = ConfidentialNormalization.verifyRangeProof({ - rangeProof: confidentialNormalizationRangeProof, - normalizedEncryptedBalance: confidentialNormalization.normalizedConfidentialAmount!.amountEncrypted!, - }); - - expect(isValid).toBeTruthy(); - }, longTestTimeout); + test( + "Generate normalization range proof", + async () => { + confidentialNormalizationRangeProof = await confidentialNormalization.genRangeProof(); + + expect(confidentialNormalizationRangeProof).toBeDefined(); + }, + longTestTimeout, + ); + test( + "Verify normalization range proof", + async () => { + const isValid = ConfidentialNormalization.verifyRangeProof({ + rangeProof: confidentialNormalizationRangeProof, + normalizedEncryptedBalance: confidentialNormalization.normalizedConfidentialAmount!.amountEncrypted!, + }); + + expect(isValid).toBeTruthy(); + }, + longTestTimeout, + ); }); diff --git a/package.json b/package.json index a9b41a94e..ad8351c36 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "build:clean": "rm -rf dist", "build": "pnpm build:clean && tsup", "prepublishOnly": "pnpm run build", - "_fmt": "prettier 'src/**/*.ts' 'tests/**/*.ts' 'examples/**/*.js' 'examples/**/*.ts' 'eslint.config.cjs'", + "_fmt": "prettier 'src/**/*.ts' 'confidential-assets/**/*.ts' 'tests/**/*.ts' 'examples/**/*.js' 'examples/**/*.ts' 'eslint.config.cjs'", "fmt": "pnpm _fmt --write", "lint": "eslint '**/*.{cts,mts,ts}'", "test": "pnpm jest ./tests/**/*.test.ts --passWithNoTests",