Nacatgunma is an experimental blockchain that supports fluid consensus.
- The blockchain is a DAG (directed acyclic graph), potentially with multiple tips.
- Anyone can extend the chain by signing a new block that references one or more parents.
- Anyone can ignore the tips they do not like.
- The block bodies are arbitrary and may be encrypted.
- Because the creator of a block signs the block, the contents of that block are implicitly reified in that they include provenance about the creator and the time of creation.
- Consortia of parties can collaborate on building a tip because they partially trust each other and can consider the reification in their individual trust models.
When used with blocks consisting of RDF (resource description framework) quads, this creates a provable, forkable, trust-aware semantic web, where:
- History is preserved.
- Trust is local.
- Forks are first-class citizens.
- Knowledge evolves socially, not algorithmically.
- Machine-readable graphs allow reasoning, merging, and analysis beyond human curation.
The combination of signed RDF graphs + DAG tips + subjective tip choice constitutes a model embraces partial trust and subjectivity rather than forcing global consensus. Use cases involve not just block structure and DAG evolution, but also the social logic around trust, forks, merges, and graph evolution. In essence it provides semantic CRDTs (conflict-free replicated data types) but with subjective acceptance and formal provenance: i.e., provenance-anchored knowledge graphs with subjective evolution.
- General specification
- Specialization to RDF bodies
- Specialization to TGDH encryption
- Using Cardano for Layer 1
- Genesis block and other artifacts
- Nacatgunma Explorer web application (source available at web/).
The CLI nacatgunma supports operations on the blockchain. Build using build.sh.
go build -o nacatgunma main.gonacatgunma key generate \
--key-file private.pemdid:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nrcat private.pem-----BEGIN ED25519 PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIDwz2pHLuwjP+rIrsLEwWhxoHq5iyZvWGFy/k44sHFCR
-----END ED25519 PRIVATE KEY-----nacatgunma key resolve \
--key-did "did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr" \
--output-file resolution.json
json2yaml resolution.jsonContext:
- https://w3id.org/did-resolution/v1
DIDDocument:
'@context':
- https://w3id.org/did/v1
id: did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr
verificationMethod:
- controller: did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr
id: did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr#z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr
publicKeyBase58: DNaZJmSsAinjnxjSsaUNj7G8fjJGck6C1gHaiT1xisbU
type: Ed25519VerificationKey2018
authentication:
- did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr#z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr
assertionMethod:
- did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr#z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr
capabilityDelegation:
- did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr#z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr
capabilityInvocation:
- did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr#z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr
keyAgreement:
- controller: did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr
id: did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr#z6LSpeMaM7nxQ7xYbC4wK2nNxZwqDpKQRNcPy2u3E9nvN961
publicKeyBase58: DyBQpoz6JfEoVohAnPGRdyjMNfnHimSF64BMjh9PemKF
type: X25519KeyAgreementKey2019
created: '2025-04-26T08:00:57.983089098-06:00'
updated: '2025-04-26T08:00:57.983089098-06:00'
DocumentMetadata: nullnacatgunma header build \
--key-file private.pem \
--body bafyreiea2su23cm4nbfl3675m442gp5yo5qmghspjikeeeioudyls2jjtm \
--accept bafyreid32eo34hcksuilttqhoyhssoz36r5umtk6zallvgoxqlehsqltru \
--header-file header.cborbafyreib5fuk4qex34is3pt52ij4jddlnsevkys7jwa6v2lp2qrs2eoq5hecbordump header.cbor {"Issuer": "did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr", "Payload": {"Body": 42(h'000171122080d4a9ad899c684abdfbfd6739a33fb87760c31e4f4a1442110ea0f0b969299b'), "Accept": [42(h'00017112207bd11dbe1c4a9510b9ce07760f293b3bf47b464d5ec816ba99d782c87941738d')], "Reject": [], "Schema": "DAG-CBOR", "Version": 1, "MediaType": "application/cbor"}, "Signature": h'6801ce78df1867c633fdc4b8a13fd7a5b81c93751ee9c9688e5b35a7f4e74756eefc4e6b22241f13c721fe9185b8a1fa2b41752ae5254f78bcf9025ed837990e'}nacatgunma header verify \
--header-file header.cborVerified signature by did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nrecho $?0nacatgunma header export \
--header-file header.cbor \
--output-file header.json
json2yaml header.jsonPayload:
Version: 1
Accept:
- /: QmXUuPakG4UHBs7BBQKS6o3vKeZJkRy7yTY4Pu1iGSr2PY
Reject: null
Body:
/: QmXUuPakG4UHBs7BBQKS6o3vKeZJkRy7yTY4Pu1iGSr2PY
Schema: DAG-CBOR
MediaType: application/cbor
Issuer: did:key:z6Mkrpqbu1hJWGHCuTa9Z9SDaCp8VJa82dLYhhCWYiyye6Nr
Signature: /Up9zvN/8Nf9uR0kcC5PSgLR+c4nYx2GL4XVKYR5hh3fsGsvwECGnw0E5kee9ZDj2oZlLy826bKcPQV+C4DxBw==nacatgunma body rdf \
--rdf-file body.nq \
--base-uri http://example.org/person \
--body-file body.cborbafyreiea2su23cm4nbfl3675m442gp5yo5qmghspjikeeeioudyls2jjtmcbordump body.cbor{"@id": "g1", "@graph": [{"@id": "#1234", "name": "Alice", "knows": {"@id": "#5678"}}, {"@id": "#5678", "name": "Bob"}], "@context": {"name": "http://schema.org/name", "knows": "http://schema.org/knows"}}nacatgunma body export \
--body-file body.cbor \
--output-file body.json
json2yaml body.json'@context':
knows: http://schema.org/knows
name: http://schema.org/name
'@graph':
- '@id': '#1234'
knows:
'@id': '#5678'
name: Alice
- '@id': '#5678'
name: Bob
'@id': g1nacatgunma ipfs store \
--key-file private.pem \
--body-file body.cbor \
--accept bafyreid32eo34hcksuilttqhoyhssoz36r5umtk6zallvgoxqlehsqltrubafyreib5fuk4qex34is3pt52ij4jddlnsevkys7jwa6v2lp2qrs2eoq5henacatgunma ipfs fetch \
--header-cid bafyreib5fuk4qex34is3pt52ij4jddlnsevkys7jwa6v2lp2qrs2eoq5he \
--header-file h.cbor \
--body-file b.cbornacatgunma ipfs chain \
--tip-cid bafyreidyikafj5fablrtd526tjlsnxgk6nw3wr4mrsronbo5wceihes6b4 \
--header-dir onchain/headers \
--body-dir onchain/bodies \
--progress 2025/05/31 09:04:44 Fetched and verified block header: bafyreidyikafj5fablrtd526tjlsnxgk6nw3wr4mrsronbo5wceihes6b4
2025/05/31 09:04:44 Block body previously fetched: bafybeieuxid7jfvcqs2kv74t5fcwgdw26ja4cexe6hwpkuhbrcudaj5nfm
2025/05/31 09:04:44 Fetched and verified block header: bafyreiarhfqkfmkku2hkk5dfzdxmborrhfqjs264r3f3gnweqoldh7lsxa
2025/05/31 09:04:44 Block body previously fetched: bafybeif7ztnhq65lumvvtr4ekcwd2ifwgm3awq4zfr3srh462rwyinlb4y
2025/05/31 09:04:44 Fetched and verified block header: bafyreiampkqrvb7xkgfnvs5ca6y4oashcyevrezl4xnboige7wymflpcc4
. . .
```console
### Fetch the tip from Cardano
```bash
nacatgunma cardano tips \
--node-socket preprod.socket \
--network-magic 1 \
--script-address $(cat onchain/script-0.testnet.address)[
{
"TxId": "c37f280000dac5f5e1c1b36413f786403170fc21c4e186625a7906a1d0fc2445#0",
"ScriptCredential": true,
"CredentialHash": "30135f08305143796de4276083cc54e47fbcafb176df6b58ab309446",
"HeaderCid": "bafyreignmx5htp2z4dzzqvty5bzpyw72yueqas7jzcw2qjfje7rakshzna"
}
]$ nacatgunma ledger export --help
NAME:
nacatgunma ledger export - Export headers from the ledger.
USAGE:
nacatgunma ledger export [command options]
OPTIONS:
--tip-cid value The CID for the block header of the tip of the chain
--header-dir value Input folder for the block headers
--turtle-file value Output file for the block headers in Turtle format
--json-file value Output file for the block headers in JSON format
--help, -h show help$ nacatgunma ledger prune --help
NAME:
nacatgunma ledger prune - Prune rejected blocks from the ledger.
USAGE:
nacatgunma ledger prune [command options]
OPTIONS:
--tip-cid value The CID for the block header of the tip of the chain
--header-dir value Input folder for the block headers
--accepted-file value Output file for the list of accepted block headers
--rejected-file value Output file for the list of rejected block headers
--body-file value Output file for the list of accepted block bodies
--help, -h show helpnacatgunma cardano inputs \
--header-cid bafyreignmx5htp2z4dzzqvty5bzpyw72yueqas7jzcw2qjfje7rakshzna \
--script \
--credential-hash 30135f08305143796de4276083cc54e47fbcafb176df6b58ab309446 \
--datum-file datum.json \
--redeemer-file redeemer.json \
--metadata-file metadata.jsonjson2yaml datum.jsonlist:
- constructor: 1
fields:
- bytes: 30135f08305143796de4276083cc54e47fbcafb176df6b58ab309446
- bytes: 01711220cd65fa79bf59e0f3985678e872fc5bfac509004be9c8ada824a927e20548f968json2yaml redeemer.jsonint: 58312json2yaml metadata.json'58312':
blockchain: https://github.com/functionally/nacatgunma
header:
ipfs: bafyreignmx5htp2z4dzzqvty5bzpyw72yueqas7jzcw2qjfje7rakshznaNote that these files can be generated individually using the following commands:
nacatgunma cardano datumnacatgunma cardano redeemernacatgunma cardano metadata