Skip to content

Commit

Permalink
feat: example of private token transfer event (#7242)
Browse files Browse the repository at this point in the history
A small extension on some of the work @sklppy88 have been doing lately
to satisfy @rahul-kothari and have an example where you end up with your
"transfer history".

The events currently only have neat macros autogenerated for when we are
using a struct of fields only, but works just fine for us here.

---------

Co-authored-by: esau <152162806+sklppy88@users.noreply.github.com>
  • Loading branch information
LHerskind and sklppy88 authored Jun 28, 2024
1 parent 17c8d3a commit 99ce26f
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
context::PrivateContext, event::event_interface::EventInterface,
encrypted_logs::payload::compute_encrypted_event_log, oracle::logs_traits::LensForEncryptedEvent
encrypted_logs::payload::compute_encrypted_event_log, oracle::logs_traits::LensForEncryptedEvent,
oracle::unsafe_rand::unsafe_rand
};
use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};

Expand All @@ -20,6 +21,20 @@ fn emit_with_keys<Event, NB, MB, OB>(
}

pub fn encode_and_encrypt_event<Event, NB, MB, OB>(
context: &mut PrivateContext,
ov: AztecAddress,
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let header = context.get_header();
let ovpk = header.get_ovpk_m(context, ov);
let ivpk = header.get_ivpk_m(context, iv);
let randomness = unsafe_rand();
emit_with_keys(context, randomness, e, ovpk, ivpk);
}
}

pub fn encode_and_encrypt_event_with_randomness<Event, NB, MB, OB>(
context: &mut PrivateContext,
randomness: Field,
ov: AztecAddress,
Expand All @@ -34,6 +49,17 @@ pub fn encode_and_encrypt_event<Event, NB, MB, OB>(
}

pub fn encode_and_encrypt_event_with_keys<Event, NB, MB, OB>(
context: &mut PrivateContext,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint
) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let randomness = unsafe_rand();
emit_with_keys(context, randomness, e, ovpk, ivpk);
}
}

pub fn encode_and_encrypt_event_with_keys_with_randomness<Event, NB, MB, OB>(
context: &mut PrivateContext,
randomness: Field,
ovpk: GrumpkinPoint,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ contract Test {
PrivateContext, PrivateImmutable, PrivateSet, SharedImmutable
};
use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note;
use dep::aztec::encrypted_logs::encrypted_event_emission::encode_and_encrypt_event_with_keys;
use dep::aztec::encrypted_logs::encrypted_event_emission::encode_and_encrypt_event_with_keys_with_randomness;

use dep::aztec::protocol_types::{
abis::private_circuit_public_inputs::PrivateCircuitPublicInputs,
Expand Down Expand Up @@ -271,7 +271,7 @@ contract Test {
let event = ExampleEvent { value0: fields[0], value1: fields[1], value2: fields[2], value3: fields[3], value4: fields[4] };

event.emit(
encode_and_encrypt_event_with_keys(
encode_and_encrypt_event_with_keys_with_randomness(
&mut context,
// testing only - a secret random value is passed in here to salt / mask the address
5,
Expand All @@ -288,7 +288,7 @@ contract Test {
let otherEvent = ExampleEvent { value0: 1, value1: 2, value2: 3, value3: 4, value4: 5 };

otherEvent.emit(
encode_and_encrypt_event_with_keys(
encode_and_encrypt_event_with_keys_with_randomness(
&mut context,
// testing only - a randomness of 0 signals the kerels to not mask the address
0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ contract TestLog {
use dep::value_note::value_note::ValueNote;
use dep::aztec::encrypted_logs::incoming_body::EncryptedLogIncomingBody;
use dep::aztec::event::event_interface::EventInterface;
use dep::aztec::encrypted_logs::encrypted_event_emission::{encode_and_encrypt_event, encode_and_encrypt_event_with_keys};
use dep::aztec::encrypted_logs::encrypted_event_emission::encode_and_encrypt_event_with_randomness;
use dep::aztec::unencrypted_logs::unencrypted_event_emission::encode_event;

#[aztec(event)]
Expand Down Expand Up @@ -49,7 +49,7 @@ contract TestLog {
let event0 = ExampleEvent0 { value0: preimages[0], value1: preimages[1] };

event0.emit(
encode_and_encrypt_event(
encode_and_encrypt_event_with_randomness(
&mut context,
randomness[0],
// outgoing is set to other, incoming is set to msg sender
Expand All @@ -72,7 +72,7 @@ contract TestLog {
let event1 = ExampleEvent1 { value2: preimages[2], value3: preimages[3] };

event1.emit(
encode_and_encrypt_event(
encode_and_encrypt_event_with_randomness(
&mut context,
randomness[1],
// outgoing is set to other, incoming is set to msg sender
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ contract Token {
use dep::aztec::{
hash::compute_secret_hash,
prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress},
encrypted_logs::encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys}
encrypted_logs::{
encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys},
encrypted_event_emission::{encode_and_encrypt_event, encode_and_encrypt_event_with_keys}
}
};

// docs:start:import_authwit
Expand All @@ -28,6 +31,13 @@ contract Token {
use crate::types::{transparent_note::TransparentNote, token_note::{TokenNote, TOKEN_NOTE_LEN}, balances_map::BalancesMap};
// docs:end::imports

#[aztec(event)]
struct Transfer {
from: Field,
to: Field,
amount: Field,
}

// docs:start:storage_struct
#[aztec(storage)]
struct Storage {
Expand Down Expand Up @@ -324,6 +334,8 @@ contract Token {
let amount = U128::from_integer(amount);
storage.balances.sub(from, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, from_ivpk));
storage.balances.add(to, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, to_ivpk));

Transfer { from: from.to_field(), to: to.to_field(), amount: amount.to_field() }.emit(encode_and_encrypt_event_with_keys(&mut context, from_ovpk, to_ivpk));
}
// docs:end:transfer

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {
AztecAddress,
CompleteAddress,
EventType,
Fr,
computeAuthWitMessageHash,
computeInnerAuthWitHashFromAction,
} from '@aztec/aztec.js';
import { TokenContract } from '@aztec/noir-contracts.js';

import { DUPLICATE_NULLIFIER_ERROR } from '../fixtures/fixtures.js';
import { TokenContractTest } from './token_contract_test.js';
Expand Down Expand Up @@ -32,8 +34,16 @@ describe('e2e_token_contract transfer private', () => {
const balance0 = await asset.methods.balance_of_private(accounts[0].address).simulate();
const amount = balance0 / 2n;
expect(amount).toBeGreaterThan(0n);
await asset.methods.transfer(accounts[1].address, amount).send().wait();
const tx = await asset.methods.transfer(accounts[1].address, amount).send().wait();
tokenSim.transferPrivate(accounts[0].address, accounts[1].address, amount);

const events = await wallets[1].getEvents(EventType.Encrypted, TokenContract.events.Transfer, tx.blockNumber!, 1);

expect(events[0]).toEqual({
from: accounts[0].address,
to: accounts[1].address,
amount: new Fr(amount),
});
});

it('transfer less than balance to non-deployed account', async () => {
Expand Down

0 comments on commit 99ce26f

Please sign in to comment.