igneum/tools/upstream
igneum-labs 9cc195ddec Provenance: credit every borrowed component, upstream merge procedure, prover customer brief
docs/provenance.md: table of every component Igneum uses (origin, licence, what changed, why, how measured), what is new, what to adopt from upstream, own-code licence pending the project lead's decision. Licences verified on disk: rusty-kaspa ISC, chiavdf Apache-2.0, igneum-pow MIT, blake2b_simd MIT, blake3 CC0 or Apache-2.0, sha2 MIT or Apache-2.0, secp256k1 CC0, keccak Apache-2.0 or MIT. RandomX, SP1, revm, blst, ProgPoW, LWMA, Monero, GMP, sha3: approximate, not cloned.
site: litepaper gains the Built on the shoulders section and nav entry; index gains the two-line mention and footer link near the RandomX comparison; the block rate reads one block a second at launch, rising, where it read as permanent (litepaper diagram, index live section).
tools/upstream: README with the exact merge commands, expected conflict files from fork-divergence, the test list and the consensus-review rule; sync-upstream.sh fetches and opens the merge on a branch without committing. Not run against the fork.
docs/commercial/prover-customer-brief.md: one-page brief for a first proving customer at testnet, timeline from journey.json, risks, 10 candidates labelled approximate.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 20:02:16 +00:00
..
README.md Provenance: credit every borrowed component, upstream merge procedure, prover customer brief 2026-10-03 20:02:16 +00:00
sync-upstream.sh Provenance: credit every borrowed component, upstream merge procedure, prover customer brief 2026-10-03 20:02:16 +00:00

Merging rusty-kaspa upstream into the Igneum node fork

The fork lives at vendor/igneum-node, a clone of vendor/rusty-kaspa at v2.1.0 commit 01b532e8. Every Igneum change is one commit per subject on top of that base, so git log 01b532e8..HEAD in the fork is the full list, and docs/fork-divergence.md is the reading guide. This procedure brings a tagged upstream release into the fork on a branch, with nothing committed until a person has read the conflicts and the consensus review is done.

Written 3 October 2026. Not yet run against the fork: the first real merge will be the next rusty-kaspa tag after v2.1.0.

Rules

  1. Merges land on a branch named merge/upstream-<tag>, never on master.
  2. The script fetches and opens the merge. It never commits. A person commits.
  3. Any upstream change to a consensus rule is reviewed against docs/spec before the merge commit. Consensus means anything under consensus/, crypto/hashes, crypto/txscript, crypto/addresses, protocol/p2p/proto and mining/ in the fork. The reviewer names the spec section each change touches (sections 2.1 to 2.6 for the ordering layer, 2.4 for the header, 2.5 for emission) and either confirms the spec still holds or opens a spec change first.
  4. The node's database version and the p2p protocol version are read after every merge. If upstream bumped either, the merge note in docs/fork-divergence.md says so and the devnet is resynced from scratch.
  5. The ISC notice in vendor/igneum-node/LICENSE stays as upstream ships it.
  6. The merge is recorded: a new row at the top of docs/fork-divergence.md ("Upstream merges") with the tag, the date, the conflicted files and how each was resolved.

The commands

The remote is named upstream. Today it points at the local clone vendor/rusty-kaspa; pointing it at GitHub is equivalent and is what the script does when the remote is missing.

cd vendor/igneum-node

# 1. The remote (skip if `git remote -v` already lists upstream)
git remote add upstream https://github.com/kaspanet/rusty-kaspa.git
# or, to merge from the local mirror: git remote add upstream ../rusty-kaspa

# 2. Fetch the release tags
git fetch upstream --tags --prune

# 3. Confirm the tag and read what changed in the consensus directories
git tag --list 'v*' | sort -V | tail -5
git log --oneline v2.1.0..v2.2.0 -- consensus crypto/hashes crypto/txscript crypto/addresses protocol/p2p/proto mining
git diff --stat v2.1.0..v2.2.0 -- consensus/core/src/header.rs consensus/core/src/hashing/header.rs consensus/src/processes/coinbase.rs

# 4. The branch, from a clean master
git status --porcelain            # must print nothing
git checkout -b merge/upstream-v2.2.0 master

# 5. Open the merge without committing
git merge --no-commit --no-ff v2.2.0

# 6. See the conflicts
git diff --name-only --diff-filter=U

tools/upstream/sync-upstream.sh v2.2.0 does steps 1, 2, 4, 5 and 6 and stops. It refuses a dirty tree, a missing tag, an existing branch and a merge already in progress.

Where conflicts are expected

From docs/fork-divergence.md. Resolve each by keeping the Igneum change and re-applying the upstream intent around it.

File in the fork Why it conflicts What to do
consensus/core/src/header.rs, consensus/core/src/hashing/header.rs vote_key_hash is the last header field and is hashed after pruning_point Keep the field last. If upstream adds a header field, it goes before vote_key_hash and the p2p and gRPC field numbers (15 and 16) stay unique. Re-derive the four genesis hashes
consensus/core/src/config/genesis.rs Every genesis hash moved Re-run the ignored test that prints the hashes, paste them in
consensus/core/src/config/params.rs, consensus/core/src/config/bps.rs OneBps, devnet at 1 BPS, DNS seeders emptied, crescendo_activation: always() Keep Igneum's values. Any new upstream fork activation is always() for Igneum (no history to replay)
consensus/core/src/network.rs igneum- network ids and devnet ports Keep. These are the handshake magic
consensus/src/processes/coinbase.rs Kaspa's subsidy table removed; 80/20 split in expected_coinbase_transaction Highest risk. Upstream edits here are read line by line against spec 2.5. The payload format is still Kaspa's, so payload parsing merges cleanly
consensus/core/src/igneum.rs New file, emission constants No upstream side; conflicts only if upstream adds a file of the same name
consensus/pow/src/igneum.rs, consensus/pow/src/lib.rs, consensus/pow/Cargo.toml PowEngine trait and the igneum-pow feature beside Kaspa's State State is untouched, so upstream pow changes merge. Keep the feature forwarding in consensus/Cargo.toml and kaspad/Cargo.toml
consensus/src/pipeline/header_processor/processor.rs, pre_ghostdag_validation.rs PoW check moved after GHOSTDAG; epoch_seed walk; pow_engine on the processor Any upstream refactor of process_header conflicts. Re-read spec 2.2 before resolving
consensus/src/pipeline/header_processor/pre_ghostdag_validation.rs, consensus/core/src/errors/block.rs check_vote_key_hash_present, RuleError::MissingVoteKeyHash Keep
protocol/p2p/proto/p2p.proto, protocol/p2p/src/convert/{header,block,messages}.rs, protocol/flows/src/v10/request_headers.rs voteKeyHash = 15 on the wire Keep field 15 unique. If upstream bumped the protocol version, note it
rpc/grpc/core/proto/rpc.proto, rpc/core/src/model/header.rs, rpc/core/src/model/optional/header.rs, rpc/core/src/model/verbosity.rs, rpc/core/src/convert/verbosity.rs, rpc/grpc/core/src/convert/{header,optional/header}.rs, rpc/service/src/converter/consensus.rs, consensus/client/src/header.rs vote_key_hash through RPC Mechanical
consensus/src/model/stores/headers.rs, consensus/src/test_helpers.rs, mining/src/testutils/consensus_mock.rs, mining/src/template_limits_tests.rs, consensus/src/pipeline/virtual_processor/processor.rs, consensus/src/pipeline/body_processor/body_validation_in_isolation.rs Store serde and template plumbing for the field Mechanical
crypto/addresses/src/lib.rs, crypto/txscript/src/standard.rs, bridge/src/{default_client,share_handler,tests}.rs igneum* prefixes and regenerated vectors Any upstream test that spells a kaspa: address fails. Regenerate the vector, keep the prefix
kaspad/Cargo.toml, kaspad/src/{args,daemon,main}.rs, core/src/kaspad_env.rs, core/src/log/consts.rs, components/addressmanager/src/lib.rs, database/src/utils.rs, protocol/p2p/src/core/router.rs, rpc/grpc/server/src/connection.rs The igneumd rename of user-visible strings Keep Igneum's strings. Crate names, module paths and protobuf packages stay Kaspa's on purpose, so these are the only rename lines that conflict
Cargo.toml (root), Cargo.lock Workspace member igneum/miner, default-members, the igneum-pow path dependency Keep the member and the default set; take upstream's lock changes, then cargo update -p igneum-pow if the path moved
consensus/core/src/config/constants.rs Comment block on the DAA constants Comment only. If upstream changed a DAA constant, that is a consensus change: review against spec 2.3

Running the fork's tests after the merge

From vendor/igneum-node, in this order. Build before test so a type error shows up first.

cargo build --release -p kaspad -p igneum-miner --features igneum-pow
cargo test -p kaspa-consensus-core                      # header hashing, genesis hashes, emission schedule, params pin
cargo test -p kaspa-pow --features igneum-pow           # engine trait, binding against igneum-pow
cargo test -p kaspa-consensus --features igneum-pow     # coinbase split, PoW after GHOSTDAG, pipeline
cargo test -p kaspa-addresses -p kaspa-txscript         # igneum* prefixes and vectors
cargo test -p kaspa-p2p-lib -p kaspa-rpc-core -p kaspa-grpc-core   # wire round trips of vote_key_hash
cargo test --workspace --features igneum-pow            # everything, including upstream's own suites
./check                                                 # upstream's fmt and clippy pass

Then the crate the engine calls, from the repository root: cd igneum-pow && cargo test (23 tests, bit-exact vectors against the packs).

Then the devnet smoke test from docs/fork-divergence.md: one node on the real engine (igneumd --devnet --nodnsseed --disable-upnp --enable-unsynced-mining --yes), the miner with --engine igneum-pow, blocks accepted with the PoW accepted ... by igneum-lottery-v1-bound log line, and a second node peered by --addpeer syncing to the same sink. Do not point a merge-test node at the running devnet's appdir or ports.

A merge is committed only when every line above passes. The commit message names the tag, lists the conflicted files and states "consensus review: no rule change" or names the spec section that was updated first.

After the commit

  • Add the row to docs/fork-divergence.md.
  • Add a bench-log entry if the merge changed any measured number (build time, devnet block rate).
  • Rebuild the Windows miner and the three GPU workers against the merged igneum-pow only if that crate changed; the merge itself does not touch it.