Skip to content

Commit

Permalink
feat: nuking Pokeable contract (#2939)
Browse files Browse the repository at this point in the history
Fixes #2938 
+ fixed the camel case naming in the `Test` contract
  • Loading branch information
benesjan authored Oct 20, 2023
1 parent 78f9f52 commit 583d6fb
Show file tree
Hide file tree
Showing 15 changed files with 77 additions and 226 deletions.
7 changes: 6 additions & 1 deletion docs/docs/concepts/foundation/accounts/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,12 @@ A side-effect of not having nonces at the protocol level is that it is not possi

Since the `entrypoint` interface is not enshrined, there is nothing that differentiates an account contract from an application one in the protocol. This means that a transaction can be initiated in any contract. This allows implementing functions that do not need to be called by any particular user and are just intended to advance the state of a contract.

As an example, we can think of a lottery contract, where at some point a prize needs to be paid out to its winners. This `pay` action does not require authentication and does not need to be executed by any user in particular, so anyone could submit a transaction that defines the lottery contract itself as `origin` and `pay` as entrypoint function. For an example implementation of a different use case, refer to the [`pokeable_token_contract`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/noir-contracts/src/contracts/pokeable_token_contract/src/main.nr) in the repository.
As an example, we can think of a lottery contract, where at some point a prize needs to be paid out to its winners. This `pay` action does not require authentication and does not need to be executed by any user in particular, so anyone could submit a transaction that defines the lottery contract itself as `origin` and `pay` as entrypoint function. For an example of this behavior see our [non_contract_account test](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts) and the [SignerLess wallet](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec.js/src/wallet/signerless_wallet.ts) implementation.
Notice that the Signerless wallet doesn't invoke an entrypoint function of an account contract but instead invokes the target contract function directly.

:::info
In case no contract entrypoint is used `msg_sender` is set to 0.
:::

### Account initialization

Expand Down
10 changes: 5 additions & 5 deletions yarn-project/acir-simulator/src/client/private_execution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ describe('Private Execution test suite', () => {
const dummyNote = { amount: 1, secretHash: 2 };
const deepStruct = { aField: 1, aBool: true, aNote: dummyNote, manyNotes: [dummyNote, dummyNote, dummyNote] };
args = [1, true, 1, [1, 2], dummyNote, deepStruct];
testCodeGenArtifact = TestContractArtifact.functions.find(f => f.name === 'testCodeGen')!;
testCodeGenArtifact = TestContractArtifact.functions.find(f => f.name === 'test_code_gen')!;
const serializedArgs = encodeArguments(testCodeGenArtifact, args);
argsHash = await computeVarArgsHash(await CircuitsWasm.get(), serializedArgs);
});
Expand Down Expand Up @@ -786,7 +786,7 @@ describe('Private Execution test suite', () => {
describe('get public key', () => {
it('gets the public key for an address', async () => {
// Tweak the contract artifact so we can extract return values
const artifact = getFunctionArtifact(TestContractArtifact, 'getPublicKey');
const artifact = getFunctionArtifact(TestContractArtifact, 'get_public_key');
artifact.returnTypes = [{ kind: 'array', length: 2, type: { kind: 'field' } }];

// Generate a partial address, pubkey, and resulting address
Expand All @@ -806,7 +806,7 @@ describe('Private Execution test suite', () => {
const aztecAddressToQuery = AztecAddress.random();

// Tweak the contract artifact so we can extract return values
const artifact = getFunctionArtifact(TestContractArtifact, 'getPortalContractAddress');
const artifact = getFunctionArtifact(TestContractArtifact, 'get_portal_contract_address');
artifact.returnTypes = [{ kind: 'field' }];

const args = [aztecAddressToQuery.toField()];
Expand All @@ -821,7 +821,7 @@ describe('Private Execution test suite', () => {
const contractAddress = AztecAddress.random();

// Tweak the contract artifact so we can extract return values
const artifact = getFunctionArtifact(TestContractArtifact, 'getThisAddress');
const artifact = getFunctionArtifact(TestContractArtifact, 'get_this_address');
artifact.returnTypes = [{ kind: 'field' }];

// Overwrite the oracle return value
Expand All @@ -833,7 +833,7 @@ describe('Private Execution test suite', () => {
const portalContractAddress = EthAddress.random();

// Tweak the contract artifact so we can extract return values
const artifact = getFunctionArtifact(TestContractArtifact, 'getThisPortalAddress');
const artifact = getFunctionArtifact(TestContractArtifact, 'get_this_portal_address');
artifact.returnTypes = [{ kind: 'field' }];

// Overwrite the oracle return value
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/acir-simulator/src/public/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ describe('ACIR public execution simulator', () => {

it('Should be able to create a L2 to L1 message from the public context', async () => {
const createL2ToL1MessagePublicArtifact = TestContractArtifact.functions.find(
f => f.name === 'createL2ToL1MessagePublic',
f => f.name === 'create_l2_to_l1_message_public',
)!;
const args = encodeArguments(createL2ToL1MessagePublicArtifact, params);

Expand Down Expand Up @@ -429,7 +429,7 @@ describe('ACIR public execution simulator', () => {

it('Should be able to create a nullifier from the public context', async () => {
const createNullifierPublicArtifact = TestContractArtifact.functions.find(
f => f.name === 'createNullifierPublic',
f => f.name === 'create_nullifier_public',
)!;

const args = encodeArguments(createNullifierPublicArtifact, params);
Expand Down
1 change: 0 additions & 1 deletion yarn-project/end-to-end/src/cli_docs_sandbox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ ImportTestContractArtifact
LendingContractArtifact
ParentContractArtifact
PendingCommitmentsContractArtifact
PokeableTokenContractArtifact
PriceFeedContractArtifact
SchnorrAccountContractArtifact
SchnorrHardcodedAccountContractArtifact
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/end-to-end/src/e2e_block_building.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ describe('e2e_block_building', () => {

it('drops tx with public nullifier already emitted on the same block', async () => {
const secret = Fr.random();
const calls = times(2, () => contract.methods.createNullifierPublic(140n, secret));
const calls = times(2, () => contract.methods.create_nullifier_public(140n, secret));
for (const call of calls) await call.simulate();
const [tx1, tx2] = calls.map(call => call.send());
await tx1.wait();
Expand All @@ -141,7 +141,7 @@ describe('e2e_block_building', () => {
);

const calls = [
contract.methods.createNullifierPublic(140n, secret),
contract.methods.create_nullifier_public(140n, secret),
contract.methods.emit_nullifier(emittedPublicNullifier),
];

Expand Down
4 changes: 2 additions & 2 deletions yarn-project/end-to-end/src/e2e_cheat_codes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,13 @@ describe('e2e_cheat_codes', () => {
expect(Number(await rollup.read.lastBlockTs())).toEqual(newTimestamp);
expect(Number(await rollup.read.lastWarpedBlockTs())).toEqual(newTimestamp);

const txIsTimeEqual = contract.methods.isTimeEqual(newTimestamp).send();
const txIsTimeEqual = contract.methods.is_time_equal(newTimestamp).send();
const isTimeEqualReceipt = await txIsTimeEqual.wait({ interval: 0.1 });
expect(isTimeEqualReceipt.status).toBe(TxStatus.MINED);

// Since last rollup block was warped, txs for this rollup will have time incremented by 1
// See https://github.com/AztecProtocol/aztec-packages/issues/1614 for details
const txTimeNotEqual = contract.methods.isTimeEqual(newTimestamp + 1).send();
const txTimeNotEqual = contract.methods.is_time_equal(newTimestamp + 1).send();
const isTimeNotEqualReceipt = await txTimeNotEqual.wait({ interval: 0.1 });
expect(isTimeNotEqualReceipt.status).toBe(TxStatus.MINED);
// block is published at t >= newTimestamp + 1.
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/end-to-end/src/e2e_deploy_contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ describe('e2e_deploy_contract', () => {

const contract = await Contract.at(receipt.contractAddress!, TestContractArtifact, wallet);
logger(`Sending TX to contract ${index + 1}...`);
await contract.methods.getPublicKey(accounts[0].address).send().wait();
await contract.methods.get_public_key(accounts[0].address).send().wait();
}
}, 30_000);

Expand Down
59 changes: 21 additions & 38 deletions yarn-project/end-to-end/src/e2e_non_contract_account.test.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,46 @@
import { AztecAddress, SignerlessWallet, Wallet } from '@aztec/aztec.js';
import { SignerlessWallet, Wallet } from '@aztec/aztec.js';
import { CircuitsWasm, Fr } from '@aztec/circuits.js';
import { siloNullifier } from '@aztec/circuits.js/abis';
import { DebugLogger } from '@aztec/foundation/log';
import { PokeableTokenContract } from '@aztec/noir-contracts/types';
import { AztecNode, CompleteAddress, PXE, TxStatus } from '@aztec/types';
import { TestContract } from '@aztec/noir-contracts/types';
import { AztecNode, PXE, TxStatus } from '@aztec/types';

import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup } from './fixtures/utils.js';
import { setup } from './fixtures/utils.js';

describe('e2e_non_contract_account', () => {
let aztecNode: AztecNode | undefined;
let pxe: PXE;
let wallet: Wallet;
let sender: AztecAddress;
let recipient: AztecAddress;
let pokerWallet: Wallet;
let nonContractAccountWallet: Wallet;
let teardown: () => Promise<void>;

let logger: DebugLogger;

let contract: PokeableTokenContract;

const initialBalance = 987n;
let contract: TestContract;

beforeEach(async () => {
let accounts: CompleteAddress[];
({ teardown, aztecNode, pxe, accounts, wallet, logger } = await setup(2));
sender = accounts[0].address;
recipient = accounts[1].address;
pokerWallet = new SignerlessWallet(pxe);
let wallet: Wallet;
({ teardown, aztecNode, pxe, wallet, logger } = await setup(1));
nonContractAccountWallet = new SignerlessWallet(pxe);

logger(`Deploying L2 contract...`);
const tx = PokeableTokenContract.deploy(pxe, initialBalance, sender, recipient).send();
await tx.isMined({ interval: 0.1 });
const receipt = await tx.getReceipt();
expect(receipt.status).toEqual(TxStatus.MINED);
contract = await TestContract.deploy(wallet).send().deployed();
logger('L2 contract deployed');
contract = await PokeableTokenContract.at(receipt.contractAddress!, wallet);
}, 100_000);

afterEach(() => teardown());

const expectBalance = async (owner: AztecAddress, expectedBalance: bigint) => {
const balance = await contract.methods.getBalance(owner).view({ from: owner });
logger(`Account ${owner} balance: ${balance}`);
expect(balance).toBe(expectedBalance);
};

it('Arbitrary non-contract account can call a private function on a contract', async () => {
await expectBalance(sender, initialBalance);
await expectBalance(recipient, 0n);
await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 1);

const contractWithNoContractWallet = await PokeableTokenContract.at(contract.address, pokerWallet);
const contractWithNoContractWallet = await TestContract.at(contract.address, nonContractAccountWallet);

// Send transaction as poker (arbitrary non-contract account)
await contractWithNoContractWallet.methods.poke(sender, recipient).send().wait({ interval: 0.1 });
// Send transaction as arbitrary non-contract account
const nullifier = new Fr(940);
const receipt = await contractWithNoContractWallet.methods.emit_nullifier(nullifier).send().wait({ interval: 0.1 });
expect(receipt.status).toBe(TxStatus.MINED);

// Initial balance should be fully transferred to the recipient
await expectBalance(sender, 0n);
await expectBalance(recipient, initialBalance);
const tx = await aztecNode!.getTx(receipt.txHash);
const expectedSiloedNullifier = siloNullifier(await CircuitsWasm.get(), contract.address, nullifier);
const siloedNullifier = tx!.newNullifiers[1];

await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 1);
expect(siloedNullifier.equals(expectedSiloedNullifier)).toBeTruthy();
}, 120_000);
});
2 changes: 1 addition & 1 deletion yarn-project/end-to-end/src/guides/dapp_testing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ describe('guides/dapp/testing', () => {
// docs:start:warp
const newTimestamp = Math.floor(Date.now() / 1000) + 60 * 60 * 24;
await cheats.aztec.warp(newTimestamp);
await testContract.methods.isTimeEqual(newTimestamp).send().wait();
await testContract.methods.is_time_equal(newTimestamp).send().wait();
// docs:end:warp
});
});
Expand Down
1 change: 0 additions & 1 deletion yarn-project/noir-contracts/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ members = [
"src/contracts/lending_contract",
"src/contracts/parent_contract",
"src/contracts/pending_commitments_contract",
"src/contracts/pokeable_token_contract",
"src/contracts/price_feed_contract",
"src/contracts/schnorr_account_contract",
"src/contracts/schnorr_hardcoded_account_contract",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ contract ImportTest {
target: Field
) -> Field {
let test_contract_instance = TestPrivateContextInterface::at(target);
let return_values = test_contract_instance.testCodeGen(
let return_values = test_contract_instance.test_code_gen(
&mut context,
1,
true,
Expand Down Expand Up @@ -56,7 +56,7 @@ contract ImportTest {
target: Field
) -> Field {
let test_contract_instance = TestPrivateContextInterface::at(target);
let return_values = test_contract_instance.getThisAddress(&mut context);
let return_values = test_contract_instance.get_this_address(&mut context);

return_values[0]
}
Expand All @@ -69,7 +69,7 @@ contract ImportTest {
target: Field,
) {
let test_contract_instance = TestPrivateContextInterface::at(target);
test_contract_instance.createNullifierPublic(&mut context, 1, 2);
test_contract_instance.create_nullifier_public(&mut context, 1, 2);
}

// Calls the createNullifierPublic on the Test contract at the target address
Expand All @@ -80,7 +80,7 @@ contract ImportTest {
target: Field,
) -> Field {
let test_contract_instance = TestPublicContextInterface::at(target);
let ret = test_contract_instance.createNullifierPublic(context, 1, 2);
let ret = test_contract_instance.create_nullifier_public(context, 1, 2);

ret[0]
}
Expand Down

This file was deleted.

Loading

0 comments on commit 583d6fb

Please sign in to comment.