trusset-kyc-zk-proofs) up for the first time. After reading it you will have built the tool from source and produced a bundle for a sample subject. You will have verified it twice, once with your operator key and once with its root.
Nothing here is skipped. Every command below was run in this order against a clean clone, and the output shown is what it printed. One substitution: where the tool prints an em dash, these excerpts show a hyphen.
Toolchain
You need three things on the machine:
There are no prebuilt binaries. The first build compiles about 130 crates from the pinned
Cargo.lock. On the machine used for this page it took just under four minutes; after that, builds are incremental and take seconds.
Tested on macOS under Rosetta 2. Linux and Windows are untested. The key-loading step below assumes a POSIX shell.
1
Clone and build
npm install runs scripts/build.sh as a postinstall step: a release build of the Rust workspace, the WASM verifier when the wasm32 target is present, and the TypeScript CLI. The five native binaries land in target/release/: trusset-prover, trusset-verifier-cli, trusset-registry, trusset-archive, and trusset-list-commit.Every npm run command from here on re-runs that build script first, so each one prints a few [build] lines before its own output. When nothing changed, that takes about a second.2
Initialise the working tree
init asks who is legally responsible for the assertions the tool will produce. Interactively it prompts for four values. To script it, pass them as flags:.trusset/keys.env at mode 0600, adding that path to .gitignore. It writes a config.json with the batch date pinned to today and starting claim descriptors. It records version 1 of the sample allowlist in the signed registry. It checks the environment, and it prints your operator public key:input/ is reported but does not block readiness.init pins the batch date into config.json as "epochDaysSource": "fixed:<today>". Leave it pinned. Every per-subject key, nonce and leaf hash derives from that number, so a bundle proved against a moving clock cannot be reproduced tomorrow. Reproducing a bundle is exactly what an auditor asks for. The tool refuses to run unpinned unless you pass --dev-unpinned-epoch.init again on an existing tree leaves config.json and the key file untouched and says so. --force replaces both, which makes every existing bundle unreproducible.3
Load the keys
The prover reads both keys from the environment. Do this in every new shell:Back the file up where you keep other operator-private material and never commit it. Lose the master key and no existing
secrets.enc can be decrypted and no bundle can be regenerated. Lose the signing key and no future bundle can be signed under the same identity.4
Add records
Create Both country codes are in the shipped sample allowlist of 17 ISO 3166-1 alpha-3 codes, and both tiers satisfy the generated config’s
input/records.json with two subjects:minTier: PROFESSIONAL. A RETAIL record would fail that predicate and be reported, not silently downgraded. Input records has every column.5
Dry run
A dry run validates the whole batch through every stage, including the prover’s own predicate checks, reports every problem at once, and writes nothing. It needs no keys.The
-- is required: npm drops arguments that come before it. npm run hash is the same command as npm start.6
Prove
set_membership proofs. Performance has measured numbers.The wallet is printed in its EIP-55 checksummed form, and that is the bundle directory name. Use that form in the commands below.firstName, lastName, documentType and documentNumber are commitment_only leaves, which carry a hiding commitment and no STARK. Bundle format describes every file.7
Verify against your key
show prints the resolved configuration and, with the keys loaded, your operator public key. It is the key init printed.set_membership leaves which list version the proof was made against.8
Verify against the root
A counterparty who can read the Passing neither anchor is refused with exit code 1, because a bundle verified against nothing proves only its own internal consistency. Passing a wrong root fails with exit code 2. Verification explains what each anchor proves.
kycHash from the chain does not need your key at all. The root authenticates the bundle. Here the root is read from the bundle itself, which is what a chain read would return:What to do next
- Record where you published each root with
npm run anchor, so a question about a past block can be answered without chain access. Then build an archive withnpm run archive, one file that verifies on a bare machine. Both are on Registries and archives. - Review
config.json. The claim descriptorsinitwrote are starting points that name a plausible instrument and provision. They are hashed into every leaf, so they are evidence, not comments. Configuration documents every field. - Replace the sample allowlist. The 17 codes in
config/list_commitments/country_allowlist.source.txtare a sample, and recording a new version is one command.
In the repository
- README.md, the quick start section
