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

chore!: remove param_witnesses and return_witnesses from ABI #5154

Merged
merged 5 commits into from
Jun 10, 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
27 changes: 0 additions & 27 deletions .github/workflows/test-js-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,32 +221,6 @@ jobs:
- name: Run browser tests
run: yarn workspace @noir-lang/noirc_abi test:browser

test-noir-js-backend-barretenberg:
needs: [build-noirc-abi]
name: noir-js-backend-barretenberg
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Download wasm package artifact
uses: actions/download-artifact@v4
with:
name: noirc_abi_wasm
path: ./tooling/noirc_abi_wasm

- name: Install Yarn dependencies
uses: ./.github/actions/setup

- name: Build noir_js_types
run: yarn workspace @noir-lang/types build

- name: Run barretenberg wrapper tests
run: |
yarn workspace @noir-lang/backend_barretenberg test

test-noir-js:
needs: [build-nargo, build-acvm-js, build-noirc-abi]
name: Noir JS
Expand Down Expand Up @@ -546,7 +520,6 @@ jobs:
- test-acvm_js-node
- test-acvm_js-browser
- test-noirc-abi
- test-noir-js-backend-barretenberg
- test-noir-js
- test-noir-wasm
- test-noir-codegen
Expand Down
93 changes: 2 additions & 91 deletions compiler/noirc_driver/src/abi_gen.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use std::collections::BTreeMap;

use acvm::acir::circuit::ErrorSelector;
use acvm::acir::native_types::Witness;
use iter_extended::{btree_map, vecmap};
use iter_extended::vecmap;
use noirc_abi::{Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue};
use noirc_frontend::ast::Visibility;
use noirc_frontend::{
Expand All @@ -11,27 +10,23 @@ use noirc_frontend::{
macros_api::{HirExpression, HirLiteral},
node_interner::{FuncId, NodeInterner},
};
use std::ops::Range;

/// Arranges a function signature and a generated circuit's return witnesses into a
/// `noirc_abi::Abi`.
pub(super) fn gen_abi(
context: &Context,
func_id: &FuncId,
input_witnesses: Vec<Witness>,
return_witnesses: Vec<Witness>,
return_visibility: Visibility,
error_types: BTreeMap<ErrorSelector, Type>,
) -> Abi {
let (parameters, return_type) = compute_function_abi(context, func_id);
let param_witnesses = param_witnesses_from_abi_param(&parameters, input_witnesses);
let return_type = return_type
.map(|typ| AbiReturnType { abi_type: typ, visibility: return_visibility.into() });
let error_types = error_types
.into_iter()
.map(|(selector, typ)| (selector, AbiErrorType::from_type(context, &typ)))
.collect();
Abi { parameters, return_type, param_witnesses, return_witnesses, error_types }
Abi { parameters, return_type, error_types }
}

pub(super) fn compute_function_abi(
Expand Down Expand Up @@ -67,55 +62,6 @@ fn into_abi_params(context: &Context, params: Vec<Param>) -> Vec<AbiParameter> {
})
}

// Takes each abi parameter and shallowly maps to the expected witness range in which the
// parameter's constituent values live.
fn param_witnesses_from_abi_param(
abi_params: &[AbiParameter],
input_witnesses: Vec<Witness>,
) -> BTreeMap<String, Vec<Range<Witness>>> {
let mut idx = 0_usize;
if input_witnesses.is_empty() {
return BTreeMap::new();
}

btree_map(abi_params, |param| {
let num_field_elements_needed = param.typ.field_count() as usize;
let param_witnesses = &input_witnesses[idx..idx + num_field_elements_needed];

// It's likely that `param_witnesses` will consist of mostly incrementing witness indices.
// We then want to collapse these into `Range`s to save space.
let param_witnesses = collapse_ranges(param_witnesses);
idx += num_field_elements_needed;
(param.name.clone(), param_witnesses)
})
}

/// Takes a vector of [`Witnesses`][`Witness`] and collapses it into a vector of [`Range`]s of [`Witnesses`][`Witness`].
fn collapse_ranges(witnesses: &[Witness]) -> Vec<Range<Witness>> {
if witnesses.is_empty() {
return Vec::new();
}
let mut wit = Vec::new();
let mut last_wit: Witness = witnesses[0];

for (i, witness) in witnesses.iter().enumerate() {
if i == 0 {
continue;
};
let witness_index = witness.witness_index();
let prev_witness_index = witnesses[i - 1].witness_index();
if witness_index != prev_witness_index + 1 {
wit.push(last_wit..Witness(prev_witness_index + 1));
last_wit = *witness;
};
}

let last_witness = witnesses.last().unwrap().witness_index();
wit.push(last_wit..Witness(last_witness + 1));

wit
}

pub(super) fn value_from_hir_expression(context: &Context, expression: HirExpression) -> AbiValue {
match expression {
HirExpression::Tuple(expr_ids) => {
Expand Down Expand Up @@ -169,38 +115,3 @@ pub(super) fn value_from_hir_expression(context: &Context, expression: HirExpres
_ => unreachable!("Type cannot be used in the abi {:?}", expression),
}
}

#[cfg(test)]
mod test {
use std::ops::Range;

use acvm::acir::native_types::Witness;

use super::collapse_ranges;

#[test]
fn collapses_single_range() {
let witnesses: Vec<_> = vec![1, 2, 3].into_iter().map(Witness::from).collect();

let collapsed_witnesses = collapse_ranges(&witnesses);

assert_eq!(collapsed_witnesses, vec![Range { start: Witness(1), end: Witness(4) },]);
}

#[test]
fn collapse_ranges_correctly() {
let witnesses: Vec<_> =
vec![1, 2, 3, 5, 6, 2, 3, 4].into_iter().map(Witness::from).collect();

let collapsed_witnesses = collapse_ranges(&witnesses);

assert_eq!(
collapsed_witnesses,
vec![
Range { start: Witness(1), end: Witness(4) },
Range { start: Witness(5), end: Witness(7) },
Range { start: Witness(2), end: Witness(5) }
]
);
}
}
21 changes: 3 additions & 18 deletions compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,32 +531,17 @@ pub fn compile_no_check(
info!("Program matches existing artifact, returning early");
return Ok(cached_program.expect("cache must exist for hashes to match"));
}
let visibility = program.return_visibility;
let return_visibility = program.return_visibility;

let SsaProgramArtifact {
program,
debug,
warnings,
main_input_witnesses,
main_return_witnesses,
names,
error_types,
} = create_program(
let SsaProgramArtifact { program, debug, warnings, names, error_types, .. } = create_program(
program,
options.show_ssa,
options.show_brillig,
options.force_brillig,
options.benchmark_codegen,
)?;

let abi = abi_gen::gen_abi(
context,
&main_function,
main_input_witnesses,
main_return_witnesses,
visibility,
error_types,
);
let abi = abi_gen::gen_abi(context, &main_function, return_visibility, error_types);
let file_map = filter_relevant_files(&debug, &context.file_manager);

Ok(CompiledProgram {
Expand Down
3 changes: 2 additions & 1 deletion docs/docs/getting_started/tooling/noir_codegen.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ After the export and codegen steps, you should have an `index.ts` like:
export type Field = string;


export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"};
export const is_equal_circuit: CompiledCircuit =
{"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"}},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"};

export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise<boolean> {
const program = new Noir(is_equal_circuit);
Expand Down
3 changes: 1 addition & 2 deletions tooling/nargo_cli/src/cli/debug_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,10 @@ fn debug_program_and_decode(
let (inputs_map, _) =
read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &program.abi)?;
let solved_witness = debug_program(&program, &inputs_map)?;
let public_abi = program.abi.public_abi();

match solved_witness {
Some(witness) => {
let (_, return_value) = public_abi.decode(&witness)?;
let (_, return_value) = program.abi.decode(&witness)?;
Ok((return_value, Some(witness)))
}
None => Ok((None, None)),
Expand Down
3 changes: 1 addition & 2 deletions tooling/nargo_cli/src/cli/execute_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,10 @@ fn execute_program_and_decode(
let (inputs_map, _) =
read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &program.abi)?;
let witness_stack = execute_program(&program, &inputs_map, foreign_call_resolver_url)?;
let public_abi = program.abi.public_abi();
// Get the entry point witness for the ABI
let main_witness =
&witness_stack.peek().expect("Should have at least one witness on the stack").witness;
let (_, return_value) = public_abi.decode(main_witness)?;
let (_, return_value) = program.abi.decode(main_witness)?;

Ok((return_value, witness_stack))
}
Expand Down
3 changes: 0 additions & 3 deletions tooling/noir_js_backend_barretenberg/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
"generate:package": "bash ./fixup.sh",
"build": "yarn clean && tsc && tsc -p ./tsconfig.cjs.json && yarn generate:package",
"clean": "rm -rf ./lib",
"test": "mocha --timeout 25000 --exit --config ./.mocharc.json",
"prettier": "prettier 'src/**/*.ts'",
"prettier:fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts'",
"nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json",
Expand All @@ -49,10 +48,8 @@
"devDependencies": {
"@types/node": "^20.6.2",
"@types/prettier": "^3",
"chai": "^4.4.1",
"eslint": "^8.57.0",
"eslint-plugin-prettier": "^5.1.3",
"mocha": "^10.2.0",
"prettier": "3.2.5",
"ts-node": "^10.9.1",
"typescript": "5.4.2"
Expand Down
1 change: 0 additions & 1 deletion tooling/noir_js_backend_barretenberg/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export { BarretenbergBackend } from './backend.js';
export { BarretenbergVerifier } from './verifier.js';
export { publicInputsToWitnessMap } from './public_inputs.js';

// typedoc exports
export { Backend, CompiledCircuit, ProofData } from '@noir-lang/types';
Expand Down
26 changes: 1 addition & 25 deletions tooling/noir_js_backend_barretenberg/src/public_inputs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Abi, WitnessMap } from '@noir-lang/types';
import { WitnessMap } from '@noir-lang/types';

export function flattenPublicInputsAsArray(publicInputs: string[]): Uint8Array {
const flattenedPublicInputs = publicInputs.map(hexToUint8Array);
Expand All @@ -23,30 +23,6 @@ export function witnessMapToPublicInputs(publicInputs: WitnessMap): string[] {
return flattenedPublicInputs;
}

export function publicInputsToWitnessMap(publicInputs: string[], abi: Abi): WitnessMap {
const return_value_witnesses = abi.return_witnesses;
const public_parameters = abi.parameters.filter((param) => param.visibility === 'public');
const public_parameter_witnesses: number[] = public_parameters.flatMap((param) =>
abi.param_witnesses[param.name].flatMap((witness_range) =>
Array.from({ length: witness_range.end - witness_range.start }, (_, i) => witness_range.start + i),
),
);

// We now have an array of witness indices which have been deduplicated and sorted in ascending order.
// The elements of this array should correspond to the elements of `flattenedPublicInputs` so that we can build up a `WitnessMap`.
const public_input_witnesses = [...new Set(public_parameter_witnesses.concat(return_value_witnesses))].sort(
(a, b) => a - b,
);

const witnessMap: WitnessMap = new Map();
public_input_witnesses.forEach((witness_index, index) => {
const witness_value = publicInputs[index];
witnessMap.set(witness_index, witness_value);
});

return witnessMap;
}

function flattenUint8Arrays(arrays: Uint8Array[]): Uint8Array {
const totalLength = arrays.reduce((acc, val) => acc + val.length, 0);
const result = new Uint8Array(totalLength);
Expand Down
Loading
Loading