Skip to content

Commit

Permalink
feat(avm): make authwit work with avm (#5594)
Browse files Browse the repository at this point in the history
  • Loading branch information
fcarreiro authored Apr 9, 2024
1 parent d872445 commit b02d1e1
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 19 deletions.
20 changes: 16 additions & 4 deletions noir-projects/aztec-nr/authwit/src/auth.nr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ use dep::aztec::protocol_types::{
abis::function_selector::FunctionSelector, address::AztecAddress,
constants::{GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER}, hash::pedersen_hash
};
use dep::aztec::{context::{PrivateContext, PublicContext, Context, gas::GasOpts}, hash::hash_args_array};
use dep::aztec::{
context::{
PrivateContext, PublicContext, Context, gas::GasOpts,
interface::{ContextInterface, PublicContextInterface}
},
hash::hash_args_array
};

global IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256("IS_VALID()")

Expand All @@ -18,10 +24,16 @@ pub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf

// docs:start:assert_current_call_valid_authwit_public
// Assert that `on_behalf_of` have authorized the current call in a public context
pub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {
pub fn assert_current_call_valid_authwit_public<TPublicContext>(
context: &mut TPublicContext,
on_behalf_of: AztecAddress
) where TPublicContext: ContextInterface + PublicContextInterface {
let function_selector = FunctionSelector::from_signature("spend_public_authwit(Field)");
let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);
let result = context.call_public_function(
let inner_hash = compute_inner_authwit_hash(
[(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]
);
let result = PublicContextInterface::call_public_function(
context,
on_behalf_of,
function_selector,
[inner_hash],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ contract AvmInitializerTest {
storage.immutable.initialize(42);
}

unconstrained fn view_storage_immutable() -> pub Field {
#[aztec(public-vm)]
fn read_storage_immutable() -> pub Field {
storage.immutable.read()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ type = "contract"

[dependencies]
aztec = { path = "../../../aztec-nr/aztec" }
compressed_string = { path = "../../../aztec-nr/compressed-string" }
compressed_string = { path = "../../../aztec-nr/compressed-string" }
authwit = { path = "../../../aztec-nr/authwit" }
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ contract AvmTest {
use dep::aztec::protocol_types::traits::ToField;
use dep::aztec::protocol_types::constants::RETURN_VALUES_LENGTH;
use dep::compressed_string::CompressedString;
use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}};

// avm lib
use dep::aztec::avm::hash::{keccak256, poseidon, sha256};
Expand Down Expand Up @@ -250,6 +251,14 @@ contract AvmTest {
assert(ci.is_some());
}

/************************************************************************
* Authwit functions
************************************************************************/
#[aztec(public-vm)]
fn test_authwit_send_money(from: AztecAddress, _to: AztecAddress, _amount: Field) {
assert_current_call_valid_authwit_public(&mut context, from);
}

/************************************************************************
* AvmContext functions
************************************************************************/
Expand Down
60 changes: 47 additions & 13 deletions yarn-project/end-to-end/src/e2e_avm_simulator.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { AztecAddress, Fr, FunctionSelector, TxStatus, type Wallet } from '@aztec/aztec.js';
import { type AccountWallet, AztecAddress, Fr, FunctionSelector, TxStatus } from '@aztec/aztec.js';
import { AvmInitializerTestContract, AvmTestContract } from '@aztec/noir-contracts.js';

import { jest } from '@jest/globals';

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

const TIMEOUT = 100_000;

describe('e2e_avm_simulator', () => {
jest.setTimeout(TIMEOUT);

let wallet: Wallet;
let wallet: AccountWallet;
let teardown: () => Promise<void>;

beforeAll(async () => {
({ teardown, wallet } = await setup());
await publicDeployAccounts(wallet, [wallet]);
}, 100_000);

afterAll(() => teardown());
Expand Down Expand Up @@ -91,20 +92,53 @@ describe('e2e_avm_simulator', () => {
.avm_to_acvm_call(FunctionSelector.fromSignature('assert_unsiloed_nullifier_acvm(Field)'), nullifier)
.send()
.wait();
// });
});
});
});

describe('AvmInitializerTestContract', () => {
let avmContract: AvmInitializerTestContract;
describe('Authwit', () => {
it('Works if authwit provided', async () => {
const recipient = AztecAddress.random();
const action = avmContract.methods.test_authwit_send_money(
/*from=*/ wallet.getCompleteAddress(),
recipient,
100,
);
let tx = await wallet
.setPublicAuthWit({ caller: wallet.getCompleteAddress().address, action }, /*authorized=*/ true)
.send()
.wait();
expect(tx.status).toEqual(TxStatus.MINED);

tx = await avmContract.methods
.test_authwit_send_money(/*from=*/ wallet.getCompleteAddress(), recipient, 100)
.send()
.wait();
expect(tx.status).toEqual(TxStatus.MINED);
});

it('Fails if authwit not provided', async () => {
await expect(
async () =>
await avmContract.methods
.test_authwit_send_money(/*from=*/ wallet.getCompleteAddress(), /*to=*/ AztecAddress.random(), 100)
.send()
.wait(),
).rejects.toThrow(/Message not authorized by account/);
});
});

beforeEach(async () => {
avmContract = await AvmInitializerTestContract.deploy(wallet).send().deployed();
}, 50_000);
describe('AvmInitializerTestContract', () => {
let avmContract: AvmInitializerTestContract;

describe('Storage', () => {
it('Read immutable (initialized) storage (Field)', async () => {
expect(await avmContract.methods.view_storage_immutable().simulate()).toEqual(42n);
beforeEach(async () => {
avmContract = await AvmInitializerTestContract.deploy(wallet).send().deployed();
}, 50_000);

describe('Storage', () => {
it('Read immutable (initialized) storage (Field)', async () => {
expect(await avmContract.methods.read_storage_immutable().simulate()).toEqual([42n, 0n, 0n, 0n]);
});
});
});
});
});
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/simulator/src/avm/opcodes/external_calls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ abstract class ExternalCall extends Instruction {
// const nestedContext = context.createNestedContractCallContext(
// callAddress.toFr(),
// calldata,
// allocatedGas,
// this.type,
// FunctionSelector.fromField(functionSelector),
// );
// const nestedCallResults: AvmContractCallResults = await new AvmSimulator(nestedContext).execute();
Expand Down

0 comments on commit b02d1e1

Please sign in to comment.