Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions yarn-project/aztec.js/src/wallet/account_wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export class AccountWallet extends BaseWallet {
super(pxe);
}

getAccount(): AccountInterface {
return this.account;
}

createTxExecutionRequest(exec: ExecutionRequestInit): Promise<TxExecutionRequest> {
return this.account.createTxExecutionRequest(exec);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import { createAccounts } from '@aztec/accounts/testing';
import { type AccountWallet, AztecAddress, Contract, Fr, retryUntil } from '@aztec/aztec.js';
import { AccountWallet, AztecAddress, Contract, Fr, retryUntil } from '@aztec/aztec.js';
import { EntrypointPayload } from '@aztec/aztec.js/entrypoint';
import {
EscrowableTokenContract,
SchnorrAccountContractArtifact,
SimpleEscrowContract,
} from '@aztec/noir-contracts.js';

import { DUPLICATE_NULLIFIER_ERROR } from '../../fixtures/fixtures.js';
import { setupPXEService } from '../../fixtures/utils.js';
import { EscrowTokenContractTest, toAddressOption } from '../escrowable_token_contract_test.js';

describe('e2e_escrowable_token_contract escrow transfer private', () => {
let teardownB: () => Promise<void>;

const t = new EscrowTokenContractTest('transfer_private');
let { asset, tokenSim, wallets, aztecNode } = t;
let { asset, tokenSim, wallets, aztecNode, pxe } = t;

let alice!: AccountWallet; // On pxe a
let bob!: AccountWallet; // On pxe b

let doubleTroubleA!: AccountWallet; // On both PXE
let doubleTroubleB!: AccountWallet; // On both PXE

let escrowAlice!: SimpleEscrowContract;
let escrowBob!: SimpleEscrowContract;

Expand All @@ -33,7 +37,7 @@ describe('e2e_escrowable_token_contract escrow transfer private', () => {
await t.applyBaseSnapshots();
await t.applyMintSnapshot();
await t.setup();
({ asset, tokenSim, wallets, aztecNode } = t);
({ asset, tokenSim, wallets, aztecNode, pxe } = t);

// We need a fresh PXE service for the second group of wallets
const { pxe: pxeB, teardown: _teardown } = await setupPXEService(aztecNode!, {}, undefined, true);
Expand All @@ -42,6 +46,36 @@ describe('e2e_escrowable_token_contract escrow transfer private', () => {
alice = wallets[0];
bob = (await createAccounts(pxeB, 1))[0];

const secret = Fr.random();

// :skull: This is a pain to deal with.
doubleTroubleA = (await createAccounts(pxe, 1, [secret]))[0];
const acc = doubleTroubleA.getAccount();
doubleTroubleB = new AccountWallet(pxeB, acc);
await pxeB.registerAccount(secret, doubleTroubleB.getCompleteAddress().partialAddress);

// https://i.pinimg.com/originals/e0/a7/1f/e0a71f597967638ffd90698f1fd8aa5a.png
{
{
const instance = await alice.getContractInstance(alice.getAddress());
if (!instance) {
throw new Error('Failed to get contract instance');
}
await pxeB.registerContract({
instance: instance,
});
}
{
const instance = await bob.getContractInstance(bob.getAddress());
if (!instance) {
throw new Error('Failed to get contract instance');
}
await alice.registerContract({
instance: instance,
});
}
}

await alice.registerRecipient(bob.getCompleteAddress());
await bob.registerRecipient(alice.getCompleteAddress());

Expand All @@ -54,6 +88,21 @@ describe('e2e_escrowable_token_contract escrow transfer private', () => {
escrowAlice = await SimpleEscrowContract.deploy(alice, asset.address, alice.getAddress()).send().deployed();
escrowBob = await SimpleEscrowContract.deploy(bob, asset.address, bob.getAddress()).send().deployed();

/*
{
// We cannot actually do these because the `addNote` is broken! 💀
{
const extendedNotes = await alice.getNotes({ contractAddress: alice.getAddress() });
expect(extendedNotes.length).toEqual(1);
await bob.addNote(extendedNotes[0]);
}
{
const extendedNotes = await bob.getNotes({ contractAddress: bob.getAddress() });
expect(extendedNotes.length).toEqual(1);
await alice.addNote(extendedNotes[0]);
}
}*/

// Add to the token
tokenSim.addAccount(escrowAlice.address);
tokenSim.addAccount(escrowBob.address);
Expand All @@ -71,6 +120,69 @@ describe('e2e_escrowable_token_contract escrow transfer private', () => {
await t.tokenSim.check();
});

describe.skip('broken authwit escrow', () => {
/**
* The ability to pass an authwit to someone else such that they can do something on your behalf is BROKEN.
* Unless the actor is yourself, they will not have the keys to nullify or make the proper outgoing
*/

it('transfer on behalf of other', async () => {
// The only difference between this test and the one in the `transfer_private.test.ts` files, are that this is run
// with wallets connected to different PXE services. This is to show that the authwit is not working as expected.
// The reason that this was not encountered earlier is that this slows down the tests, and was not directly considered.
const balance0 = await asset.methods.balance_of_private(alice.getAddress()).simulate();
const amount = balance0 / 2n;
const nonce = Fr.random();
expect(amount).toBeGreaterThan(0n);

// We need to compute the message we want to sign and add it to the wallet as approved
const action = asset
.withWallet(bob)
.methods.transfer(
alice.getAddress(),
bob.getAddress(),
amount,
nonce,
toAddressOption(),
toAddressOption(),
toAddressOption(),
);

const witness = await alice.createAuthWit({ caller: bob.getAddress(), action });

await bob.addAuthWitness(witness);

expect(await alice.lookupValidity(alice.getAddress(), { caller: bob.getAddress(), action })).toEqual({
isValidInPrivate: true,
isValidInPublic: false,
});

expect(await bob.lookupValidity(alice.getAddress(), { caller: bob.getAddress(), action })).toEqual({
isValidInPrivate: true,
isValidInPublic: false,
});

// Perform the transfer
await action.send().wait();
tokenSim.transferPrivate(alice.getAddress(), bob.getAddress(), amount);

// Perform the transfer again, should fail
const txReplay = asset
.withWallet(bob)
.methods.transfer(
alice.getAddress(),
bob.getAddress(),
amount,
nonce,
toAddressOption(),
toAddressOption(),
toAddressOption(),
)
.send();
await expect(txReplay.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR);
});
});

describe('escrowing', () => {
describe('simple escrow', () => {
it('alice donate to alice escrow, `incoming_viewer_and_nullifier != to`', async () => {
Expand Down Expand Up @@ -209,6 +321,54 @@ describe('e2e_escrowable_token_contract escrow transfer private', () => {
.simulate(),
).rejects.toThrow("Assertion failed: Cannot return zero notes 'num_notes != 0'");
}

console.log('LASSE 2');
{
// Alice and Bob is colluding on getting a hold of Bobs funds
// Alice will only help if bob gives her half of the amount!

const toAlice = amount / 2n;
const toBob = amount - toAlice;
const actionBlackmail = asset
.withWallet(alice)
.methods.transfer(
bob.getAddress(),
alice.getAddress(),
toAlice,
0,
toAddressOption(),
toAddressOption(),
toAddressOption(),
)
.request();
console.log('LASSE 3');

const actionNonBlackmail = asset
.withWallet(alice)
.methods.transfer(
bob.getAddress(),
bob.getAddress(),
toBob,
0,
toAddressOption(),
toAddressOption(),
toAddressOption(),
)
.request();

console.log('LASSE 4');
const appPayload = EntrypointPayload.fromAppExecution([actionBlackmail, actionNonBlackmail]);
// Even though Alice is practically sending it, she is not the sender in the fee option notation.
const feePayload = await EntrypointPayload.fromFeeOptions(bob.getAddress());

await alice.addAuthWitness(await bob.createAuthWit(appPayload.hash()));
await alice.addAuthWitness(await bob.createAuthWit(feePayload.hash()));

console.log('LASSE 5');
const bobsAccount = await Contract.at(bob.getAddress(), SchnorrAccountContractArtifact, alice);
console.log('LASSE 6');
await bobsAccount.withWallet(alice).methods['entrypoint'](appPayload, feePayload).send().wait();
}
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ExtendedNote,
Fr,
Note,
PXE,
type TxHash,
createDebugLogger,
} from '@aztec/aztec.js';
Expand Down Expand Up @@ -78,6 +79,7 @@ export class EscrowTokenContractTest {
blacklisted!: AccountWallet;

aztecNode!: AztecNode;
pxe!: PXE;

constructor(testName: string) {
this.logger = createDebugLogger(`aztec:e2e_escrowable_token_contract:${testName}`);
Expand Down Expand Up @@ -124,6 +126,7 @@ export class EscrowTokenContractTest {
this.accounts = await pxe.getRegisteredAccounts();
this.wallets.forEach((w, i) => this.logger.verbose(`Wallet ${i} address: ${w.getAddress()}`));
this.aztecNode = aztecNode;
this.pxe = pxe;
},
);

Expand Down