Chaincode source
The four contracts are one Go module, github.com/jyflix/digifir-chaincode. The module pins Go 1.27.0 with toolchain go1.27.3 and builds from the committed vendor/ directory without network access. The binding specification is docs/SPEC.md; where it is silent or ambiguous, the reading the code takes is recorded in docs/IMPLEMENTATION_NOTES.md.
Layout
| Path | What |
|---|---|
shared/ | Code compiled into all four chaincodes: canonical JSON, ES256, the action envelope, Gate 1 verification, records, keys, events, errors, pagination, policies |
identityregistry/, firregistry/, evidencecustody/, judicialactions/ | The four contracts |
cmd/<chaincode>/ | Each contract as a chaincode-as-a-service server |
deploy/<chaincode>/ | The image build context for the network's deployCC: Dockerfile, CouchDB indexes (META-INF), collections.json |
internal/testkit/ | An in-memory peer, endorsement simulator and test signer that the unit tests run on |
testvectors/ | Cross-language test vectors and their generator |
tools/analyzers/ | The seven static checks, run as a go vet tool |
integration/ | The end-to-end scenarios on the development network (its own Go module) |
Build and test
A host with an older Go passes GOTOOLCHAIN=go1.27.3 to make.
| Target | What it does |
|---|---|
make test | Unit tests with the race detector, and the analysers' own tests |
make vet, make lint, make checks | go vet; gofmt and vet of the analysers and integration modules; the seven analysers |
make vulncheck | Fails on a vulnerability the code reaches that has a fixed version |
make vectors | Checks testvectors/ against generate.py (Python 3 with cryptography) |
make build | Compiles each chaincode in golang:1.27.3-alpine with --network none into deploy/<cc>/chaincode |
make images | Builds the images digifir/cc-<cc>:$(VERSION) |
make deploy-dev | Builds and deploys the four chaincodes on the development network |
make integration | Brings the development network up if needed, deploys, and runs the scenarios |
The images run as an unprivileged user on fabric-baseos. Running make deploy-dev again with the same version and sequence rebuilds the binaries and restarts the chaincode servers; a new definition needs VERSION=<v> SEQUENCE=<n+1>.
Rules a change must keep
| Rule | Enforced by |
|---|---|
No DelState or DelPrivateData; PurgePrivateData only in the erasure function | nodelete analyser |
No time.Now outside shared/clock.go; no map-order dependence, randomness, network or goroutines; integer arithmetic only | determinism analyser |
Exactly one SetEvent per transaction, through shared/event.go | oneevent analyser |
| Rich, paginated, history and private reads only in the query functions allowed them | reads analyser |
No panic, log.Fatal or log.Panic | nopanic analyser |
Composite keys built only by shared/keys.go | keys analyser |
| Only the specification's error codes | errcodes analyser |
| Every submit function runs Gate 1 and refuses replays, bad signatures, stale and future actions, wrong creators, roles and jurisdictions | Gate 1 negative tests on every submit function |
| Every endorsing peer produces identical bytes | Determinism tests across peers |
| Go, TypeScript and Dart encode and hash identically | Shared test vectors, checked in every repository's CI |
CI also runs staticcheck, gosec, 30 seconds of fuzzing per target, and requires at least 85 % coverage per contract package. Current coverage is 86 to 98 % per package.
Tests
| Kind | Count |
|---|---|
| Unit test functions | 369 (shared 113, identity-registry 62, fir-registry 68, evidence-custody 55, judicial-actions 55, test kit and commands 16), with about 695 subtests |
| Fuzz targets | 7 |
| Golden files | 104 |
| Integration tests on the network | 19, covering the scenarios of the test report |
make integration # about 22 minutes from nothing
../digifir-network/scripts/network.sh down # remove the network afterwardsWithout DIGIFIR_INTEGRATION=1 the integration tests skip, so go test ./... inside integration/ is safe anywhere.
Changing the specification
The specification and the code change together. A change that the code reads differently from the specification is recorded in docs/IMPLEMENTATION_NOTES.md, and every change is added to the review log at the end of docs/SPEC.md. A change to an action's body or the action catalogue also needs the backend's routing table and both SDKs to follow; the backend checks its catalogue against the chaincode's in CI.
Sources: digifir-chaincode README.md, Makefile, docs/SPEC.md section 11, docs/IMPLEMENTATION_NOTES.md, tools/analyzers/.