Closed tomoima525 closed 1 year ago
@critesjosh could you help boil the example code down into a minimally reproducible example?
Suspecting constraint count might not be the actual underlying reason here. Would be good to verify that.
Installing the latest noir nightly generates a new, different Solidity verifier contract for the same noir program. in order to verify the same program, I have to generate a new proof using this version (proofs generated with the stable 0.9.0 release dont work).
additionally, it seems like this new verifier contract is not compatible with proofs generated with the latest version of bb.js (0.3.6). Hopefully resolving this will fix the issue
Updated the solidity file with Noir 0.10.3 but the result was the same
Assertion 1 & 2 => Succeeds Assertion 3 only => Succeeds Assertion 1 & 2 & 3 => Fails
I tested other patterns.
Assertion 1 & 3 => Fails Assertion 2 & 3 => Fails
So when the merkle root check is combined with other assertions, it fails... 🤔
Some interesting experiments:
I changed my noir circuit a bit and saw how many circuit sizes could cause this issue.
Experiment 1: Assertion 1 3 = 7225 3 = 21675 circuit size Result: PASS (Solidity works)
Experiment 2: Assersion 1 3 + Custom assertion = 7225 3 + 361 = 22036 circuit size
for i in 0..90 {
assert(age == 18);
}
Result: PASS
Experiment 3: Assertion 2 + Assertion 3 = 22092 circuit size Result: FAIL
Experiment 4: Assertion 1 3 + Assertion 2 = 7225 3 + 2776 = 24451 circuit size Result: FAIL
If the circuit size passes the value between 22036 and 22092 Solidity file starts to fail.
did you try any circuits above 22092 with different logic? or just modifications of your circuit?
Just modifications
In trying to replicate this error, I wrote my own circuit of varying sizes.
I wrote this circuit
fn main(x : u52) {
let mut z = x;
for i in 0..5000{
z = z + 1;
assert(z > x);
}
}
nargo info
prints
+-------------+------------------------+--------------+----------------------+
| Package | Language | ACIR Opcodes | Backend Circuit Size |
+-------------+------------------------+--------------+----------------------+
| noirstarter | PLONKCSat { width: 3 } | 50001 | 65413 |
+-------------+------------------------+--------------+----------------------+
proving and verify works with nargo.
Verifying fails when building the solidity verifier, deploying to anvil, and running in the browser. This is the error:
RuntimeError: null function or function signature mismatch
at std::__2::shared_ptr<proof_system::plonk::proving_key> proof_system::plonk::initialize_proving_key<proof_system::UltraCircuitBuilder_<barretenberg::field<barretenberg::Bn254FrParams>>>(proof_system::UltraCircuitBuilder_<barretenberg::field<barretenberg::Bn254FrParams>> const&, barretenberg::srs::factories::CrsFactory<curve::BN254>*, unsigned long, unsigned long, proof_system::CircuitType) (02646f1a)
at proof_system::plonk::UltraComposer::compute_proving_key(proof_system::UltraCircuitBuilder_<barretenberg::field<barretenberg::Bn254FrParams>>&) (02646f1a)
at proof_system::plonk::UltraComposer::compute_verification_key(proof_system::UltraCircuitBuilder_<barretenberg::field<barretenberg::Bn254FrParams>>&) (02646f1a)
at acir_proofs::AcirComposer::verify_proof(std::__2::vector<unsigned char, std::__2::allocator<unsigned char>> const&, bool) (02646f1a)
at acir_verify_proof (02646f1a)
at BarretenbergWasm.call (432.60f9453cd29313c1.js:189:40)
at callback (432.60f9453cd29313c1.js:359:48)
I created this branch on the noir-starter so anyone can replicate.
@Savio-Sou do you know if this issue being tracked elsewhere?
After modifying the web component, I was able to get a circuit of size 65413 verified on chain. The verification using bb.js is what is failing in the error i describe above.
So I don't think the size is what is causing your circuit verification to fail on-chain. Here is the code that is working for me.
@Savio-Sou do you know if this issue being tracked elsewhere?
This is the best tracking issue atm afaik.
The verification using bb.js is what is failing in the error i describe above.
Not sure if I follow if this is a Solidity verifier bug or a bb.js verification bug, but either way that means this is more likely a barretenberg problem.
@critesjosh would you like to start an Issue on https://github.com/AztecProtocol/aztec-packages/issues with your latest findings (cc @rahul-kothari).
If it turns out to be Solidity verifier specific, we can also source help from @LHerskind.
Solidity verifier is working fine, its just bb.js.
I created an issue here https://github.com/AztecProtocol/aztec-packages/issues/1845
Thanks for the update @critesjosh !
I tried the above circuit on ts-node using https://github.com/tomoima525/noir-starter/pull/1 but it failed with the same error. Do you know any difference between the ts-node version and the browser version? I think it's okay as long as it works on the browser but the inconsistency between platforms can become a big issue later on
I changed the code like this and the verifier contract is working now. So yeah I guess it's not related to the circuit size ... 🤔
fn main(x : pub u32) {
let mut z = x;
for i in 0..5000{
z = z + 1;
assert(z > x);
}
}
Here is the code that is working for me.
Also I wonder how the circuit worked as it doesn't provide public inputs in the circuit, but in this code, you provided the first 32bits of the public inputs which I believe should fail?
Let's hope that bb.js update will resolve the issue with my original circuit 🙏
Hello @tomoima525 I stumbled on a very similar issue, I also thought at first that this was caused by bb.js
but I am not sure anymore. I noticed that the verifier smart contract code (for a same fixed circuit) changed between nargo 0.10.3
and nargo 0.10.5
and unexpectedly, as I thought this was a problem in bb.js
, upgrading to nargo 0.10.5
solved this very same issue. See similar issue
I noticed that the verifier smart contract code (for a same fixed circuit) changed between
nargo 0.10.3
andnargo 0.10.5
Do you have the verifier code lying around for this, I don't think much should have changed on those in months so would be interested in seeing the diff if other than just vk.
I noticed that the verifier smart contract code (for a same fixed circuit) changed between
nargo 0.10.3
andnargo 0.10.5
Do you have the verifier code lying around for this, I don't think much should have changed on those in months so would be interested in seeing the diff if other than just vk.
I just pushed it on a new branch here : https://github.com/jat9292/bbjs-bug-minimal-example/tree/compare-nargo-10-3-vs-10-5/contract/bbjs you can see both versions, one generated via nargo 0.10.3
and the other with nargo 0.10.5
Output of the diff :
1c1
< // Verification Key Hash: 56c0033c7b88d37f038f03eed5ece7197e6c56da0c770906b5ca146219f4e362
---
> // Verification Key Hash: 2b951f2ad8c30e9c6fd1df64cf0c26a662589d7c8cd9cfa5066de177b8dddd99
8c8
< return 0x56c0033c7b88d37f038f03eed5ece7197e6c56da0c770906b5ca146219f4e362;
---
> return 0x2b951f2ad8c30e9c6fd1df64cf0c26a662589d7c8cd9cfa5066de177b8dddd99;
17,32c17,32
< mstore(add(_vk, 0x80), 0x058d2d96844efd71d1ea79dc01cf5794bfa80a7666be31f8f3b504eb0f9c1b9e) // vk.Q1.x
< mstore(add(_vk, 0xa0), 0x21522d2c085a459b9fa71435489397f907f75252e400c9a3a975b2074558e382) // vk.Q1.y
< mstore(add(_vk, 0xc0), 0x26ae7d13e55a1917f7aca910c36e48e15c3c35879f351a3fc001de83603994b4) // vk.Q2.x
< mstore(add(_vk, 0xe0), 0x10bfa8463b6359772e9d1918c28f37146e05125f522a3751eb490351c4bdd1b0) // vk.Q2.y
< mstore(add(_vk, 0x100), 0x27ffe3fa9dc1949a99b4619ae2026266213829ebbeaa026dc2055d1a99322d36) // vk.Q3.x
< mstore(add(_vk, 0x120), 0x0a125f3e228005f1944ce6c3bf014bfaa5b3463614534d4d8cc4cbf5236a0429) // vk.Q3.y
< mstore(add(_vk, 0x140), 0x1998e4bbdb2bfc7e4a1d41dd70d44543385bcccf1e8779176ff0322d88a04398) // vk.Q4.x
< mstore(add(_vk, 0x160), 0x28701822301d544f74c69f01ef1bd3812dda8505172bad4ea0588c8d26a94e74) // vk.Q4.y
< mstore(add(_vk, 0x180), 0x2911326f874fd6f495eff81c9d2b9c98097fd27da0fb8e66135ec73f6d987b4f) // vk.Q_M.x
< mstore(add(_vk, 0x1a0), 0x0fe7e7c1012c7dc6c5bb1d5e0166110064cf2ac98eb5ab3a0d27b47b3daa2c33) // vk.Q_M.y
< mstore(add(_vk, 0x1c0), 0x01991a8a75f79b9a8ade5d6d7220732e287893ff974ba903d1e5f085909ab3f0) // vk.Q_C.x
< mstore(add(_vk, 0x1e0), 0x2a54ef87c8dc13619f43381f9b7be2f177019e7c403ad3a156f1ce50de1b5c08) // vk.Q_C.y
< mstore(add(_vk, 0x200), 0x06957128f5ef3e69a11aadb549f5c5184fb6cf8c127c29a746603784d74597d8) // vk.Q_ARITHMETIC.x
< mstore(add(_vk, 0x220), 0x076af2ef4420a18f36f5239ba998419484505032ce532e3fb6ecf6b2f32b2aaf) // vk.Q_ARITHMETIC.y
< mstore(add(_vk, 0x240), 0x02051bb8f4b013b3a885871e9dd0fe11a26004e5463e906d863c8a2ca27c256e) // vk.QSORT.x
< mstore(add(_vk, 0x260), 0x1211d58150ea2fc83d924b60eb7df99321071620bd1e6ab422f671fa5f38af51) // vk.QSORT.y
---
> mstore(add(_vk, 0x80), 0x0fe0cf1b541c14fc5349c8c822d4c7b5e872dec36ce9c752d08fc784e92df9af) // vk.Q1.x
> mstore(add(_vk, 0xa0), 0x2b10d6a43ae32cb93ef903f8c2162db59ab562c41173e37b88b6ad4e5327fd21) // vk.Q1.y
> mstore(add(_vk, 0xc0), 0x0221404bff9920f6f6b3cb8da1583fab51db8600f08f0c6070f4f697e9c19f48) // vk.Q2.x
> mstore(add(_vk, 0xe0), 0x2dde1ab639bd4feeb8caae1e136aec34545be591181bb27506e98e90a4cd0cf7) // vk.Q2.y
> mstore(add(_vk, 0x100), 0x16f8b651166eba8bfca6f8fe9567af685321f54bcf975c1ac7d343861126cdaf) // vk.Q3.x
> mstore(add(_vk, 0x120), 0x1f376c5475d7c9fc0a70bde6ac0d03dc52b10e9872e7f40725a1852962a7dee6) // vk.Q3.y
> mstore(add(_vk, 0x140), 0x2cfd195398c36559e8a8a9cc66fcaa66a324360f1a426f40f4616e64b3c3c4cf) // vk.Q4.x
> mstore(add(_vk, 0x160), 0x0f501ba520a88956d9b194d94b75d359c08191cebdf44dd835bf7c0b5ea5e0d6) // vk.Q4.y
> mstore(add(_vk, 0x180), 0x1f99ab321383bab6bcd6066e1d4a7b95459d2747117405e196ccaebcba1baf91) // vk.Q_M.x
> mstore(add(_vk, 0x1a0), 0x0d7d83510f2b89a66cddb5443badfd9edc0e50d1edf99b7fa6fb114cd078a3b0) // vk.Q_M.y
> mstore(add(_vk, 0x1c0), 0x0a2c5ca9d72218a88ba274ee2ebe5e3ee2f09cd909c2db7f171b5438a888c667) // vk.Q_C.x
> mstore(add(_vk, 0x1e0), 0x218c5c7b9b1cf92825bcb2cac55d93688393d549b69c5d59708c63007915dc76) // vk.Q_C.y
> mstore(add(_vk, 0x200), 0x1c9a04bb37dfffa6cf5416dcaae3ae6480cfe936b454c02bbbb2dbff0136cee2) // vk.Q_ARITHMETIC.x
> mstore(add(_vk, 0x220), 0x2bb51262ccf024b2177b780d29f951d1180eb509504fad9d08da2c0e276d06e9) // vk.Q_ARITHMETIC.y
> mstore(add(_vk, 0x240), 0x2bdd55cdf544f4551ae8989c4eae79d8f0c9a06c1f2004441c85d95224b8cd6e) // vk.QSORT.x
> mstore(add(_vk, 0x260), 0x026f3f477fd783ce6d5881c40de0f94021667d13497483023739942384115e33) // vk.QSORT.y
37,44c37,44
< mstore(add(_vk, 0x300), 0x2a5fb4aca0d954dd8def70e6c829c0f5be3cbb710b97a5dd24d773589e57ee2d) // vk.SIGMA1.x
< mstore(add(_vk, 0x320), 0x05ce27117bcb0139d51b9c0dcfa707fd36933f87478aaba14e5f5f1df9870e9f) // vk.SIGMA1.y
< mstore(add(_vk, 0x340), 0x09bb09e35142de5d4c9b8c9581b3431dbeefbd4e85baea07e2070ed3d4f1970b) // vk.SIGMA2.x
< mstore(add(_vk, 0x360), 0x2015a519f73e3d74d2d3c60f5ebb721ccd1c42a860806f6886af681b257637b9) // vk.SIGMA2.y
< mstore(add(_vk, 0x380), 0x0edbf7a493e782fbbb7d9e4377cad4206016e327d1ca7ceba9a1b1165e069f72) // vk.SIGMA3.x
< mstore(add(_vk, 0x3a0), 0x234593aeb40273c0c5d0cf8c65b38392b5b8efaa2685963d6b901b79ed2dc2c8) // vk.SIGMA3.y
< mstore(add(_vk, 0x3c0), 0x1805e0d3fa123cb706690c421a1557cd72c48463590a2dc0e63656f1bdf26106) // vk.SIGMA4.x
< mstore(add(_vk, 0x3e0), 0x0a3e5dbd9c627ff26f91d2aff915dd2832c16ea3456527edf6c912a0f9a0edcc) // vk.SIGMA4.y
---
> mstore(add(_vk, 0x300), 0x0468df4907d56f150ae8d8008841bca19acca9669e2af225fb92874f5da29230) // vk.SIGMA1.x
> mstore(add(_vk, 0x320), 0x200b5ebe358975ba33dcc1b4cbf186fdff23b1a88cabca21258a5332361e54c9) // vk.SIGMA1.y
> mstore(add(_vk, 0x340), 0x0ab414db5b312392f89c89372d6a98e674cb0daaa467a2749456b83f8385b7ea) // vk.SIGMA2.x
> mstore(add(_vk, 0x360), 0x231bb22c3fd064230b06a3b16088ec29d4da4d913c140cc2a0a69c534cd0ecd8) // vk.SIGMA2.y
> mstore(add(_vk, 0x380), 0x00636bbca64afea046eb7954008fe140ad9d0a061cf560c09699cb508dcb4145) // vk.SIGMA3.x
> mstore(add(_vk, 0x3a0), 0x07f6e3a33bfba310d75dfbc498e6745ed75e59a00656b99172835bda96d05ee6) // vk.SIGMA3.y
> mstore(add(_vk, 0x3c0), 0x2b60590dd8d5eac39051f83bff9b5c4d4c7093609a724b4c9f398f89a99f4510) // vk.SIGMA4.x
> mstore(add(_vk, 0x3e0), 0x15f170f7f028ff73fdc73022ca685f967b13d450128ddc5a62ec0c0926bcf472) // vk.SIGMA4.y
55,62c55,62
< mstore(add(_vk, 0x540), 0x030bdc5ddd5d329c901a2249effa8866f5b4c6f06e7b9e213e4c7e3851c0090a) // vk.ID1.x
< mstore(add(_vk, 0x560), 0x22297c47e82c9ea7e1ec9374969337556968244c17223441dfe8753c1f83930e) // vk.ID1.y
< mstore(add(_vk, 0x580), 0x2f194668067fda5f01e74870f2474082e65796799a6d1f45557c9a5fd3f2df31) // vk.ID2.x
< mstore(add(_vk, 0x5a0), 0x2c7716dfdd83ab421cb94504eac9467738401b718aea745f910e96b5ad3212bf) // vk.ID2.y
< mstore(add(_vk, 0x5c0), 0x0567f0d5420bacfa17b34998ddff21d91d4539e53ba2c9c7a3f6b071e88c3585) // vk.ID3.x
< mstore(add(_vk, 0x5e0), 0x2f5471417429570f6268565f2733bce5dd900a4a7962d54412c632727aa1edb8) // vk.ID3.y
< mstore(add(_vk, 0x600), 0x1853b45ca80f3abf163f764d5bfc2ed297b4ecd53a4abed3f018fd944d70acef) // vk.ID4.x
< mstore(add(_vk, 0x620), 0x1b06a4b9eb80f545d5f4b6491787ff10e27e674a3dae2a91faa286932347653e) // vk.ID4.y
---
> mstore(add(_vk, 0x540), 0x02536b4e5b114885afc7a7548e53f8346671257b7c1d1855f4fdbdf5aed3b1b2) // vk.ID1.x
> mstore(add(_vk, 0x560), 0x10adfe7f93b3b1e067bef6f26b2751325d62c64f36b6f20ec48588ec4abce80b) // vk.ID1.y
> mstore(add(_vk, 0x580), 0x13bf791ca08dc98dff61eb9cdaac4c60a75f2edf0c11591bb6f5cdfab93d7fe2) // vk.ID2.x
> mstore(add(_vk, 0x5a0), 0x1d03866028d293ebb9ae096d6d08d89a0ec5c8c4182314a8bb41cf25515cc098) // vk.ID2.y
> mstore(add(_vk, 0x5c0), 0x0793018304f71b55dfbd2b3c87b2e5449c824045add3e943e03e81a2f64a2f26) // vk.ID3.x
> mstore(add(_vk, 0x5e0), 0x0b21b74df7b13754d38662b7295a7b5296b613b3c6ec85e211d951e3429a31fa) // vk.ID3.y
> mstore(add(_vk, 0x600), 0x0209afacf58ea1f4b626d4a2eff2298d3042c727fac5fd6cec724ba0aecc522a) // vk.ID4.x
> mstore(add(_vk, 0x620), 0x2f94cb9eaee45486acdbbfe36c28ef26438c4abba89b8408034c7cd676a215a8) // vk.ID4.y
I just pushed it on a new branch here
Ah cool. Its only the vk differing (which is based on the circuit and output from bb), so with the same circuit if that one is different that is due to noir compiler updates or bb, so makes sense if the issue came from bb.js
@jat9292 this is awesome!
I updated Noir 0.10.5 then I see this error when calling api.acirGetCircuitSizes
from barretenberg API (0.3.6). Did you change bb.js or any other related library version?
file:///Users/tomoima525/workspace/zkp/noir-starter/with-foundry/node_modules/.pnpm/@aztec+bb.js@0.3.6/node_modules/@aztec/bb.js/dest/node/barretenberg_wasm/barretenberg_wasm.js:169
return this.exports()[name](...args) >>> 0;
^
Error [RuntimeError]: unreachable
at abort (wasm://wasm/02646f1a:wasm-function[11571]:0x422819)
at throw_or_abort(std::__2::basic_string<char, std::__2::char_traits<char>, std::__2::allocator<char>> const&) (wasm://wasm/02646f1a:wasm-function[94]:0x380e6)
at Circuit::Circuit::bincodeDeserialize(std::__2::vector<unsigned char, std::__2::allocator<unsigned char>>) (wasm://wasm/02646f1a:wasm-function[2213]:0x12774b)
at acir_format::circuit_buf_to_acir_format(std::__2::vector<unsigned char, std::__2::allocator<unsigned char>> const&) (wasm://wasm/02646f1a:wasm-function[2212]:0x12746a)
at acir_get_circuit_sizes (wasm://wasm/02646f1a:wasm-function[2251]:0x12835f)
at BarretenbergWasm.call (file:///Users/tomoima525/workspace/zkp/noir-starter/with-foundry/node_modules/.pnpm/@aztec+bb.js@0.3.6/node_modules/@aztec/bb.js/dest/node/barretenberg_wasm/barretenberg_wasm.js:169:40)
at callback (/Users/tomoima525/workspace/zkp/noir-starter/with-foundry/node_modules/.pnpm/comlink@4.4.1/node_modules/comlink/dist/umd/comlink.js:109:52)
at MessagePort.l (file:///Users/tomoima525/workspace/zkp/noir-starter/with-foundry/node_modules/.pnpm/@aztec+bb.js@0.3.6/node_modules/@aztec/bb.js/dest/node/barretenberg_wasm/node/node_endpoint.js:11:21)
at [nodejs.internal.kHybridDispatch] (node:internal/event_target:737:20)
at exports.emitMessage (node:internal/per_context/messageport:23:28)
I am able to use acirGetCircuitSizes
without any issue for my circuits : https://github.com/jat9292/Private-token/blob/main/utils/proof_utils.js#L33
I am using @aztec/bb.js 0.3.6
and @noir-lang/acvm_jsgit+https://git@github.com/noir-lang/acvm-simulator-wasm.git#b9d9ca9dfc5140839f23998d9466307215607c42 , as per documentation
Btw here is my most complex circuit : https://github.com/jat9292/Private-token/blob/main/circuits/transfer/src/main.nr
I noticed it had 24 (Gaffine=2 Fields) inputs among which 20 are public, while yours had a total of 28 inputs but only 4 of which were public, so I do not now if this explains some added complexity which could explain the bug (?)
Was able to resolve import issue by adding @ts-ignore
And successfully verify the contract onchain with 0.10.5
Referencing the update https://github.com/knot-inc/noxx-contract/pull/40#issuecomment-1710512956
Aim
api.acirVerifyProof
from bb.js, on-chain verification failsExpected Behavior
Bug
Command and Error message
To Reproduce
You can find the reproducible code in https://github.com/tomoima525/noir-starter/pull/1
Installation Method
Binary
Nargo Version
nargo 0.9.0 (git version hash: 3d1b2522c8d9a0acebff102f9f877c44178c5db5, is dirty: false)
Additional Context
I see that when the number of gates hits a certain amount, on-chain(Solidity) verification fails
We have three assertions in the circuit.
I tested the patterns below and found that on-chain verification fails when everything is checked at once
This is the number of gates in each assertion.
Would you like to submit a PR for this Issue?
No
Support Needs
Just pinging @critesjosh as we've been discussing this issue