Skip to content

Commit

Permalink
feat: meaningful outgoing (#6560)
Browse files Browse the repository at this point in the history
Fixes #6410
  • Loading branch information
benesjan authored May 29, 2024
1 parent ded4e22 commit 3f93757
Show file tree
Hide file tree
Showing 83 changed files with 838 additions and 394 deletions.
20 changes: 16 additions & 4 deletions boxes/boxes/react/src/contracts/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,29 @@ contract BoxReact {

#[aztec(private)]
#[aztec(initializer)]
fn constructor(number: Field, owner: AztecAddress, owner_npk_m_hash: Field, owner_ivpk_m: GrumpkinPoint) {
fn constructor(
number: Field,
owner: AztecAddress,
owner_npk_m_hash: Field,
owner_ovpk_m: GrumpkinPoint,
owner_ivpk_m: GrumpkinPoint
) {
let numbers = storage.numbers;
let mut new_number = ValueNote::new(number, owner_npk_m_hash);
numbers.at(owner).initialize(&mut new_number, true, owner_ivpk_m);
numbers.at(owner).initialize(&mut new_number, true, owner_ovpk_m, owner_ivpk_m);
}

#[aztec(private)]
fn setNumber(number: Field, owner: AztecAddress, owner_npk_m_hash: Field, owner_ivpk_m: GrumpkinPoint) {
fn setNumber(
number: Field,
owner: AztecAddress,
owner_npk_m_hash: Field,
owner_ovpk_m: GrumpkinPoint,
owner_ivpk_m: GrumpkinPoint
) {
let numbers = storage.numbers;
let mut new_number = ValueNote::new(number, owner_npk_m_hash);
numbers.at(owner).replace(&mut new_number, true, owner_ivpk_m);
numbers.at(owner).replace(&mut new_number, true, owner_ovpk_m, owner_ivpk_m);
}

unconstrained fn getNumber(owner: AztecAddress) -> pub ValueNote {
Expand Down
11 changes: 10 additions & 1 deletion boxes/boxes/react/src/hooks/useContract.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ export function useContract() {
setWait(true);
const wallet = await deployerEnv.getWallet();
const salt = Fr.random();
const tx = await BoxReactContract.deploy(wallet, Fr.random(), wallet.getCompleteAddress().address, wallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(), wallet.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey).send({
const { masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey } =
wallet.getCompleteAddress().publicKeys;
const tx = await BoxReactContract.deploy(
wallet,
Fr.random(),
wallet.getCompleteAddress().address,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey,
masterIncomingViewingPublicKey,
).send({
contractAddressSalt: salt,
});
const contract = await toast.promise(tx.deployed(), {
Expand Down
24 changes: 19 additions & 5 deletions boxes/boxes/react/src/hooks/useNumber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,25 @@ export function useNumber({ contract }: { contract: Contract }) {

const value = BigInt(el.value);
const deployerWallet = await deployerEnv.getWallet();
await toast.promise(contract!.methods.setNumber(value, deployerWallet.getCompleteAddress().address, deployerWallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(), deployerWallet.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey).send().wait(), {
pending: 'Setting number...',
success: `Number set to: ${value}`,
error: 'Error setting number',
});
const { masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey } =
deployerWallet.getCompleteAddress().publicKeys;
await toast.promise(
contract!.methods
.setNumber(
value,
deployerWallet.getCompleteAddress().address,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey,
masterIncomingViewingPublicKey,
)
.send()
.wait(),
{
pending: 'Setting number...',
success: `Number set to: ${value}`,
error: 'Error setting number',
},
);
setWait(false);
}
};
Expand Down
30 changes: 26 additions & 4 deletions boxes/boxes/react/tests/node.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AccountWallet, CompleteAddress, Contract, Fr, createDebugLogger } from '@aztec/aztec.js';
import { BoxReactContract } from '../artifacts/BoxReact.js';
import { AccountWallet, Fr, Contract, TxStatus, createDebugLogger, ContractDeployer } from '@aztec/aztec.js';
import { deployerEnv } from '../src/config.js';

const logger = createDebugLogger('aztec:http-pxe-client');
Expand All @@ -8,11 +8,22 @@ describe('BoxReact Contract Tests', () => {
let wallet: AccountWallet;
let contract: Contract;
const numberToSet = Fr.random();
let accountCompleteAddress: CompleteAddress;

beforeAll(async () => {
wallet = await deployerEnv.getWallet();
accountCompleteAddress = wallet.getCompleteAddress();
const salt = Fr.random();
contract = await BoxReactContract.deploy(wallet, Fr.random(), wallet.getCompleteAddress().address, wallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(), wallet.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey)
const { masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey } =
accountCompleteAddress.publicKeys;
contract = await BoxReactContract.deploy(
wallet,
Fr.random(),
accountCompleteAddress.address,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey,
masterIncomingViewingPublicKey,
)
.send({ contractAddressSalt: salt })
.deployed();

Expand All @@ -21,11 +32,22 @@ describe('BoxReact Contract Tests', () => {

test('Can set a number', async () => {
logger.info(`${await wallet.getRegisteredAccounts()}`);
await contract.methods.setNumber(numberToSet, wallet.getCompleteAddress().address, wallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(), wallet.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey).send().wait();
const { masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey } =
accountCompleteAddress.publicKeys;
await contract.methods
.setNumber(
numberToSet,
accountCompleteAddress.address,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey,
masterIncomingViewingPublicKey,
)
.send()
.wait();
}, 40000);

test('Can read a number', async () => {
const viewTxReceipt = await contract.methods.getNumber(wallet.getCompleteAddress().address).simulate();
const viewTxReceipt = await contract.methods.getNumber(accountCompleteAddress.address).simulate();
expect(numberToSet.toBigInt()).toEqual(viewTxReceipt.value);
}, 40000);
});
8 changes: 4 additions & 4 deletions boxes/boxes/vanilla/src/contracts/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ contract Vanilla {

#[aztec(private)]
#[aztec(initializer)]
fn constructor(number: Field, owner: AztecAddress, owner_npk_m_hash: Field, owner_ivpk_m: GrumpkinPoint) {
fn constructor(number: Field, owner: AztecAddress, owner_npk_m_hash: Field, owner_ovpk_m: GrumpkinPoint, owner_ivpk_m: GrumpkinPoint) {
let numbers = storage.numbers;
let mut new_number = ValueNote::new(number, owner_npk_m_hash);
numbers.at(owner).initialize(&mut new_number, true, owner_ivpk_m);
numbers.at(owner).initialize(&mut new_number, true, owner_ovpk_m, owner_ivpk_m);
}

#[aztec(private)]
fn setNumber(number: Field, owner: AztecAddress, owner_npk_m_hash: Field, owner_ivpk_m: GrumpkinPoint) {
fn setNumber(number: Field, owner: AztecAddress, owner_npk_m_hash: Field, owner_ovpk_m: GrumpkinPoint, owner_ivpk_m: GrumpkinPoint) {
let numbers = storage.numbers;
let mut new_number = ValueNote::new(number, owner_npk_m_hash);
numbers.at(owner).replace(&mut new_number, true, owner_ivpk_m);
numbers.at(owner).replace(&mut new_number, true, owner_ovpk_m, owner_ivpk_m);
}

unconstrained fn getNumber(owner: AztecAddress) -> pub ValueNote {
Expand Down
23 changes: 21 additions & 2 deletions boxes/boxes/vanilla/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,16 @@ const setWait = (state: boolean): void =>
document.querySelector('#deploy').addEventListener('click', async ({ target }: any) => {
setWait(true);
wallet = await account.register();
contract = await VanillaContract.deploy(wallet, Fr.random(), wallet.getCompleteAddress().address, wallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(), wallet.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey)
const { masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey } =
wallet.getCompleteAddress().publicKeys;
contract = await VanillaContract.deploy(
wallet,
Fr.random(),
wallet.getCompleteAddress().address,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey,
masterIncomingViewingPublicKey,
)
.send({ contractAddressSalt: Fr.random() })
.deployed();
alert(`Contract deployed at ${contract.address}`);
Expand All @@ -36,7 +45,17 @@ document.querySelector('#set').addEventListener('submit', async (e: Event) => {

const { value } = document.querySelector('#number') as HTMLInputElement;
const { address: owner, publicKeys } = wallet.getCompleteAddress();
await contract.methods.setNumber(parseInt(value), owner, publicKeys.masterNullifierPublicKey.hash(), publicKeys.masterIncomingViewingPublicKey).send().wait();
const { masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey } = publicKeys;
await contract.methods
.setNumber(
parseInt(value),
owner,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey,
masterIncomingViewingPublicKey,
)
.send()
.wait();

setWait(false);
alert('Number set!');
Expand Down
3 changes: 2 additions & 1 deletion noir-projects/aztec-nr/address-note/src/address_note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ impl NoteInterface<ADDRESS_NOTE_LEN, ADDRESS_NOTE_BYTES_LEN> for AddressNote {
}

// Broadcasts the note as an encrypted log on L1.
fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) {
fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) {
// docs:start:encrypted
context.encrypt_and_emit_note(
(*context).this_address(),
slot,
Self::get_note_type_id(),
ovpk_m,
ivpk_m,
self,
);
Expand Down
28 changes: 26 additions & 2 deletions noir-projects/aztec-nr/aztec/src/context/private_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -310,12 +310,23 @@ impl PrivateContext {
contract_address: AztecAddress,
randomness: Field, // Secret random value used later for masked_contract_address
event_type_id: Field,
ovpk_m: GrumpkinPoint,
ivpk_m: GrumpkinPoint,
preimage: [Field; N]
) where [Field; N]: LensForEncryptedLog<N, M> {
let ovsk_app = self.request_ovsk_app(ovpk_m.hash());

// We are currently just encrypting it EXACTLY the same way as if it was a note.
let counter = self.next_counter();
let encrypted_log: [u8; M] = compute_encrypted_log(contract_address, randomness, event_type_id, ivpk_m, preimage);
let encrypted_log: [u8; M] = compute_encrypted_log(
contract_address,
randomness,
event_type_id,
ovsk_app,
ovpk_m,
ivpk_m,
preimage
);
emit_encrypted_log(contract_address, randomness, encrypted_log, counter);
let len = 32 + 32 + 64 + 48 + 48 + 176 + 64 + (preimage.len() as Field * 32) + 16 + 4;
let log_hash = sha256_to_field(encrypted_log);
Expand All @@ -328,6 +339,7 @@ impl PrivateContext {
contract_address: AztecAddress,
storage_slot: Field,
note_type_id: Field,
ovpk_m: GrumpkinPoint,
ivpk_m: GrumpkinPoint,
note: Note
) where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
Expand All @@ -343,8 +355,18 @@ impl PrivateContext {
let preimage = note.serialize_content();
let counter = self.next_counter();

let ovsk_app = self.request_ovsk_app(ovpk_m.hash());

// TODO(#1139 | #6408): perform encryption in the circuit
let encrypted_log: [u8; M] = compute_encrypted_log(contract_address, storage_slot, note_type_id, ivpk_m, preimage);
let encrypted_log: [u8; M] = compute_encrypted_log(
contract_address,
storage_slot,
note_type_id,
ovsk_app,
ovpk_m,
ivpk_m,
preimage
);
emit_encrypted_note_log(note_hash, encrypted_log, counter);

// Current unoptimized size of the encrypted log
Expand Down Expand Up @@ -696,6 +718,7 @@ impl Empty for PrivateContext {
}
}

// TODO(#6640)): This should be in its own file
struct PackedReturns {
packed_returns: Field,
}
Expand Down Expand Up @@ -725,6 +748,7 @@ impl PackedReturns {
}
}

// TODO(#6640)): This should not be here but in oracle folder
#[oracle(emitUnencryptedLog)]
fn emit_unencrypted_log_oracle_private<T>(
_contract_address: AztecAddress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ mod test {

fn compute_nullifier_without_context(self) -> Field {1}

fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) {}
fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) {}

fn serialize_content(self) -> [Field; ADDRESS_NOTE_LEN] { [self.address.to_field(), self.owner.to_field(), self.randomness]}

Expand Down
31 changes: 16 additions & 15 deletions noir-projects/aztec-nr/aztec/src/keys/getters.nr
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,42 @@ use dep::protocol_types::{
use crate::{
context::PrivateContext,
oracle::{keys::get_public_keys_and_partial_address, key_validation_request::get_key_validation_request},
keys::{public_keys::PublicKeys, constants::{NULLIFIER_INDEX, INCOMING_INDEX}},
keys::{public_keys::PublicKeys, constants::{NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX}},
state_vars::{shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter}
};

global DELAY = 5;

// docs:start:key-getters
trait KeyGetters {
fn get_ivpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;
fn get_npk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;
fn get_ivpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;
fn get_ovpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;
// fn get_tpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;
fn get_npk_m_hash(header: Header, context: &mut PrivateContext, address: AztecAddress) -> Field;
}

impl KeyGetters for Header {
fn get_npk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {
get_master_key(context, address, NULLIFIER_INDEX, self)
}

fn get_ivpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {
get_master_key(context, address, INCOMING_INDEX, self)
}

fn get_npk_m_hash(self, context: &mut PrivateContext, address: AztecAddress) -> Field {
get_master_key(context, address, NULLIFIER_INDEX, self).hash()
fn get_ovpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {
get_master_key(context, address, OUTGOING_INDEX, self)
}

fn get_npk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {
get_master_key(context, address, NULLIFIER_INDEX, self)
// fn get_tpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {
// get_master_key(context, address, TAGGING_INDEX, self)
// }

fn get_npk_m_hash(self, context: &mut PrivateContext, address: AztecAddress) -> Field {
get_master_key(context, address, NULLIFIER_INDEX, self).hash()
}
}

// Commented out as it's currently not enabled in key registry
// pub fn get_ovpk_m(context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {
// get_master_key(context, address, OUTGOING_INDEX)
// }
//
// pub fn get_tpk_m(context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {
// get_master_key(context, address, TAGGING_INDEX)
// }
// docs:end:key-getters

fn get_master_key(
Expand Down
3 changes: 2 additions & 1 deletion noir-projects/aztec-nr/aztec/src/note/lifecycle.nr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub fn create_note<Note, N, M>(
storage_slot: Field,
note: &mut Note,
broadcast: bool,
ovpk_m: GrumpkinPoint,
ivpk_m: GrumpkinPoint
) where Note: NoteInterface<N, M> {
let contract_address = (*context).this_address();
Expand Down Expand Up @@ -38,7 +39,7 @@ pub fn create_note<Note, N, M>(
context.push_new_note_hash(inner_note_hash);

if broadcast {
Note::broadcast(*note, context, storage_slot, ivpk_m);
Note::broadcast(*note, context, storage_slot, ovpk_m, ivpk_m);
}
}

Expand Down
2 changes: 1 addition & 1 deletion noir-projects/aztec-nr/aztec/src/note/note_interface.nr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ trait NoteInterface<N, M> {

fn compute_nullifier_without_context(self) -> Field;

fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) -> ();
fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) -> ();

// Autogenerated by the #[aztec(note)] macro unless it is overridden by a custom implementation
fn serialize_content(self) -> [Field; N];
Expand Down
Loading

0 comments on commit 3f93757

Please sign in to comment.