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>
96 lines
9.1 KiB
Markdown
96 lines
9.1 KiB
Markdown
# 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.
|
|
|
|
```sh
|
|
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.
|
|
|
|
```sh
|
|
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.
|