Copied from docs/TEST-VECTORS.md at build time. Edit that file.
zx402: Test Vectors
| Field | Value |
|---|---|
| Status | v1.0, 2026-10-06 |
| Machine-readable files | vectors/poseidon-vectors.json , vectors/encoding-vectors.json , vectors/groth16-vectors.json , vectors/key-vectors.json |
| Companions | SPEC.md section 4, TEST-PLAN.md |
These are known answers. An implementation is correct only if it reproduces them. Never edit a vector to make a test pass.
1. How these vectors were made
- Poseidon vectors: computed with
poseidon-bls123811.0.2. A circom circuit built fromposeidon-bls12381-circom1.0.0 gave the same outputs. The check ran with circom 2.2.3 and snarkjs 0.7.6. - Encoding vectors: computed with vectors/encoding_vectors.py , which follows SPEC sections 4.4 and 4.5 line by line.
- Groth16 vectors: a real snarkjs proof on curve
bls12-381, converted to compressed bytes and verified with Plutus builtins in an Aiken test.
All field elements are decimal. All byte strings are lowercase hex.
r is the field prime:
r = 52435875175126190479447740508185965837690552500527637822603658699938581184513
= 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff000000012. Poseidon255
H1, H2, and H3 are poseidon1, poseidon2, and poseidon3 in the JavaScript library.
They are Poseidon255(1), Poseidon255(2), and Poseidon255(3) in circom.
| Function | Inputs | Output |
|---|---|---|
| H1 | 0 | 2811068068091031911201269074038037779542827974520177560187358960284013358662 |
| H1 | 1 | 33312903538086167554741214005086116725441315171650202128840830167854170336490 |
| H1 | 2 | 17889845856397553779318975219882180584831719213776877975727308309479382137869 |
| H1 | r - 1 | 7813170824547960260738571974704552535576767123587963859613076085894492214587 |
| H2 | 0, 0 | 51576823595707970152643159819788304363803754756066229172775779360774743019614 |
| H2 | 1, 2 | 28821147804331559602169231704816259064962739503761913593647409715501647586810 |
| H2 | 2, 1 | 38495653493229404436964394677907381793366115704270664029389503644145292560024 |
| H2 | r - 1, r - 1 | 13749015692973795093326134640289425716893530583220479127948941647063541061741 |
| H3 | 0, 0, 0 | 2730905762547441968003121309138324946079012218264271483639179080642326469387 |
| H3 | 1, 2, 3 | 41091099622722973056082071867846799679887891223501702244297781245659866568853 |
| H3 | 3, 2, 1 | 40534334082547568663372484250048352425565615075186793931897048837941546368699 |
In hex, H2(1, 2) is 0x3fb8310b0e962b75bffec5f9cfcbf3f965a7b1d2dcac8d95ccb13d434e08e5fa. Both upstream libraries assert this value in their own tests.
Warnings:
- The JavaScript library does not range-check inputs.
H1(r)equalsH1(0). Reject any value ofror more before hashing. - The library accepts
BigIntor numeric strings. A JavaScriptNumberthrows. - Other Poseidon parameter sets for this field give different values. These vectors fit this library only.
3. Zero hashes
Z[0] = 0 and Z[i+1] = H2(Z[i], Z[i]). The empty tree root is Z[32].
| i | Z[i] |
|---|---|
| 0 | 0 |
| 1 | 51576823595707970152643159819788304363803754756066229172775779360774743019614 |
| 2 | 33646187916922823865935622258451714952164674255482660942215703235411158105736 |
| 3 | 27818645450144846908742692719385898720249207574255739267233226464286012246073 |
| 4 | 39404029000907277292464556408734412130261913210564395069696342233560511006152 |
| 5 | 24907123534309659921713005795092724527532698077589223246276579583330771465031 |
| 6 | 22103361713848256938655449390262013863291224679776344310249539314760174194771 |
| 7 | 28665358770471415124367990738618755861132249577405347373337125991381323369983 |
| 8 | 6786998243528185650306462855937293964443624194496859265310261299800128548513 |
| 9 | 50997336463747555660384185705133244552288600683323691317203235239320942865561 |
| 10 | 13916937046501108967048154641689659101970478684843793251827738918983778486795 |
| 11 | 18687330317699879820441947090357020131335081966987817560646762002601404312692 |
| 12 | 5829984778942235508054786484586420582947187778500268001993713384889194068958 |
| 13 | 50753373693280024567332706650665895696517500665837690627852645244127601005954 |
| 14 | 1121944223990168834607757664588750855677305893915654403458231958042499198410 |
| 15 | 36305469446279205776473409399606075705498404819785351200416937243175517105400 |
| 16 | 35469255857533658984001872129259281494468859278269474829072253610856427637368 |
| 17 | 25002462511210597541252327993404833104943873248749427570203455562220619092990 |
| 18 | 10886081007110941254401730551833799559046107841056410372886204429067753525173 |
| 19 | 42912979393075378276322569383190765808963985610018715455225906661987202405442 |
| 20 | 17829666917206563427639071038301760428441910791113344915950879171718159851699 |
| 21 | 19959276178289919454624964033156874212383627630834686313695346050977724605069 |
| 22 | 23989753422250835433889368180384720833918212448397225750725913542081009371602 |
| 23 | 30676787872348478191822243338725486111070704489819315495569589143785123050098 |
| 24 | 25400627233432738585719544580033466956420584769957678836609603389338933363270 |
| 25 | 24790024100310572264101231265718453471525549456629575928571511811696933715746 |
| 26 | 32075852797240796685207471461798732683947259283520477880592601361588212812696 |
| 27 | 32906066193481495156743794651229831300236677336460633963901602814611572398900 |
| 28 | 46119376166408719345098363576995150680035627711276296907869001149951372314881 |
| 29 | 35770383075372255535430626119192220757841143930722388143862437791520728066325 |
| 30 | 17652037977464836264079014691140456808166939095961837218105254669963832997725 |
| 31 | 24234508768808309317912829799845407853080987152375512095526136856005911796628 |
| 32 | 34147729537948564452788589313828361831422685361580832702235439851958634889397 |
4. Note example
| Field | Value |
|---|---|
nullifier | 11 |
secret | 22 |
value | 5000000 |
label | 33 |
precommitment = H2(nullifier, secret) | 7804547571376060123316069248076895932850031953822444106594559586999678602896 |
commitment = H3(value, label, precommitment) | 25774960505238821075274772195585739030769339872205046610252935787521405310031 |
nullifierHash = H1(nullifier) | 39931036134437929071662103397633869899593947182626814510062446930794907636202 |
5. Tree examples
The tree has depth 32. A node is H2(left, right). The empty leaf is 0.
Bit i of the leaf index, counted from the least significant bit, is 1 when the node is the right child at level i.
Example 1. The note above is the only leaf, at index 0. Its siblings are Z[0] to Z[31].
root = 41575667297252774047664012125459209856646049272089381757727633024565983987862Example 2. A second note is appended at index 1.
| Field | Value |
|---|---|
nullifier | 12 |
secret | 23 |
value | 7000000 |
label | 34 |
precommitment | 24266778378722671668954724274878920486911690898706740720066518505283479047324 |
commitment | 29348268626606385949476924076909126625122473558957859785832003957964309116132 |
nullifierHash | 1401985395294375214774884236543700766810734519981862875374688073007963619144 |
root = 1340925349014447301927427273926538909429425436400238753938505309885490857044For index 1, the path bits are 1 at level 0 and 0 at every other level.
The siblings are the first commitment at level 0, then Z[1] to Z[31].
6. Label vectors
Rule: SPEC section 4.4.
label_1
pool_id = 11111111111111111111111111111111111111111111111111111111
deposit_tx_id = 2222222222222222222222222222222222222222222222222222222222222222
output_index = 1
refund_key_hash = 33333333333333333333333333333333333333333333333333333333
label_preimage = 7a783430322f6c6162656c2f76311111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222220000000133333333333333333333333333333333333333333333333333333333
blake2b_256 = 811f2d8bc79ace00d71801918f4ef4e7a3c951ac18e55b0ae487d4cf1279655c
label = 228138453411283262991000831398678695771983281117198721375515711136284703077label_2
pool_id = 11111111111111111111111111111111111111111111111111111111
deposit_tx_id = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
output_index = 0
refund_key_hash = 6465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f
label_preimage = 7a783430322f6c6162656c2f763111111111111111111111111111111111111111111111111111111111000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f000000006465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f
blake2b_256 = d4bae02984c5fd4b4a31edcf42d3e757e45c4c8696c05eb967e4a7c2ec1854e9
label = 3758613459539977300294395896307793699567950224691634352163306347222424679247. Context vectors
Rule: SPEC section 4.5. Both use pool_id = 11111111111111111111111111111111111111111111111111111111.
context_1. One payout: key credential 44 repeated 28 times, no stake credential, amount 5,000,000, no datum hash. No relayer. valid_until = 1790000000000.
intent_bytes = 7a783430322f696e74656e742f7631111111111111111111111111111111111111111111111111111111110100444444444444444444444444444444444444444444444444444444440000000000004c4b400000000001a0c4506c00
blake2b_256 = c82426fff0d2d13310e82344746a10cf6472eb3d71180d1ba0c5c98dcb657798
context = 353618927255838097014367112914778006164571628135081790697632992728971961719context_2. Two payouts and a relayer. valid_until = 1790000600000.
| Payout | Payment credential | Stake credential | Amount | Datum hash |
|---|---|---|---|---|
| 1 | script, 55 repeated 28 times | inline key, 66 repeated 28 times | 12,345,678 | 77 repeated 32 times |
| 2 | key, 44 repeated 28 times | none | 1,000,000 | none |
The relayer key hash is 88 repeated 28 times.
intent_bytes = 7a783430322f696e74656e742f7631111111111111111111111111111111111111111111111111111111110201555555555555555555555555555555555555555555555555555555550100666666666666666666666666666666666666666666666666666666660000000000bc614e01777777777777777777777777777777777777777777777777777777777777777700444444444444444444444444444444444444444444444444444444440000000000000f4240000188888888888888888888888888888888888888888888888888888888000001a0c45993c0
blake2b_256 = b8ed36856044de15f8293453601f1f0681144d0f5a02da54788ecac6df87a1ce
context = 3267370436866696735315949313211750449142600459324644401623300108496026684498. Nullifier key vectors
The key in the nullifier set is the nullifier hash as 32 big-endian bytes.
| Nullifier hash | Key |
|---|---|
123456789012345678901234567890 | 00000000000000000000000000000000000000018ee90ff6c373e0ee4e3f0ad2 |
52435875175126190479447740508185965837690552500527637822603658699938581184512 | 73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000 |
9. Groth16 proof and key vectors
Circuit: d <== a * b + c, with a and b private and c public. The public signals are [d, c].
The key comes from a throwaway development setup. Never use it for anything but this test.
The verification key in compressed bytes (48 bytes for G1, 96 bytes for G2):
alpha_g1 = 91d2818338afc909d485a8d59597eba6fbdab091bd686ef52005e569d256e8fd3077c509e226bd16ea1764f67d0fd999
beta_g2 = 86425dbce28f2bbe8b7fdf5d7b9eaa8f435155643d505a68803d11d92bde56e3df9d3ef3d27f49b23468d74ca60909fa190a478692ae34909355ddf92a83109f900b1384c617b7fe22e9a5debeb88805545bc0660a3a6ab078b0e2b7794f5b9d
gamma_g2 = 93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8
delta_g2 = 8ab01564d7dc3d4b20872f68a9cfb0f4c4113d400771554cebda3525daefde95ed8b19eef544a5e0b93fec0c20e7f0f8146ae94f8a70dc48b676208a4fba786fbe43cbeb1ffa20649dfd09b3c0b850a08123ffdc17ee7be89696835f03485601
ic[0] = a8bc06cac776073ae33eecef4e6719a88dada0cbbf00c22ebcbda61d4d8811e749792e053651f7d0ea5ef3b80234b07d
ic[1] = 97f780c0ddc2cb146123b6d1a5e9c5bd21dd385610feb41dd0079cfbaa261f37e6fad1786938b42e8accc0ce3e01b91c
ic[2] = 99f1e0e23f9693023bb97bc1bb7461f0739cc5dd02d0bf48ea62fcec61957f82e47f85b46f05752f1958ee47e6554d01Proof 1. Inputs a = 3, b = 4, c = 5. Public signals [17, 5].
a = 840679528d4326d7cc856bf3d6fc7ebadd18a5aa6b1a233e93a06dc7a8edefc059e8d775872d5f29f5159aea169fc4c8
b = 97c5a1af533150935877339f5d0376ad86bfb37f3e3f6ddc9d74b440eeff7f0ffb04e56a3b04d8ae5b2d24247828dcdc0fad6f141c7d684778caca6f0af760da0193024af930d31708d799bff19ed8129b32fe58f1eb254a0dd6d3c2e67bc86f
c = b0ca2896c7e9adaafb40259a20d4a8fba7859693491e421d89831f63535cd00316984737c61d4b43cf061cef5a9410b2Proof 2. Inputs a = 6, b = 7, c = 0. Public signals [42, 0].
a = 90f19e65a20af7555aa37299913cd9d060b53014a112c208b7374d1a3502d2473e4e2ad7a9c7597f9d7a6fadb1f61145
b = a3fd291b3e6f9d7b722e1ad37019e804cbbd822c7741976959f8e19fa0fbe90f598cb7bc65378ac89ede18a89c9785e6078b203f075ddfeb8123133de9a8294d92f929d505ef10be7caf482d91cac0859cefbca4c07b61c498507d2cf52cb64b
c = 8dda982b272c2275d3ec3dd0692dc9a3162bdeabce09369f24820b980f87d8dd32c4634b61dd0ad5c9532c740528d133The JSON file also holds the original snarkjs proof and key. Use them as input when you test proofToCardano and vkToCardano.
Expected results, all measured in an Aiken 1.1.24 test on 2026-10-06:
| Case | Result |
|---|---|
Proof 1 with signals [17, 5] | Valid |
Proof 2 with signals [42, 0] | Valid. The zero input is skipped |
Proof 1 with signals [18, 5] | Invalid |
Proof 1 with its c replaced by its a | Invalid |
Proof 1 with signals [17 + r, 5] and the range check | Invalid |
Proof 1 with signals [17 + r, 5] and no range check | Valid. This is the attack that rule V1 stops |
Conversion rules that these vectors pin down:
- snarkjs writes plain decimal coordinates, not Montgomery form.
- snarkjs writes each G2 coordinate as
[c0, c1]. The compressed bytes holdc1first, thenc0. - The first byte carries three flags:
0x80for compressed,0x40for infinity,0x20whenyis the larger root. - snarkjs sets
gamma_g2to the G2 generator.
10. Key derivation vectors
Rule: SPEC section 4.7. HKDF-SHA256 with an empty salt. The input key is the 32-byte seed.
The info strings are zx402/nullifier/v1/, zx402/secret/v1/, and zx402/onetime/v1/, each followed by the decimal index.
A nullifier or a secret is 64 bytes of output, read as a big-endian integer, reduced modulo r.
A one-time key is 32 bytes of output, used as an Ed25519 seed.
These values come from vectors/key_vectors.py , which uses only the Python standard library. Its HKDF routine reproduces test case 3 of RFC 5869.
| Seed | Index | Nullifier | Secret | One-time key |
|---|---|---|---|---|
00 01 .. 1f | 0 | 6392169606537001630664487786370543086421165969781915050253684248971553975133 | 45058049200327044039904574757438738825783775994281982784300651022677201309403 | ebe4f4443ed9f47f48e91927b44837e6f4de02009402b2b593fa41e65ff661c2 |
00 01 .. 1f | 1 | 8243662026203720316401175583416470713834081104790870158835823596313638905945 | 4367966839093052913230936107324283643092463070581325287880640661918934745348 | 1e7e7d932557584aea54f6cf0c0321f7d0df9a108bc6907516ecbe1c2fac4345 |
00 01 .. 1f | 7 | 29150221156029212952568887808142255350148583046946671573851965219334960650960 | 45950479737837808962831675520420509610740929869374616149012420134706413843027 | 19bb5110b3b717361763a9499372065e2ddaf14a6fef7fcbd425bcb6cd8c273c |
00 01 .. 1f | 1000000 | 15679876640936791816373436726626857393043590143310752614165817506816653026357 | 287299233994415351281658498432165946390675491719532547353390041738972436184 | c4d4a7b44fb125bcaa2a935abb01c3db8352bc293988384ceede208742f1ff4c |
ff repeated 32 times | 0 | 15620797452332961444108882041567924155414725334022325873657319847899122466455 | 51130867585472255326539025569510170132666544056980087963162129562051798101057 | fff18aa63656792f45173dde2fd0fb4a4da087847e621ade182325d8a45bcdd0 |
ff repeated 32 times | 1 | 2989192437253411145246814522697187195712126560801973847755424167077598391963 | 35997152803269655276675941094109444526685933353695601829342905094979971715997 | 4586071dc7f24e2386a7cc4c871585e8c0e2b605fcacd08a5088a57ee16e81ef |
ff repeated 32 times | 7 | 5731142636468778404836199220476338158305090467549899149756516919199798132411 | 24510126533629832186754154277129799566046453028976872154617616292341141955811 | 04b64135e1977b81df45a5a82e5b411bc5069299bd1c9956f9e934397da9c943 |
ff repeated 32 times | 1000000 | 30221801572498562728106651924518256639745206337156606979818696131680487035751 | 8511966141615212697416588305076989897917931317827227739181830424916588458140 | 750b7e3132f5be957ae87d5386392c168b8769cc672feda3ba0b579f879e0a0e |