Kagami is a tool used to generate and validate automatically generated data files that are shipped with Iroha.
From anywhere in the repository, run:
cargo build --bin kagamiThis will place kagami inside the target/debug/ directory (from the root of the repository).
Enabling optional algorithms:
Kagami inherits cryptographic features fromiroha_crypto.
--features gostexposes the TC26 GOST R 34.10-2012 parameter sets.--features ml-dsaenables ML‑DSA (Dilithium) helpers.--features blsenables BLS validator tooling (default).
Combine features as needed, for example:cargo build --bin kagami --features "bls,gost"
See Command-Line Help.
Quick tip: set IVM block gas budget at genesis
- To pin a consistent per-block gas budget for IVM across peers, Kagami can embed a custom parameter in genesis:
- Flag:
--ivm-gas-limit-per-block <u64> - Rationale: the node enforces a per‑block gas cap when validating transactions. Baking the value into genesis ensures every peer enforces the same limit, even if compiled defaults differ.
- Example:
kagami genesis generate --ivm-dir ./ivm_libs --genesis-public-key <MULTIHASH> --ivm-gas-limit-per-block 1680000
- Flag:
- If omitted, Kagami applies a sensible default: 1,680,000.
- Run
cargo xtask kagami-profilesto emit sample bundles for theiroha3-dev,iroha3-testus, andiroha3-nexusprofiles underdefaults/kagami/<profile>/. - Each bundle includes:
genesis.jsongenerated withkagami genesis --profile ...and patched with deterministic PoPs/topology.verify.txt— stdout fromkagami verify --profile ... --genesis genesis.json.config.toml+docker-compose.ymlfor a single-node smoke run (ports 8080/1337).README.mddescribing the VRF seed and peer material for the profile.
- Flags:
--profile <slug>limits generation to one profile;--kagami <path>points at a prebuilt Kagami binary;--out <dir>overrides the output root (defaultdefaults/kagami).
Sora Nexus public dataspaces require NPoS and do not support staged cutovers; omit --next-consensus-mode/--mode-activation-height when targeting a public dataspace. Other Iroha3 dataspaces may use permissioned or NPoS.
- Bare metal (Iroha3):
kagami localnet --consensus-mode npos --peers <N> --out-dir <dir>renders peer configs/PoPs. Supply--seedto keep the validator roster and PoPs deterministic; editgenesis.jsonif you need to pinsumeragi_npos_parameters.epoch_seedfor a fixed VRF seed. - Sora Nexus localnet:
kagami localnet --sora-profile nexus --peers 4 --out-dir ./sora-nexus-localgenerates a 4-node NPoS localnet and starts peers with--soraso Nexus dataspaces are enabled. - Sora dataspace localnet:
kagami localnet --sora-profile dataspace --consensus-mode permissioned --peers 4 --out-dir ./sora-ds-localkeeps Sora multi-lane defaults while letting you pick permissioned/NPoS consensus. - Bare metal (Iroha2 cutover):
kagami localnet --build-line iroha2 --consensus-mode permissioned --next-consensus-mode npos --mode-activation-height <H> --peers <N> --out-dir <dir>stages an NPoS cutover in genesis and renders peer configs/PoPs. --build-line <iroha2|iroha3>pins DA/RBC defaults to the target line; useiroha2when generating staged cutovers with thekagamibinary.- Localnet defaults to a fast pipeline (1.0s total split ~1/3 block and ~2/3 commit), tunes the commit-inflight timeout to match, shortens transaction gossip (
network.transaction_gossip_period_ms = 100,network.transaction_gossip_resend_ticks = 1, and matching target reshuffle cadence) to keep 1s blocks from waiting on propagation, bumps redundant-send fanout for DA, raisessumeragi.advanced.rbc.chunk_max_bytesto 256 KiB, lifts queue capacity to 262,144, setsnexus.fusion.exit_teu = 1,000,000andsumeragi.block.proposal_queue_scan_multiplier = 4to keep proposal assembly bounded, relaxes Torii tx rate limiting (torii.tx_rate_per_authority_per_sec = 1,000,000,torii.tx_burst_per_authority = 2,000,000,torii.api_high_load_tx_threshold = 262,144), raises Torii pre-auth limits (torii.preauth_rate_per_ip_per_sec = 1,000,000,torii.preauth_burst_per_ip = 2,000,000), and disables Kura fsync (kura.fsync_mode = "off") for local throughput. It also tunes DA availability timeouts for local runs (sumeragi.advanced.da.quorum_timeout_multiplier = 1,sumeragi.advanced.da.availability_timeout_multiplier = 1,sumeragi.advanced.da.availability_timeout_floor_ms = 2000) and writes per-peertiered_stateroots understorage/peerN. NPoS localnets now seed XOR stake for validators, activate validators in genesis, derive NPoS timeouts from the on-chain block time, and raiseparameters.block.max_transactionsto 10,000. Override the pipeline with--block-time-ms/--commit-time-msand adjust the config fields when you need slower timings; if you set only one of--block-time-msor--commit-time-ms, Kagami mirrors it to the other so the pipeline stays balanced. - Perf profiles:
--perf-profile 10k-permissionedand--perf-profile 10k-npospin 1s block/commit timing, setcollectors_k=3, deriveredundant_send_r=2f+1from the peer count (e.g., 3 for 4 peers), and apply the 10k tx-per-block cap. The NPoS profile also raises the bootstrap stake to match the configuredmin_self_bond. Use these profiles when running the localnet throughput harness. - Localnet peer configs allow loopback CIDRs (
127.0.0.0/8,::1/128) through Torii pre-auth and API rate-limit allowlists so demo clients don't hit temporary bans. --bind-host/--public-hostaccept host/IP only (no port); IPv6 literals are supported and will be bracketed in URLs.start.shdefaults totarget/debug/irohad, falls back totarget/release/irohad, and respectsCARGO_TARGET_DIRvia the generated absolute paths; setIROHAD_BINto override.- Docker (Iroha3): reuse the same
genesis.json/configs and runkagami swarm --consensus-mode npos --peers <N> --config-dir <dir> --image <img> --out-file <compose.yml>. - Docker (Iroha2 cutover): reuse the same
genesis.json/configs and runkagami swarm --consensus-mode permissioned --next-consensus-mode npos --mode-activation-height <H> --peers <N> --config-dir <dir> --image <img> --out-file <compose.yml>. The Compose manifest forwards the cutover flags to the signing sidecar sokagami genesis signstamps bothnext_modeandmode_activation_height. - Topology/PoPs: use the “End-to-end: validator PoP and genesis signing” flow to attach
--topology/--peer-popat sign time; the same PoP/topology bundle can be reused for both localnet and swarm deployments.
- Bare-metal localnet (NPoS now):
kagami localnet --consensus-mode npos --out-dir ./localnet-npos --peers 4generates BLS keys/PoPs, stamps NPoS parameters, and writes configs/genesis/scripts. Editgenesis.jsonto set a reproducible VRF seed viaparameters.custom.sumeragi_npos_parameters.epoch_seed(32-byte array/hex) when you need deterministic epochs. - Bare-metal localnet (Iroha2 cutover):
kagami localnet --build-line iroha2 --consensus-mode permissioned --next-consensus-mode npos --mode-activation-height 5 --out-dir ./localnet-npos --peers 4stagesnext_mode = nposat height 5 while keeping the permissioned fingerprint until activation. - Compose/Docker: generate an NPoS-ready
genesis.jsonfirst (kagami genesis generate --consensus-mode npos --ivm-dir ./ivm_libs --genesis-public-key <PK>), then sign it with your roster + PoPs:kagami genesis sign genesis.json --consensus-mode npos --topology "<peer ids>" --peer-pop "<pk=pop_hex>" --private-key <hex> --out-file genesis.signed.nrt. For Iroha2 cutovers, add--next-consensus-mode npos --mode-activation-height 5(keep--consensus-mode permissioned). - Swarm cutover (Iroha2):
kagami swarm --consensus-mode permissioned --next-consensus-mode npos --mode-activation-height 5 --config-dir ./cfg --image hyperledger/iroha:dev --out-file docker-compose.ymlnow refuses to render whengenesis.jsonis missingsumeragi_npos_parameters, so the compose run always carries the NPoS tuning baked into genesis. - Topology/PoP reminders: when signing for NPoS, supply a full BLS roster in
--topologyand pair each entry with--peer-popso validators carry Proofs-of-Possession in the final signed block; reuse the same roster when launching swarm/localnet to avoid mismatches.
Iroha's streaming control plane always signs messages with an Ed25519 key. If your validator identity uses another algorithm (e.g., TC26 GOST), provide a dedicated Ed25519 pair in the node config:
[streaming]
identity_public_key = "ed0120..."
identity_private_key = "802620...""kagami crypto --algorithm ed25519 can generate the pair. When the override is absent, the node reuses its main key.
This section shows how to generate BLS validator keys, produce Proof‑of‑Possession (PoP), embed PoPs into a genesis JSON, and sign the final genesis file.
Prerequisites
- Build Kagami:
cargo build --bin kagami - Ensure you compile with
--features blsfor BLS support when needed. - Keep the genesis private key handy:
kagami genesis signnow requires--private-key <hex>(payload only, no multihash prefix) or--seed <string> --algorithm <algo>so the signed block uses the intended authority key.
Use either a seed or a private key. The example below uses seeds and emits JSON.
When using the plain-text mode, Kagami hides the private key unless you pass --expose-private-key (freshly generated keys are always shown once so you can store them).
# Validator A
target/debug/kagami genesis pop --algorithm bls_normal --seed seedA --json > popA.json
# Validator B
target/debug/kagami genesis pop --algorithm bls_normal --seed seedB --json > popB.jsonThe output looks like:
{
"public_key": "bls_normal:...",
"pop_hex": "abcd..."
}Generate a default genesis (or craft one by hand):
target/debug/kagami genesis generate \
--ivm-dir ./ivm_libs \
--genesis-public-key ed25519:... \
> genesis.jsonNote: the default template leaves topology empty and carries no PoPs. Override these at signing, or embed PoPs inline (pop_hex alongside each peer) before signing with embed-pop.
If you prefer to materialize PoPs in the manifest before signing:
# Extract public_key/pop from JSON
PK_A=$(jq -r .public_key popA.json)
POP_A=$(jq -r .pop_hex popA.json)
PK_B=$(jq -r .public_key popB.json)
POP_B=$(jq -r .pop_hex popB.json)
# Write a topology array (PeerIds) that references these public keys.
# Example topology.json content:
# ["$PK_A", "$PK_B"]
topology_json="[\"$PK_A\",\"$PK_B\"]"
echo "$topology_json" > topology.json
# Embed PoPs matching the topology into a new genesis file
target/debug/kagami genesis embed-pop \
--manifest genesis.json \
--out genesis_popped.json \
--peer-pop "$PK_A=$POP_A" \
--peer-pop "$PK_B=$POP_B"Now genesis_popped.json has topology entries, each carrying a pop_hex aligned with its peer.
When you sign, you can specify a topology and per‑peer PoPs in one go; Kagami will embed pop_hex alongside each topology entry automatically for the signing transaction.
TOPOLOGY=$(jq -c . topology.json) # compact JSON ["pkA","pkB"]
target/debug/kagami genesis sign \
genesis.json \
--topology "$TOPOLOGY" \
--peer-pop "$PK_A=$POP_A" \
--peer-pop "$PK_B=$POP_B" \
--private-key "$GENESIS_PRIVATE_KEY_HEX" \
--algorithm ed25519 \
--out-file genesis.signed.nrtEither 3A or 3B yields the same final effect: the signed genesis encodes pop_hex alongside the chosen topology.
- Optionally run
kagami genesis validate genesis.jsonto check identifiers. - Distribute the signed
genesis.signed.nrtto all peers. - Ensure your
config.tomllists validator BLS-Normal keys undertrusted_peersand provides matching PoPs undertrusted_peers_pop. The loader rejectstrusted_peers_blsmappings and any validator without a PoP; genesis-embeddedpop_hexentries can satisfy the same requirement if you prefer manifest-only PoPs. - Using BLS validator keys does not change transaction admission defaults:
allowed_signingstill defaults to Ed25519/secp256k1 for accounts. Only addbls_normaltoallowed_signing/allowed_curve_idsif you plan to accept BLS-signed transactions; consensus will function with BLS validators even when admission stays Ed25519-only.