Skip to content

Commit

Permalink
chore(avm)!: dont compress public bytecode (#8623)
Browse files Browse the repository at this point in the history
The bytecode now fits uncompressed (as expected) in the max public size
(600kB, which we expect to lower to 30k or 100k)

Thanks Noir + Alvaro!
  • Loading branch information
fcarreiro committed Sep 18, 2024
1 parent 650a241 commit 353da3f
Show file tree
Hide file tree
Showing 6 changed files with 13 additions and 41 deletions.
1 change: 0 additions & 1 deletion avm-transpiler/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion avm-transpiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,3 @@ env_logger = "0.11"
log = "0.4"
serde_json = "1.0"
serde = { version = "1.0.136", features = ["derive"] }
flate2 = "1.0"
14 changes: 2 additions & 12 deletions avm-transpiler/src/transpile_contract.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::io::Read;

use acvm::FieldElement;
use base64::Engine;
use log::info;
Expand Down Expand Up @@ -112,19 +110,11 @@ impl From<CompiledAcirContractArtifact> for TranspiledContractArtifact {
// Transpile to AVM
let avm_bytecode = brillig_to_avm(brillig_bytecode, &brillig_pcs_to_avm_pcs);

// Gzip AVM bytecode. This has to be removed once we need to do bytecode verification.
let mut compressed_avm_bytecode = Vec::new();
let mut encoder =
flate2::read::GzEncoder::new(&avm_bytecode[..], flate2::Compression::best());
let _ = encoder.read_to_end(&mut compressed_avm_bytecode);

log::info!(
"{}::{}: bytecode size of {} was compressed to {} ({}% reduction)",
"{}::{}: bytecode is {} bytes",
contract.name,
function.name,
avm_bytecode.len(),
compressed_avm_bytecode.len(),
100 - (compressed_avm_bytecode.len() * 100 / avm_bytecode.len())
);

// Patch the debug infos with updated PCs
Expand All @@ -140,7 +130,7 @@ impl From<CompiledAcirContractArtifact> for TranspiledContractArtifact {
is_unconstrained: function.is_unconstrained,
custom_attributes: function.custom_attributes,
abi: function.abi,
bytecode: base64::prelude::BASE64_STANDARD.encode(compressed_avm_bytecode),
bytecode: base64::prelude::BASE64_STANDARD.encode(avm_bytecode),
debug_symbols: ProgramDebugInfo { debug_infos },
brillig_names: function.brillig_names,
assert_messages,
Expand Down
10 changes: 5 additions & 5 deletions yarn-project/simulator/src/avm/avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ describe('AVM simulator: injected bytecode', () => {
]);
});

it('Should not be recognized as AVM bytecode (magic missing)', async () => {
expect(!(await isAvmBytecode(bytecode)));
it('Should not be recognized as AVM bytecode (magic missing)', () => {
expect(!isAvmBytecode(bytecode));
});

it('Should execute bytecode that performs basic addition', async () => {
Expand Down Expand Up @@ -117,9 +117,9 @@ describe('AVM simulator: transpiled Noir contracts', () => {
expect(results.output).toEqual([new Fr(0)]);
});

it('Should be recognized as AVM bytecode (magic present)', async () => {
it('Should be recognized as AVM bytecode (magic present)', () => {
const bytecode = getAvmTestContractBytecode('add_args_return');
expect(await isAvmBytecode(bytecode));
expect(isAvmBytecode(bytecode));
});

it('elliptic curve operations', async () => {
Expand Down Expand Up @@ -813,7 +813,7 @@ describe('AVM simulator: transpiled Noir contracts', () => {
}),
/*startGasLeft=*/ expect.anything(),
/*endGasLeft=*/ expect.anything(),
/*bytecode=*/ expect.anything(), //decompressBytecodeIfCompressed(addBytecode),
/*bytecode=*/ expect.anything(),
/*avmCallResults=*/ expect.anything(), // we don't have the NESTED call's results to check
/*functionName=*/ expect.anything(),
);
Expand Down
9 changes: 4 additions & 5 deletions yarn-project/simulator/src/avm/avm_simulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { strict as assert } from 'assert';

import type { AvmContext } from './avm_context.js';
import { AvmContractCallResult } from './avm_contract_call_result.js';
import { decompressBytecodeIfCompressed, isAvmBytecode } from './bytecode_utils.js';
import { isAvmBytecode } from './bytecode_utils.js';
import {
AvmExecutionError,
InvalidProgramCounterError,
Expand Down Expand Up @@ -53,11 +53,10 @@ export class AvmSimulator {
* This method is useful for testing and debugging.
*/
public async executeBytecode(bytecode: Buffer): Promise<AvmContractCallResult> {
const decompressedBytecode = await decompressBytecodeIfCompressed(bytecode);
assert(await isAvmBytecode(decompressedBytecode), "AVM simulator can't execute non-AVM bytecode");
assert(isAvmBytecode(bytecode), "AVM simulator can't execute non-AVM bytecode");

this.bytecode = decompressedBytecode;
return await this.executeInstructions(decodeFromBytecode(decompressedBytecode));
this.bytecode = bytecode;
return await this.executeInstructions(decodeFromBytecode(bytecode));
}

/**
Expand Down
19 changes: 2 additions & 17 deletions yarn-project/simulator/src/avm/bytecode_utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import { promisify } from 'util';
import { gunzip } from 'zlib';

import { Opcode } from './serialization/instruction_serialization.js';

const AVM_MAGIC_SUFFIX = Buffer.from([
Expand All @@ -14,19 +11,7 @@ export function markBytecodeAsAvm(bytecode: Buffer): Buffer {
return Buffer.concat([bytecode, AVM_MAGIC_SUFFIX]);
}

// This is just a helper function for the AVM simulator
export async function decompressBytecodeIfCompressed(bytecode: Buffer): Promise<Buffer> {
try {
return await promisify(gunzip)(bytecode);
} catch {
// If the bytecode is not compressed, the gunzip call will throw an error
// In this case, we assume the bytecode is not compressed and continue.
return Promise.resolve(bytecode);
}
}

export async function isAvmBytecode(bytecode: Buffer): Promise<boolean> {
const decompressedBytecode = await decompressBytecodeIfCompressed(bytecode);
export function isAvmBytecode(bytecode: Buffer): boolean {
const magicSize = AVM_MAGIC_SUFFIX.length;
return decompressedBytecode.subarray(-magicSize).equals(AVM_MAGIC_SUFFIX);
return bytecode.subarray(-magicSize).equals(AVM_MAGIC_SUFFIX);
}

0 comments on commit 353da3f

Please sign in to comment.