Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into ad/avm-proving
Browse files Browse the repository at this point in the history
  • Loading branch information
ludamad committed Feb 4, 2025
2 parents 8b2c99e + 1778867 commit 8b18f31
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 8 deletions.
1 change: 1 addition & 0 deletions noir-projects/noir-contracts/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"contracts/auth_contract",
"contracts/auth_registry_contract",
"contracts/auth_wit_test_contract",
"contracts/avm_gadgets_test_contract",
"contracts/avm_initializer_test_contract",
"contracts/avm_test_contract",
"contracts/fpc_contract",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "avm_gadgets_test_contract"
authors = [""]
compiler_version = ">=0.25.0"
type = "contract"

[dependencies]
aztec = { path = "../../../aztec-nr/aztec" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use dep::aztec::macros::aztec;

#[aztec]
contract AvmGadgetsTest {
use dep::aztec::macros::functions::public;

#[public]
fn keccak_hash(data: [u8; 10]) -> [u8; 32] {
std::hash::keccak256(data, data.len() as u32)
}

#[public]
fn keccak_f1600(data: [u64; 25]) -> [u64; 25] {
std::hash::keccak::keccakf1600(data)
}

#[public]
fn poseidon2_hash(data: [Field; 10]) -> Field {
std::hash::poseidon2::Poseidon2::hash(data, data.len())
}

#[public]
fn sha256_hash_10(data: [u8; 10]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_20(data: [u8; 20]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_30(data: [u8; 30]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_40(data: [u8; 40]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_50(data: [u8; 50]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_60(data: [u8; 60]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_70(data: [u8; 70]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_80(data: [u8; 80]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_90(data: [u8; 90]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_100(data: [u8; 100]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_255(data: [u8; 255]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_256(data: [u8; 256]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_511(data: [u8; 511]) -> [u8; 32] {
std::hash::sha256(data)
}
#[public]
fn sha256_hash_512(data: [u8; 512]) -> [u8; 32] {
std::hash::sha256(data)
}

#[public]
fn sha256_hash_2048(data: [u8; 2048]) -> [u8; 32] {
std::hash::sha256(data)
}

#[public]
fn pedersen_hash(data: [Field; 10]) -> Field {
std::hash::pedersen_hash(data)
}

#[public]
fn pedersen_hash_with_index(data: [Field; 10]) -> Field {
std::hash::pedersen_hash_with_separator(data, /*index=*/ 20)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ pub contract AvmTest {
}

/************************************************************************
<<<<<<< HEAD
=======
* Hashing functions
************************************************************************/
#[public]
Expand Down Expand Up @@ -330,6 +332,7 @@ pub contract AvmTest {
}

/************************************************************************
>>>>>>> master
* Contract instance
************************************************************************/
#[public]
Expand Down Expand Up @@ -660,15 +663,15 @@ pub contract AvmTest {
dep::aztec::oracle::debug_log::debug_log("read_storage_map");
let _ = read_storage_map(context.this_address());
dep::aztec::oracle::debug_log::debug_log("keccak_hash");
let _ = keccak_hash(args_u8);
let _ = std::hash::keccak256(args_u8, args_u8.len() as u32);
dep::aztec::oracle::debug_log::debug_log("sha256_hash");
let _ = sha256_hash(args_u8);
let _ = std::hash::sha256(args_u8);
dep::aztec::oracle::debug_log::debug_log("poseidon2_hash");
let _ = poseidon2_hash(args_field);
let _ = std::hash::poseidon2::Poseidon2::hash(args_field, args_field.len());
dep::aztec::oracle::debug_log::debug_log("pedersen_hash");
let _ = pedersen_hash(args_field);
let _ = std::hash::pedersen_hash(args_field);
dep::aztec::oracle::debug_log::debug_log("pedersen_hash_with_index");
let _ = pedersen_hash_with_index(args_field);
let _ = std::hash::pedersen_hash_with_separator(args_field, /*index=*/ 20);
dep::aztec::oracle::debug_log::debug_log("test_get_contract_instance");
test_get_contract_instance_matches(
get_instance_for_address,
Expand Down
31 changes: 28 additions & 3 deletions yarn-project/simulator/src/avm/avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { AvmSimulator } from './avm_simulator.js';
import { AvmEphemeralForest } from './avm_tree.js';
import { isAvmBytecode, markBytecodeAsAvm } from './bytecode_utils.js';
import {
getAvmGadgetsTestContractBytecode,
getAvmTestContractArtifact,
getAvmTestContractBytecode,
initContext,
Expand Down Expand Up @@ -384,19 +385,43 @@ describe('AVM simulator: transpiled Noir contracts', () => {
});
});

/*
* Can run these as follows to measure sha256 instruction execution counts:
* for i in 10 20 30 40 50 60 70 80 90 100 255 256 511 512 2048; do
* echo sha-ing $i...;
* LOG_LEVEL=debug yarn test src/avm/avm_simulator.test.ts -t "sha256_hash_$i " &> sha$i.log;
* done
* for i in 10 20 30 40 50 60 70 80 90 100 255 256 511 512 2048; do
* echo sha256 of $i bytes $(grep -Eo 'Executed .* instructions.* Gas' sha$i.log);
* done
*/
describe.each([
['sha256_hash', /*input=*/ randomMemoryBytes(10), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_10', /*input=*/ randomMemoryBytes(10), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_20', /*input=*/ randomMemoryBytes(20), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_30', /*input=*/ randomMemoryBytes(30), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_40', /*input=*/ randomMemoryBytes(40), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_50', /*input=*/ randomMemoryBytes(50), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_60', /*input=*/ randomMemoryBytes(60), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_70', /*input=*/ randomMemoryBytes(70), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_80', /*input=*/ randomMemoryBytes(80), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_90', /*input=*/ randomMemoryBytes(90), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_100', /*input=*/ randomMemoryBytes(100), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_255', /*input=*/ randomMemoryBytes(255), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_256', /*input=*/ randomMemoryBytes(256), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_511', /*input=*/ randomMemoryBytes(511), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_512', /*input=*/ randomMemoryBytes(512), /*output=*/ sha256FromMemoryBytes],
['sha256_hash_2048', /*input=*/ randomMemoryBytes(2048), /*output=*/ sha256FromMemoryBytes],
['keccak_hash', /*input=*/ randomMemoryBytes(10), /*output=*/ keccak256FromMemoryBytes],
['keccak_f1600', /*input=*/ randomMemoryUint64s(25), /*output=*/ keccakF1600FromMemoryUint64s],
['poseidon2_hash', /*input=*/ randomMemoryFields(10), /*output=*/ poseidon2FromMemoryFields],
['pedersen_hash', /*input=*/ randomMemoryFields(10), /*output=*/ pedersenFromMemoryFields],
['pedersen_hash_with_index', /*input=*/ randomMemoryFields(10), /*output=*/ indexedPedersenFromMemoryFields],
])('Hashes in noir contracts', (name: string, input: MemoryValue[], output: (msg: any[]) => Promise<Fr[]>) => {
it(`Should execute contract function that performs ${name}`, async () => {
it(`Should execute contract function that performs ${name} on input of length ${input.length}`, async () => {
const calldata = input.map(e => e.toFr());

const context = initContext({ env: initExecutionEnvironment({ calldata }) });
const bytecode = getAvmTestContractBytecode(name);
const bytecode = getAvmGadgetsTestContractBytecode(name);
const results = await new AvmSimulator(context).executeBytecode(bytecode);

expect(results.reverted).toBe(false);
Expand Down
39 changes: 39 additions & 0 deletions yarn-project/simulator/src/avm/fixtures/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { type ContractArtifact, type FunctionArtifact, FunctionSelector } from '
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr } from '@aztec/foundation/fields';
import { AvmGadgetsTestContractArtifact } from '@aztec/noir-contracts.js/AvmGadgetsTest';
import { AvmTestContractArtifact } from '@aztec/noir-contracts.js/AvmTest';

import { strict as assert } from 'assert';
Expand Down Expand Up @@ -169,6 +170,13 @@ export function getAvmTestContractFunctionSelector(functionName: string): Promis
return getFunctionSelector(functionName, AvmTestContractArtifact);
}

export function getAvmGadgetsTestContractFunctionSelector(functionName: string): Promise<FunctionSelector> {
const artifact = AvmGadgetsTestContractArtifact.functions.find(f => f.name === functionName)!;
assert(!!artifact, `Function ${functionName} not found in AvmGadgetsTestContractArtifact`);
const params = artifact.parameters;
return FunctionSelector.fromNameAndParameters(artifact.name, params);
}

export function getAvmTestContractArtifact(functionName: string): FunctionArtifact {
const artifact = getContractFunctionArtifact(functionName, AvmTestContractArtifact);
assert(
Expand All @@ -178,15 +186,46 @@ export function getAvmTestContractArtifact(functionName: string): FunctionArtifa
return artifact;
}

export function getAvmGadgetsTestContractArtifact(functionName: string): FunctionArtifact {
const artifact = AvmGadgetsTestContractArtifact.functions.find(f => f.name === functionName)!;
assert(
!!artifact?.bytecode,
`No bytecode found for function ${functionName}. Try re-running bootstrap.sh on the repository root.`,
);
return artifact;
}

export function getAvmTestContractBytecode(functionName: string): Buffer {
const artifact = getAvmTestContractArtifact(functionName);
return artifact.bytecode;
}

export function getAvmGadgetsTestContractBytecode(functionName: string): Buffer {
const artifact = getAvmGadgetsTestContractArtifact(functionName);
return artifact.bytecode;
}

export function resolveAvmTestContractAssertionMessage(
functionName: string,
revertReason: AvmRevertReason,
output: Fr[],
): string | undefined {
return resolveContractAssertionMessage(functionName, revertReason, output, AvmTestContractArtifact);
}

export function resolveAvmGadgetsTestContractAssertionMessage(
functionName: string,
revertReason: AvmRevertReason,
output: Fr[],
): string | undefined {
traverseCauseChain(revertReason, cause => {
revertReason = cause as AvmRevertReason;
});

const functionArtifact = AvmGadgetsTestContractArtifact.functions.find(f => f.name === functionName);
if (!functionArtifact || !revertReason.noirCallStack || !isNoirCallStackUnresolved(revertReason.noirCallStack)) {
return undefined;
}

return resolveAssertionMessageFromRevertData(output, functionArtifact);
}

0 comments on commit 8b18f31

Please sign in to comment.