Skip to content

Instantly share code, notes, and snippets.

@asterite
Last active March 11, 2025 14:57
Show Gist options
  • Save asterite/0821b58e82e1a7adbdfce14fcecaeef5 to your computer and use it in GitHub Desktop.
Save asterite/0821b58e82e1a7adbdfce14fcecaeef5 to your computer and use it in GitHub Desktop.
ecdsa_k_account_contract after macro expansion
use aztec::macros::aztec;
pub contract EcdsaKAccount {
use authwit::{
account::AccountActions,
auth_witness::get_auth_witness,
entrypoint::{app::AppPayload, fee::FeePayload},
};
use aztec::{
context::private_context::PrivateContext,
encrypted_logs::log_assembly_strategies::default_aes128::note::encode_and_encrypt_note,
macros::{functions::{initializer, noinitcheck, private, view}, storage::storage},
state_vars::private_immutable::PrivateImmutable,
};
use ecdsa_public_key_note::EcdsaPublicKeyNote;
struct Storage<Context> {
public_key: PrivateImmutable<EcdsaPublicKeyNote, Context>,
}
impl<Context> Storage<Context> {
fn init(context: Context) -> Storage<Context> {
Storage::<Context> { public_key: PrivateImmutable::new(context, 1) }
}
}
fn constructor(
inputs: aztec::context::inputs::private_context_inputs::PrivateContextInputs,
signing_pub_key_x: [u8; 32],
signing_pub_key_y: [u8; 32],
) -> return_data protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs {
{
let mut args_hasher: aztec::hash::ArgsHasher = aztec::hash::ArgsHasher::new();
let signing_pub_key_x_serialized: [[Field; 1]; 32] =
signing_pub_key_x.map(|x: u8| -> [Field; 1] x.serialize());
for i in 0..signing_pub_key_x.len() {
args_hasher.add_multiple(signing_pub_key_x_serialized[i]);
}
let signing_pub_key_y_serialized: [[Field; 1]; 32] =
signing_pub_key_y.map(|x: u8| -> [Field; 1] x.serialize());
for i in 0..signing_pub_key_y.len() {
args_hasher.add_multiple(signing_pub_key_y_serialized[i]);
}
let mut context: PrivateContext = PrivateContext::new(inputs, args_hasher.hash());
aztec::macros::functions::initialization_utils::assert_initialization_matches_address_preimage_private(
context,
);
let storage: Storage<&mut PrivateContext> = Storage::init(&mut context);
/* Safety: comment added by `nargo expand` */
unsafe {
aztec::discovery::discover_new_notes(
context.this_address(),
_compute_note_hash_and_nullifier,
)
};
let this: protocol_types::address::aztec_address::AztecAddress = context.this_address();
let pub_key_note: EcdsaPublicKeyNote =
EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this);
storage.public_key.initialize(pub_key_note).emit(encode_and_encrypt_note(
&mut context,
this,
this,
));
aztec::macros::functions::initialization_utils::mark_as_initialized_private(
&mut context,
);
context.finish()
}
}
fn entrypoint(
inputs: aztec::context::inputs::private_context_inputs::PrivateContextInputs,
app_payload: AppPayload,
fee_payload: FeePayload,
cancellable: bool,
) -> return_data protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs {
{
let mut args_hasher: aztec::hash::ArgsHasher = aztec::hash::ArgsHasher::new();
args_hasher.add_multiple(app_payload.serialize());
args_hasher.add_multiple(fee_payload.serialize());
args_hasher.add(cancellable as Field);
let mut context: PrivateContext = PrivateContext::new(inputs, args_hasher.hash());
aztec::macros::functions::initialization_utils::assert_is_initialized_private(
&mut context,
);
let storage: Storage<&mut PrivateContext> = Storage::init(&mut context);
/* Safety: comment added by `nargo expand` */
unsafe {
aztec::discovery::discover_new_notes(
context.this_address(),
_compute_note_hash_and_nullifier,
)
};
let actions: AccountActions<&mut PrivateContext> =
AccountActions::init(&mut context, is_valid_impl);
actions.entrypoint(app_payload, fee_payload, cancellable);
context.finish()
}
}
fn verify_private_authwit(
inputs: aztec::context::inputs::private_context_inputs::PrivateContextInputs,
inner_hash: Field,
) -> return_data protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs {
{
let mut args_hasher: aztec::hash::ArgsHasher = aztec::hash::ArgsHasher::new();
args_hasher.add(inner_hash as Field);
let mut context: PrivateContext = PrivateContext::new(inputs, args_hasher.hash());
assert(
(context.inputs.call_context.is_static_call == true),
"Function verify_private_authwit can only be called statically",
);
let storage: Storage<&mut PrivateContext> = Storage::init(&mut context);
/* Safety: comment added by `nargo expand` */
unsafe {
aztec::discovery::discover_new_notes(
context.this_address(),
_compute_note_hash_and_nullifier,
)
};
let actions: AccountActions<&mut PrivateContext> =
AccountActions::init(&mut context, is_valid_impl);
let mut return_hasher: aztec::hash::ArgsHasher = aztec::hash::ArgsHasher::new();
let macro__returned__values: Field = actions.verify_private_authwit(inner_hash);
return_hasher.add(macro__returned__values as Field);
context.set_return_hash(return_hasher);
context.finish()
}
}
#[contract_library_method]
fn is_valid_impl(context: &mut PrivateContext, outer_hash: Field) -> bool {
let storage: Storage<&mut PrivateContext> = Storage::init(context);
let public_key: EcdsaPublicKeyNote = storage.public_key.get_note();
/* Safety: comment added by `nargo expand` */
let witness: [Field; 64] = unsafe { get_auth_witness(outer_hash) };
let mut signature: [u8; 64] = [0; 64];
for i in 0..64 {
signature[i] = witness[i] as u8;
}
let outer_hash_bytes: [u8; 32] = outer_hash.to_be_bytes();
let hashed_message: [u8; 32] = sha256::sha256::digest(outer_hash_bytes);
std::ecdsa_secp256k1::verify_signature(
public_key.x,
public_key.y,
signature,
hashed_message,
)
}
#[abi(storage)]
pub global STORAGE_LAYOUT_EcdsaKAccount: StorageLayout<13> = StorageLayout::<13> {
contract_name: "EcdsaKAccount",
fields: StorageLayoutFields {
public_key: aztec::state_vars::storage::Storable { slot: 1 },
},
};
#[abi(notes)]
global EcdsaPublicKeyNote_EXPORTS_3258495142: (Field, str<18>, EcdsaPublicKeyNoteFields_3258495142) = (
0, "EcdsaPublicKeyNote",
EcdsaPublicKeyNoteFields_3258495142 {
x: aztec::note::note_field::NoteField { index: 0, nullable: false },
owner: aztec::note::note_field::NoteField { index: 64, nullable: false },
y: aztec::note::note_field::NoteField { index: 32, nullable: false },
},
);
pub struct verify_private_authwit_parameters {
inner_hash: Field,
}
pub struct constructor_parameters {
signing_pub_key_x: [u8; 32],
signing_pub_key_y: [u8; 32],
}
pub struct entrypoint_parameters {
app_payload: AppPayload,
fee_payload: FeePayload,
cancellable: bool,
}
#[abi(functions)]
pub struct verify_private_authwit_abi {
parameters: verify_private_authwit_parameters,
return_type: Field,
}
#[abi(functions)]
pub struct constructor_abi {
parameters: constructor_parameters,
}
#[abi(functions)]
pub struct entrypoint_abi {
parameters: entrypoint_parameters,
}
pub struct EcdsaKAccount {
target_contract: protocol_types::address::aztec_address::AztecAddress,
}
impl EcdsaKAccount {
fn constructor(
self,
signing_pub_key_x: [u8; 32],
signing_pub_key_y: [u8; 32],
) -> aztec::context::call_interfaces::PrivateVoidCallInterface<11> {
let mut serialized_args: [Field] = &[];
let signing_pub_key_x_serialized: [[Field; 1]; 32] =
signing_pub_key_x.map(|x: u8| -> [Field; 1] x.serialize());
for i in 0..signing_pub_key_x.len() {
serialized_args =
serialized_args.append(signing_pub_key_x_serialized[i].as_slice());
}
let signing_pub_key_y_serialized: [[Field; 1]; 32] =
signing_pub_key_y.map(|x: u8| -> [Field; 1] x.serialize());
for i in 0..signing_pub_key_y.len() {
serialized_args =
serialized_args.append(signing_pub_key_y_serialized[i].as_slice());
}
let selector: protocol_types::abis::function_selector::FunctionSelector =
3065569528.from_field();
aztec::context::call_interfaces::PrivateVoidCallInterface::new(
self.target_contract,
selector,
"constructor",
serialized_args,
false,
)
}
fn entrypoint(
self,
app_payload: AppPayload,
fee_payload: FeePayload,
cancellable: bool,
) -> aztec::context::call_interfaces::PrivateVoidCallInterface<10> {
let mut serialized_args: [Field] = &[];
serialized_args = serialized_args.append(app_payload.serialize().as_slice());
serialized_args = serialized_args.append(fee_payload.serialize().as_slice());
serialized_args = serialized_args.push_back(cancellable as Field);
let selector: protocol_types::abis::function_selector::FunctionSelector =
669466802.from_field();
aztec::context::call_interfaces::PrivateVoidCallInterface::new(
self.target_contract,
selector,
"entrypoint",
serialized_args,
false,
)
}
fn at(addr: protocol_types::address::aztec_address::AztecAddress) -> EcdsaKAccount {
EcdsaKAccount { target_contract: addr }
}
fn verify_private_authwit(
self,
inner_hash: Field,
) -> aztec::context::call_interfaces::PrivateStaticCallInterface<22, Field> {
let mut serialized_args: [Field] = &[];
serialized_args = serialized_args.push_back(inner_hash as Field);
let selector: protocol_types::abis::function_selector::FunctionSelector =
3346549015.from_field();
aztec::context::call_interfaces::PrivateStaticCallInterface::new(
self.target_contract,
selector,
"verify_private_authwit",
serialized_args,
)
}
fn interface() -> EcdsaKAccount {
EcdsaKAccount {
target_contract: protocol_types::address::aztec_address::AztecAddress::zero(),
}
}
fn storage_layout() -> StorageLayoutFields {
STORAGE_LAYOUT_EcdsaKAccount.fields
}
}
#[contract_library_method]
pub fn storage_layout() -> StorageLayoutFields {
STORAGE_LAYOUT_EcdsaKAccount.fields
}
#[contract_library_method]
pub fn at(addr: protocol_types::address::aztec_address::AztecAddress) -> EcdsaKAccount {
EcdsaKAccount { target_contract: addr }
}
#[contract_library_method]
pub fn interface() -> EcdsaKAccount {
EcdsaKAccount {
target_contract: protocol_types::address::aztec_address::AztecAddress::zero(),
}
}
/// Unpacks an array into a note corresponding to `note_type_id` and then computes its note hash
/// (non-siloed) and inner nullifier (non-siloed) assuming the note has been inserted into the note hash
/// tree with `nonce`.
///
/// The signature of this function notably matches the `aztec::discovery::ComputeNoteHashAndNullifier` type,
/// and so it can be used to call functions from that module such as `discover_new_notes`, `do_process_log`
/// and `process_private_note_log`.
///
/// This function is automatically injected by the `#[aztec]` macro.
#[contract_library_method]
unconstrained fn _compute_note_hash_and_nullifier(
packed_note: BoundedVec<Field, 16>,
storage_slot: Field,
note_type_id: Field,
contract_address: protocol_types::address::aztec_address::AztecAddress,
nonce: Field,
) -> Option<aztec::discovery::NoteHashAndNullifier> {
if (note_type_id == aztec::note::note_interface::NoteType::get_id()) {
let expected_len: u32 = 5;
let actual_len: u32 = packed_note.len();
assert(
(actual_len == expected_len),
f"Expected packed note of length {expected_len} but got {actual_len} for note type id {note_type_id}",
);
let note: EcdsaPublicKeyNote =
aztec::utils::array::subarray::subarray(packed_note.storage(), 0).unpack();
let note_hash: Field = note.compute_note_hash(storage_slot);
let note_hash_for_nullify: Field = aztec::note::utils::compute_note_hash_for_nullify(
aztec::note::retrieved_note::RetrievedNote::<EcdsaPublicKeyNote> {
note: note,
contract_address: contract_address,
metadata: aztec::note::note_metadata::SettledNoteMetadata::new(nonce).into(),
},
storage_slot,
);
let inner_nullifier: Field =
note.compute_nullifier_unconstrained(note_hash_for_nullify);
Option::some(
aztec::discovery::NoteHashAndNullifier {
note_hash: note_hash,
inner_nullifier: inner_nullifier,
},
)
} else {
Option::none()
}
}
unconstrained fn process_log(
log_plaintext: BoundedVec<Field, 18>,
tx_hash: Field,
unique_note_hashes_in_tx: BoundedVec<Field, 64>,
first_nullifier_in_tx: Field,
recipient: protocol_types::address::aztec_address::AztecAddress,
) {
let context: aztec::context::unconstrained_context::UnconstrainedContext =
aztec::context::unconstrained_context::UnconstrainedContext::new();
let contract_address: protocol_types::address::aztec_address::AztecAddress =
context.this_address();
aztec::discovery::private_logs::do_process_log(
contract_address,
log_plaintext,
tx_hash,
unique_note_hashes_in_tx,
first_nullifier_in_tx,
recipient,
_compute_note_hash_and_nullifier,
);
}
unconstrained fn sync_notes() {
aztec::oracle::note_discovery::sync_notes();
}
pub struct EcdsaPublicKeyNoteFields_3258495142 {
x: aztec::note::note_field::NoteField,
y: aztec::note::note_field::NoteField,
owner: aztec::note::note_field::NoteField,
}
pub struct StorageLayoutFields {
public_key: aztec::state_vars::storage::Storable,
}
pub struct StorageLayout<let N: u32> {
contract_name: str<N>,
fields: StorageLayoutFields,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment