diff --git a/noir/noir-repo/examples/recursion/.gitignore b/noir/noir-repo/examples/recursion/.gitignore new file mode 100644 index 00000000000..12587094b0f --- /dev/null +++ b/noir/noir-repo/examples/recursion/.gitignore @@ -0,0 +1,2 @@ +recurse_leaf/Prover.toml +recurse_node/Prover.toml \ No newline at end of file diff --git a/noir/noir-repo/examples/recursion/Nargo.toml b/noir/noir-repo/examples/recursion/Nargo.toml new file mode 100644 index 00000000000..7c7a8b1926f --- /dev/null +++ b/noir/noir-repo/examples/recursion/Nargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["recurse_leaf", "recurse_node", "sum"] diff --git a/noir/noir-repo/examples/recursion/generate_recursive_proof.sh b/noir/noir-repo/examples/recursion/generate_recursive_proof.sh new file mode 100755 index 00000000000..362512529d4 --- /dev/null +++ b/noir/noir-repo/examples/recursion/generate_recursive_proof.sh @@ -0,0 +1,61 @@ +#!/bin/bash +set -eu + +BACKEND=${BACKEND:-bb} + +nargo execute sum_witness --package sum +$BACKEND prove -b ./target/sum.json -w ./target/sum_witness.gz -o ./target/sum_proof + +# Once we have generated our inner proof, we must use this to generate inputs to `recurse_leaf`` + +$BACKEND write_vk -b ./target/sum.json -o ./target/sum_key +$BACKEND vk_as_fields -k ./target/sum_key -o ./target/sum_vk_as_fields +VK_HASH=$(jq -r '.[0]' ./target/sum_vk_as_fields) +VK_AS_FIELDS=$(jq -r '.[1:]' ./target/sum_vk_as_fields) + +FULL_PROOF_AS_FIELDS="$($BACKEND proof_as_fields -p ./target/sum_proof -k ./target/sum_key -o -)" +# sum has 3 public inputs +PUBLIC_INPUTS=$(echo $FULL_PROOF_AS_FIELDS | jq -r '.[:3]') +PROOF_AS_FIELDS=$(echo $FULL_PROOF_AS_FIELDS | jq -r '.[3:]') + +RECURSE_LEAF_PROVER_TOML=./recurse_leaf/Prover.toml +echo "num = 2" > $RECURSE_LEAF_PROVER_TOML +echo "key_hash = \"$VK_HASH\"" >> $RECURSE_LEAF_PROVER_TOML +echo "verification_key = $VK_AS_FIELDS" >> $RECURSE_LEAF_PROVER_TOML +echo "proof = $PROOF_AS_FIELDS" >> $RECURSE_LEAF_PROVER_TOML +echo "public_inputs = $PUBLIC_INPUTS" >> $RECURSE_LEAF_PROVER_TOML + +# We can now execute and prove `recurse_leaf` + +nargo execute recurse_leaf_witness --package recurse_leaf +$BACKEND prove -b ./target/recurse_leaf.json -w ./target/recurse_leaf_witness.gz -o ./target/recurse_leaf_proof + +# Let's do a sanity check that the proof we've generated so far is valid. +$BACKEND write_vk -b ./target/recurse_leaf.json -o ./target/recurse_leaf_key +$BACKEND verify -p ./target/recurse_leaf_proof -k ./target/recurse_leaf_key + +# Now we generate the final `recurse_node` proof similarly to how we did for `recurse_leaf`. + +$BACKEND vk_as_fields -k ./target/recurse_leaf_key -o ./target/recurse_leaf_vk_as_fields +VK_HASH=$(jq -r '.[0]' ./target/recurse_leaf_vk_as_fields) +VK_AS_FIELDS=$(jq -r '.[1:]' ./target/recurse_leaf_vk_as_fields) + +FULL_PROOF_AS_FIELDS="$($BACKEND proof_as_fields -p ./target/recurse_leaf_proof -k ./target/recurse_leaf_key -o -)" +# recurse_leaf has 4 public inputs (excluding aggregation object) +PUBLIC_INPUTS=$(echo $FULL_PROOF_AS_FIELDS | jq -r '.[:4]') +PROOF_AS_FIELDS=$(echo $FULL_PROOF_AS_FIELDS | jq -r '.[4:]') + +RECURSE_NODE_PROVER_TOML=./recurse_node/Prover.toml +echo "key_hash = \"$VK_HASH\"" > $RECURSE_NODE_PROVER_TOML +echo "verification_key = $VK_AS_FIELDS" >> $RECURSE_NODE_PROVER_TOML +echo "proof = $PROOF_AS_FIELDS" >> $RECURSE_NODE_PROVER_TOML +echo "public_inputs = $PUBLIC_INPUTS" >> $RECURSE_NODE_PROVER_TOML + +# We can now execute and prove `recurse_node` + +nargo execute recurse_node_witness --package recurse_node +$BACKEND prove -b ./target/recurse_node.json -w ./target/recurse_node_witness.gz -o ./target/recurse_node_proof + +# We finally verify that the generated recursive proof is valid. +$BACKEND write_vk -b ./target/recurse_node.json -o ./target/recurse_node_key +$BACKEND verify -p ./target/recurse_node_proof -k ./target/recurse_node_key diff --git a/noir/noir-repo/examples/recursion/recurse_leaf/Nargo.toml b/noir/noir-repo/examples/recursion/recurse_leaf/Nargo.toml new file mode 100644 index 00000000000..7af9cd74940 --- /dev/null +++ b/noir/noir-repo/examples/recursion/recurse_leaf/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "recurse_leaf" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/examples/recursion/recurse_leaf/src/main.nr b/noir/noir-repo/examples/recursion/recurse_leaf/src/main.nr new file mode 100644 index 00000000000..b6a2b49b219 --- /dev/null +++ b/noir/noir-repo/examples/recursion/recurse_leaf/src/main.nr @@ -0,0 +1,20 @@ +use dep::std; + +#[recursive] +fn main( + verification_key: [Field; 114], + public_inputs: pub [Field; 3], + key_hash: Field, + proof: [Field; 93], + num: u64 +) -> pub u64 { + // verify sum so far was computed correctly + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); + // Take output of previous proof and add another number to it. + public_inputs[2] as u64 + num +} \ No newline at end of file diff --git a/noir/noir-repo/examples/recursion/recurse_node/Nargo.toml b/noir/noir-repo/examples/recursion/recurse_node/Nargo.toml new file mode 100644 index 00000000000..db4b3b77693 --- /dev/null +++ b/noir/noir-repo/examples/recursion/recurse_node/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "recurse_node" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/examples/recursion/recurse_node/src/main.nr b/noir/noir-repo/examples/recursion/recurse_node/src/main.nr new file mode 100644 index 00000000000..7c983dcf050 --- /dev/null +++ b/noir/noir-repo/examples/recursion/recurse_node/src/main.nr @@ -0,0 +1,17 @@ +use dep::std; + +fn main( + verification_key: [Field; 114], + public_inputs: pub [Field; 4], + key_hash: Field, + proof: [Field; 109] +) -> pub u64 { + // verify sum was computed correctly + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); + public_inputs[3] as u64 +} \ No newline at end of file diff --git a/noir/noir-repo/examples/recursion/sum/Nargo.toml b/noir/noir-repo/examples/recursion/sum/Nargo.toml new file mode 100644 index 00000000000..7a5f1498c3e --- /dev/null +++ b/noir/noir-repo/examples/recursion/sum/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "sum" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/examples/recursion/sum/Prover.toml b/noir/noir-repo/examples/recursion/sum/Prover.toml new file mode 100644 index 00000000000..eae66cb8593 --- /dev/null +++ b/noir/noir-repo/examples/recursion/sum/Prover.toml @@ -0,0 +1,2 @@ +a = 1 +b = 2 \ No newline at end of file diff --git a/noir/noir-repo/examples/recursion/sum/src/main.nr b/noir/noir-repo/examples/recursion/sum/src/main.nr new file mode 100644 index 00000000000..722d941d57d --- /dev/null +++ b/noir/noir-repo/examples/recursion/sum/src/main.nr @@ -0,0 +1,4 @@ +#[recursive] +fn main(a: pub u64, b: pub u64) -> pub u64 { + a + b +} \ No newline at end of file diff --git a/noir/noir-repo/examples/recursion/test.sh b/noir/noir-repo/examples/recursion/test.sh new file mode 100755 index 00000000000..1e9eca35cab --- /dev/null +++ b/noir/noir-repo/examples/recursion/test.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -eu + +# This file is used for Noir CI and is not required. + +BACKEND=${BACKEND:-bb} + +./generate_recursive_proof.sh \ No newline at end of file