Skip to content
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
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 @@ contract AvmTest {
}

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

/************************************************************************
>>>>>>> master
* Contract instance
************************************************************************/
#[public]
Expand Down Expand Up @@ -660,15 +663,15 @@ 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 @@ -38,6 +38,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 @@ -386,19 +387,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...;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dbanks12 I would directly add this code in a bash script and commit it to the repo.

* 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);
}