Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: optionally emit public bytecode #10365

Merged
merged 1 commit into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
use dep::aztec::protocol_types::{
constants::REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE, contract_class_id::ContractClassId,
constants::{
MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE,
},
contract_class_id::ContractClassId,
traits::Serialize,
};

// TODO(#10007): Use MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS instead
pub global MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS: u32 = 100;

pub struct ContractClassRegistered {
contract_class_id: ContractClassId,
version: Field,
artifact_hash: Field,
private_functions_root: Field,
packed_public_bytecode: [Field; MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS],
packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS],
}

impl Serialize<MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5> for ContractClassRegistered {
fn serialize(
self: Self,
) -> [Field; MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5] {
let mut packed = [0; MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5];
impl Serialize<MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5> for ContractClassRegistered {
fn serialize(self: Self) -> [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5] {
let mut packed = [0; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5];
packed[0] = REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE;
packed[1] = self.contract_class_id.to_field();
packed[2] = self.version;
packed[3] = self.artifact_hash;
packed[4] = self.private_functions_root;
for i in 0..MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS {
for i in 0..MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS {
packed[i + 5] = self.packed_public_bytecode[i];
}
packed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ contract ContractClassRegisterer {
};

use crate::events::{
class_registered::{
ContractClassRegistered, MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS,
},
class_registered::ContractClassRegistered,
private_function_broadcasted::{
ClassPrivateFunctionBroadcasted, InnerPrivateFunction, PrivateFunction,
},
Expand All @@ -44,6 +42,7 @@ contract ContractClassRegisterer {
artifact_hash: Field,
private_functions_root: Field,
public_bytecode_commitment: Field,
emit: bool,
) {
// TODO: Validate public_bytecode_commitment is the correct commitment of packed_public_bytecode
// TODO: We should be able to remove public_bytecode_commitment from the input if it's calculated in this function
Expand Down Expand Up @@ -98,18 +97,13 @@ contract ContractClassRegisterer {

// TODO(#10007): Drop this conditional and always emit the bytecode. We allow skipping the broadcast
// as a stopgap solution to allow txs to fit in Sepolia when we broadcast public bytecode.
if bytecode_length_in_fields <= MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS {
let mut event_public_bytecode =
[0; MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS];
for i in 0..MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS {
event_public_bytecode[i] = packed_public_bytecode[i];
}
if emit {
let event = ContractClassRegistered {
contract_class_id,
version: 1,
artifact_hash,
private_functions_root,
packed_public_bytecode: event_public_bytecode,
packed_public_bytecode,
};
emit_contract_class_log(&mut context, event.serialize());
}
Expand Down
9 changes: 8 additions & 1 deletion yarn-project/aztec.js/src/deployment/register_class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,22 @@ import { type ContractFunctionInteraction } from '../contract/contract_function_
import { type Wallet } from '../wallet/index.js';
import { getRegistererContract } from './protocol_contracts.js';

const defaultEmitPublicBytecode =
// guard against `process` not being defined (e.g. in the browser)
typeof process === 'object' && typeof process.env === 'object'
? ['1', 'true', 'yes', ''].includes(process.env.AZTEC_EMIT_PUBLIC_BYTECODE ?? '')
: true;

/** Sets up a call to register a contract class given its artifact. */
export async function registerContractClass(
wallet: Wallet,
artifact: ContractArtifact,
emitPublicBytecode = defaultEmitPublicBytecode,
): Promise<ContractFunctionInteraction> {
const { artifactHash, privateFunctionsRoot, publicBytecodeCommitment, packedBytecode } =
getContractClassFromArtifact(artifact);
const encodedBytecode = bufferAsFields(packedBytecode, MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS);
const registerer = getRegistererContract(wallet);
await wallet.addCapsule(encodedBytecode);
return registerer.methods.register(artifactHash, privateFunctionsRoot, publicBytecodeCommitment);
return registerer.methods.register(artifactHash, privateFunctionsRoot, publicBytecodeCommitment, emitPublicBytecode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('e2e_deploy_contract contract class registration', () => {

beforeAll(async () => {
artifact = StatefulTestContract.artifact;
registrationTxReceipt = await registerContractClass(wallet, artifact).then(c => c.send().wait());
registrationTxReceipt = await registerContractClass(wallet, artifact, false).then(c => c.send().wait());
contractClass = getContractClassFromArtifact(artifact);

// TODO(#10007) Remove this call. Node should get the bytecode from the event broadcast.
Expand All @@ -58,6 +58,14 @@ describe('e2e_deploy_contract contract class registration', () => {
});

describe('registering a contract class', () => {
it('optionally emits public bytecode', async () => {
const registrationTxReceipt = await registerContractClass(wallet, TestContract.artifact, true).then(c =>
c.send().wait(),
);
const logs = await aztecNode.getContractClassLogs({ txHash: registrationTxReceipt.txHash });
expect(logs.logs.length).toEqual(1);
});

// TODO(#10007) Remove this test. We should always broadcast public bytecode.
it('bypasses broadcast if exceeds bytecode limit for event size', async () => {
const logs = await aztecNode.getContractClassLogs({ txHash: registrationTxReceipt.txHash });
Expand Down
Loading