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>
This commit is contained in:
parent
94c6e11ece
commit
9cc195ddec
6 changed files with 338 additions and 2 deletions
64
docs/commercial/prover-customer-brief.md
Normal file
64
docs/commercial/prover-customer-brief.md
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# Igneum proving: brief for a first customer at testnet
|
||||
|
||||
Version 0.1, 3 October 2026. For a rollup or bridge team considering Igneum as a proving supplier. One page. Everything below is subject to the gates on the public roadmap, and nothing in it is an offer to sell anything.
|
||||
|
||||
## What Igneum is
|
||||
|
||||
A proof-of-work chain mined on consumer GPUs, where the same cards prove every Igneum block with zero-knowledge proofs and take proving jobs from other chains. The miners are the provers. At public testnet they are a network of independent GPU owners, 1,000 of them by the testnet gate, already paid by the chain to keep their cards on, so external jobs are marginal work for them.
|
||||
|
||||
## What you get
|
||||
|
||||
| Item | What it is | Status today |
|
||||
|---|---|---|
|
||||
| Proofs for your chain | Your batches or blocks proven by Igneum's GPU prover network and returned to the address you name | Designed. No shard has been proven on a card yet |
|
||||
| Price in dollars | Jobs are priced in dollars per proof. At launch the fee is paid on your own chain, in your currency, to a payout contract keyed by miner address, because Igneum cannot yet see your chain. Settlement in the coin follows when the proof bridge exists | Spec section 5.4 |
|
||||
| Delivery rule | A job is claimed with a bond that is slashed on a late or bad proof; a job nobody proves by its deadline expires and refunds in full. At launch your chain's own bond and slashing apply to the miner who claimed the job | Design document, execution layer, sections 5.2 and 6. Bond size and timeout are open (O-5.6) |
|
||||
| A versioned interface | Jobs run against the `ProofSystem` trait, version 1 of which is SP1. A later version is a release with its own test-vector set and a three-month overlap, so your integration survives a prover swap | Design document, execution layer, section 5.6 |
|
||||
| Verification you can run | A job proof is a single proof your contract verifies on your own chain; Igneum's own segment proofs recursively verify it, so no relayer or committee is in the path | Designed |
|
||||
|
||||
## What you must do
|
||||
|
||||
1. Integrate against the versioned prover interface: the guest program hash (`program_id`) your batches are proven under, the public-input layout, and the proof encoding for version 1.
|
||||
2. Supply test vectors: at least 100 historical batches or blocks with the expected public inputs and outputs, so Igneum's provers and your verifier agree before any job carries value.
|
||||
3. Name the deadline and the maximum proving budget per job (the `maxPgas` of the interface), and the address on your chain that receives proofs.
|
||||
4. Sign for testnet. Phase 4's gate is "one rollup signs for testnet"; a signed letter of intent with no payment is what the gate asks for.
|
||||
|
||||
## Timeline, tied to the public roadmap
|
||||
|
||||
| Phase | When | What it means for you |
|
||||
|---|---|---|
|
||||
| 2. Prove the proving | Nov 2026 to Jan 2027 | The shard benchmark on consumer cards. If a mid-range GPU cannot prove a shard in under 20 s, Igneum says so and the project stops. You see the numbers, pass or fail |
|
||||
| 4. Finality and job market | Apr to Jul 2027 | External proving jobs exist on the devnet. Integration work happens here. Gate: one rollup signs for testnet |
|
||||
| 5. Public testnet | Aug to Oct 2027 | Your proofs delivered by the live prover network. Gate: rollup proofs delivered on time, measured and published. No coin exists yet |
|
||||
| 6. Mainnet | Nov 2027 | Jobs priced in dollars, paid on your chain at first, settled in the coin once the proof bridge exists |
|
||||
|
||||
Dates from `site/journey.json`. Each gate is published whether it passes or fails.
|
||||
|
||||
## Risks, stated plainly
|
||||
|
||||
- Prototype prover. The devnet runs a stub that signs claims. No SP1 shard has been proven on any card in Igneum's repository yet. Phase 2 measures it.
|
||||
- Testnet. Proofs at testnet come from a network that is itself being tested. Expect missed deadlines and interface changes; the version number exists for that.
|
||||
- No coin value. There is no coin at testnet and nothing in this brief is a sale of one. Mainnet settlement in the coin depends on the proof bridge, which is phase two of the execution design.
|
||||
- Soundness. A soundness bug in the proof system is a risk for every SP1 user, Igneum included. Igneum's own blocks carry a native-execution veto; your chain's verifier should keep whatever fallback it has today.
|
||||
- Market size. Rollup proving spend is small today, low millions of dollars a year, approximate. Igneum's edge is cost, because the cards already run on domestic power. That is an edge and nothing more.
|
||||
|
||||
## Candidate first customers
|
||||
|
||||
Taiko is the first target (CLAUDE.md). The rest are approximate, from memory as of the design date, and need a conversation to confirm.
|
||||
|
||||
| Candidate | Why, in one line |
|
||||
|---|---|
|
||||
| Taiko | Named first target. Based rollup with a permissionless multi-proof design that already accepts SP1 proofs, so the interface is close to what exists. Approximate |
|
||||
| Scroll | zkEVM rollup with its own prover stack and a public interest in outsourced proving capacity. Approximate |
|
||||
| Linea | Consensys zkEVM with an in-house prover; a second supplier is a resilience story for them. Approximate |
|
||||
| zkSync Era and ZK Stack chains | A family of chains on one prover design; one integration could serve several. Approximate |
|
||||
| Polygon CDK and Agglayer chains | CDK chains with a type-1 prover path built on SP1, so the guest program may already match version 1. Approximate |
|
||||
| Aztec | Rollup proving for a privacy chain; client proofs stay with users, the rollup proof is outsourceable. Approximate |
|
||||
| OP Stack chains using OP Succinct | SP1 fault proofs on OP Stack chains are exactly the job shape Igneum's version 1 runs. Approximate |
|
||||
| SP1 light-client bridges | Bridges built on SP1 light clients (the Helios class) need a steady proof supply at a known price. Approximate |
|
||||
| Igra and Kasplex | EVM layers on Kaspa, the chain Igneum's node is forked from; shared tooling and a shared miner community. Approximate |
|
||||
| Starknet | A different proof system today, so a longer road; worth one conversation about the versioned interface. Approximate |
|
||||
|
||||
## Contact
|
||||
|
||||
Through the repository once it is public (January 2027) or the team page at public testnet. Igneum is honest about what is measured and what is planned; ask for the bench log.
|
||||
51
docs/provenance.md
Normal file
51
docs/provenance.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Igneum provenance: what is borrowed, what changed, how it is measured
|
||||
|
||||
Decision of 3 October 2026. Igneum credits every borrowed component in public, replaces only what its own design requires, and measures every change. This table is the public record of that decision. It is kept current with `docs/fork-divergence.md` (the node fork, change by change) and `docs/bench-log.md` (every measurement with its command).
|
||||
|
||||
How to read the licence column. "Verified" means the LICENSE file or the crate's `Cargo.toml` was read in this repository on 3 October 2026. "Approximate" means the licence is stated from memory because the source is not cloned under `vendor/` yet; it is checked again when the clone lands, and before the repository goes public.
|
||||
|
||||
## The table
|
||||
|
||||
| Component | Origin (project, licence, repository) | What Igneum changed | Why the design needs the change | How the change is measured |
|
||||
|---|---|---|---|---|
|
||||
| GHOSTDAG ordering | Kaspa, rusty-kaspa. ISC, verified (`vendor/rusty-kaspa/LICENSE`, "Copyright (c) 2022-2024 Kaspa developers"; workspace `license = "ISC"`). https://github.com/kaspanet/rusty-kaspa | Unchanged algorithm. Parameters set for 1 block per second: k 18, 10 max parents, mergeset limit 180, merge depth 3,600 blocks (`consensus/core/src/config/bps.rs`, `params.rs`) | Launch rate is 1 block a second (CLAUDE.md), rising later. These are the values Kaspa mainnet ran before Crescendo, so nothing new is asserted about the ordering | Spec section 2.1; bench-log "igneum-node devnet v0: 3-node igneum-devnet at 1 BPS"; a test in `params.rs` pins every value |
|
||||
| Node software (the fork) | rusty-kaspa v2.1.0, commit `01b532e8` (22 Sep 2026). ISC, verified. Fork at `vendor/igneum-node`, one commit per change on top of the base | Header gains `vote_key_hash`; genesis blocks; network ids `igneum-*`; devnet ports; DNS seeders emptied; address prefixes; emission schedule and 80/20 coinbase; PoW engine trait; PoW check moved after GHOSTDAG; rename of every user-visible string to `igneumd`. Full list: `docs/fork-divergence.md` | Each row there states the reason. The short version: finality rule v2 needs a vote key in every header, the emission is Igneum's own, the lottery hash needs chain state, and no Igneum node may ever dial a Kaspa peer | `docs/fork-divergence.md` (file, change, why, risk, merge note per row); bench-log devnet v0 and "first devnet blocks on the real lottery hash" entries; the four-node rename test of 3 Oct 2026 |
|
||||
| Difficulty controller | Kaspa sampled DAA (KIP-4) in rusty-kaspa, ISC, verified, kept as the retarget. Prior art studied: LWMA by Zawy (zawy12/difficulty-algorithms, licence approximate: MIT) and Monero's sorted and trimmed window (monero-project/monero, approximate: BSD-3-Clause). No code from either | Unchanged in the fork today (comment block only, `consensus/core/src/config/constants.rs`). The hash speed steps at every hourly program change, so a rule that tracks a step within an epoch is in progress: a two-speed rule (fast response to a step, slow drift otherwise). Not in spec 0.1 | Programs differ in cost (35 to 48 Mhash/s across seeds on one GPU), so a 44-minute window spends half an epoch at the wrong block rate | Spec section 2.3 names the two remedies and the gate 2 simpa run that decides; bench-log first-run and RTX 5090 entries hold the per-seed rates. The two-speed rule gets its own bench-log entry when it is simulated |
|
||||
| Random-program idea | RandomX by tevador, Monero. Licence approximate: BSD-3-Clause. https://github.com/tevador/RandomX (not yet cloned under `vendor/`; CLAUDE.md asks for it) | The idea only. Igneum's generator is new code (`igneum-pow/src/generator.rs`): a program drawn once per hourly epoch and compiled to native GPU code, with a per-hash random data path. RandomX draws a program per hash and interprets it on a CPU | A GPU cannot interpret a fresh program per hash at a useful rate; it compiles one program per hour instead. The target hardware is the opposite of RandomX's by design | Spec section 1 (generator, test vectors); bench-log "proto-metal first run", "RTX 5090 first run", "igneum-pow bit-exact" (96/96 vectors, three GPU vendors) |
|
||||
| Memory-hard dataset | RandomX cache lineage (tevador, BSD-3-Clause approximate): a small cache that derives a large dataset by dependent reads | New construction, same shape: 256 MiB cache of chained ChaCha12 blocks, 8 dependent reads per item, dataset 1 GiB in the prototype and 2 GB at genesis, growing on a genesis-fixed schedule (`igneum-pow/src/memhard.rs`, `proto-metal/MEMHARD.md`) | A light verifier must hold only the cache; a miner must hold the dataset; the dataset must outgrow any fixed chip memory. RandomX's dataset has one size for ever | `proto-metal/MEMHARD.md` section 2.2 (recompute 4.8x slower than load, Apple only); bench-log "memory-hard dataset" entries on Metal and the RTX 5090 |
|
||||
| ChaCha, SplitMix64, FNV-1a inside the lottery hash | ChaCha by D. J. Bernstein (public domain, approximate); SplitMix64 by Steele, Lea and Flood (algorithm from the 2014 paper, approximate); FNV-1a by Fowler, Noll and Vo (public domain, approximate). All three re-implemented from the definitions in `igneum-pow`, no code imported | Used as published: ChaCha12 core with feed-forward for the cache fill, SplitMix64 as the program stream, FNV-1a 64 for seed words and the cache digest | Standard, well-studied primitives for a cache fill and a seed stream; nothing in the design asks for more | Spec sections 1.3 and 1.8 with test vectors; bench-log "igneum-pow bit-exact" (cache digest `48c4f5bf24166b2e` matches Swift and C++) |
|
||||
| ProgPoW and KAWPOW | ProgPoW (EIP-1057 text, ifdefelse/ProgPOW; KAWPOW on Ravencoin since 2020, RavenProject/Ravencoin, MIT approximate). Prior art, no code used. Not yet cloned; `docs/fud-fixes.md` item 48 asks for the clone and citation before the repository is public | Nothing taken. The difference: ProgPoW and KAWPOW randomise the maths inside a fixed program shape every few blocks; Igneum regenerates the whole program every hour over a growing dataset, with automatic era draws and no human in the loop | Stated so that the "first" claim in the litepaper is accurate (FUD ledger M4) | Litepaper "What has never been done before", row 1, rewritten 3 Oct 2026 |
|
||||
| Class-group VDF | Chia, chiavdf. Apache-2.0, verified (`vendor/chiavdf/LICENSE`), commit `7e62ce14`. Wesolowski's proof (Efficient Verifiable Delay Functions, EUROCRYPT 2019), a paper, no licence | NUDUPL and NUCOMP ported from chiavdf's `qfb_nudupl` and `qfb_nucomp` into `proto-vdf` (Rust, over GMP through `rug`); fresh 1024-bit prime discriminant per input; 256-bit Fiat-Shamir prime (Chia uses 264); Igneum tags for the epoch and era paths. The textbook composition is kept as an oracle | The program seed must come from a certified checkpoint with a delay no miner can skip, so the seed cannot be ground. Chia's group needs no trusted setup | Spec section 4.2 (15,000 random cases agree with the oracle; 163,000 squarings per second; 4.5 ms verify); bench-log "proto-vdf" entry. GMP itself: LGPL-3.0 or GPL-2.0 dual, approximate, prototype only; the production dependency is decided with the wire format (O-4.5) |
|
||||
| revm | Ethereum ecosystem, bluealloy/revm. Licence approximate: MIT. https://github.com/bluealloy/revm (not yet cloned) | Unchanged, credited. Driven by an Igneum block executor that feeds it the DAG's canonical sequence with the environment table of spec 7.1 and two-dimensional gas | The same EVM runs natively and inside the zkVM (reth, rsp and SP1 Reth all use it), so native and proven execution share one code path | `docs/design/execution-layer.md` D6 and section 2.1; differential test plan against reth (section 8.5). Nothing measured yet |
|
||||
| SP1-class provers | Succinct, succinctlabs/sp1. Licence approximate: MIT or Apache-2.0. Not yet cloned | Unchanged, behind the versioned `ProofSystem` trait (`docs/design/execution-layer.md` 5.6). Version 1 is SP1 (Hypercube class, hash-based). Devnet v1 runs a stub that signs claims | Consumer cards prove hash-based systems without elliptic-curve MSM; the trait makes a swap a release (90% signalling, 3-month overlap, one wrap), never a redesign | No SP1 shard has been proven on any card in this repository (FUD ledger P1, P3). Phase 2 gate: shard time on a 3060-class card, published pass or fail |
|
||||
| BLS12-381 | Curve by Barreto, Lynn and Scott; blst by Supranational. Licence approximate: Apache-2.0. https://github.com/supranational/blst (not yet cloned) | Unchanged, credited. The header carries the BLAKE2b hash of a G1 compressed public key (48 bytes); every voter signs every 30-s checkpoint; signatures aggregate | Finality rule v2 needs one aggregate signature per checkpoint from thousands of keys | Spec section 3.1 (W1) and 2.4; `sim/results_v2.md` for the rule itself. Signature cost not yet measured |
|
||||
| Hashing in the node | rusty-kaspa `crypto/hashes`, ISC, verified. Crates linked by the fork, licences read from the local cargo registry: blake2b_simd 1.0.2 (MIT), blake3 1.8.3 (CC0-1.0 or Apache-2.0), sha2 0.10.8 (MIT or Apache-2.0), keccak 0.1.6 (Apache-2.0 or MIT); sha3 0.10.8 not in the local registry, approximate: MIT or Apache-2.0 | Unchanged, credited. BLAKE2b with domain separation for block, transaction and PoW pre-hashes (`BlockHash`, `TransactionHash`, ...), BLAKE3 keyed for the sequencing-commitment and payload hashers, SHA-256 for ECDSA signing hashes, cSHAKE256 (Keccak) in the kHeavyHash stub that stays as the default engine and for pruning-proof block levels | The chain's hash for everything except the lottery is the one the forked commit uses (spec 0.6), so nothing unverified enters consensus | `hash_override_nonce_time` gained one field (fork-divergence row 1); every header-hash test vector was regenerated and the four genesis hashes re-derived |
|
||||
| Address format | Bitcoin BIP 173 character set (bech32, Pieter Wuille and Greg Maxwell; BIP licence approximate: BSD-2-Clause) with the CashAddr polymod checksum of Bitcoin Cash (the source cites bch.info), as implemented in rusty-kaspa `crypto/addresses/src/bech32.rs`, ISC, verified | Prefixes only: `igneum`, `igneumtest`, `igneumsim`, `igneumdev` (Kaspa: `kaspa`, `kaspatest`, `kaspasim`, `kaspadev`). The script public key behind an address is unchanged | No Igneum address string may parse as a Kaspa address on any network | Fork-divergence row 9; test vectors in `addresses` and `txscript` regenerated and passing |
|
||||
| The EVM | Ethereum (Yellow Paper and ethereum/execution-specs, CC0 approximate). Cancun opcode set, precompiles 0x01 to 0x09 | Semantics on a DAG: `block.number` is selected-chain height, `block.timestamp` is non-decreasing by a max rule, `prevrandao` is the VDF epoch seed, chain ids 4461, 4462, 4463; 0x0a absent; gas has a second dimension | Blocks on a DAG have no single parent and no header state root; proving cost is a second resource; the random beacon must be unbiasable | Spec section 7.1 (normative table); devnet measurement R9 for timestamp drift; `ethereum/tests` replay in the differential plan |
|
||||
| kHeavyHash (kept as a stub) | Kaspa, rusty-kaspa `crypto/hashes/src/pow_hashers.rs` and `consensus/pow/src/matrix.rs`, ISC, verified | Kept untouched as `HeavyHashEngine`, the default engine when the `igneum-pow` feature is off, and the block-level source for pruning proofs until seeds are threaded through | Lets the devnet run and lets upstream pow changes merge cleanly | Fork-divergence rows 14 and 15; open item in the same file (pruning-proof block levels) |
|
||||
|
||||
## What is new in Igneum
|
||||
|
||||
Nothing here has a precedent that Igneum could have copied. Each item names the measurement or specification it rests on.
|
||||
|
||||
| Piece | What it is | Where it is specified or measured |
|
||||
|---|---|---|
|
||||
| The hourly header-bound GPU program | A program drawn per epoch from a VDF seed, compiled to native GPU code, with the nonce-zeroed header hash absorbed into the init words so one nonce serves one header | Spec section 1 and `igneum-pow/src/bind.rs`; bench-log "first devnet blocks on the real lottery hash" |
|
||||
| Sustained-mining finality, rule v2 | Vote weight is blue blocks per BLS vote key over a flat 30-day window; every voter signs every 30-s checkpoint; lock at 2/3 of active weight and at least 56.7% of total weight; no stake, no other chain | Spec section 3; `sim/results_v2.md` (0 conflicting locks in every partition and eclipse scenario) |
|
||||
| Two-dimensional gas and the per-frame app share | Execution gas on Ethereum's schedule plus proving gas from a calibrated table; 20% of the priority fee attributed per call frame to the registered developer of the contract that ran | Spec sections 5.1, 5.2; `docs/design/execution-layer.md` section 4 |
|
||||
| The shard market and the native proving precompile | Shards cut from the native trace, assigned by sortition to 8 eligible provers for 10 s, then open; a `Prover` system contract that takes a job and returns the result by a later proof record | Spec section 7.2; `docs/design/execution-layer.md` sections 5 and 6 |
|
||||
| Automatic era draws | Era parameters drawn every 6 months from chain state through a 1-h VDF, inside rules fixed at genesis; dataset growth and instruction-family unlocks by height, with no scheduled human release | Spec section 4.4; spec section 1 era schedule (Designed, not yet in code) |
|
||||
|
||||
## What we will adopt from upstream when it is ready
|
||||
|
||||
| Item | Source | Condition |
|
||||
|---|---|---|
|
||||
| DagKnight | Kaspa's parameterless successor to GHOSTDAG (Sompolinsky and Sutton, approximate), once it ships in a rusty-kaspa release | Merged through `tools/upstream/` after review against spec section 2; the finality rule reads blue blocks, so the weight table must be re-derived under the new ordering before activation |
|
||||
| Upstream security fixes | rusty-kaspa tagged releases | Every tagged release is fetched and merged on a branch by `tools/upstream/sync-upstream.sh`; any change to a consensus rule is reviewed against `docs/spec` before the merge commit |
|
||||
| Upstream pow and pruning-proof refactors | rusty-kaspa | Taken as long as `kaspa_pow::State` stays untouched (the Igneum engine sits beside it, never inside it) |
|
||||
|
||||
## Licence of Igneum's own code
|
||||
|
||||
Recommended: MIT, for the node fork's additions, `igneum-pow`, the prototypes and the tools. `igneum-pow/Cargo.toml` already declares `license = "MIT"` and should be read as provisional until the decision below.
|
||||
|
||||
Pending the project lead's decision. Two obligations hold whatever is chosen: the fork keeps Kaspa's ISC copyright notice in `vendor/igneum-node/LICENSE` (ISC requires it), and the VDF code keeps chiavdf's Apache-2.0 notice and a statement of what was changed (Apache-2.0 section 4).
|
||||
|
|
@ -270,7 +270,7 @@ footer .wrap{padding-block:48px 32px}
|
|||
<div class="wrap">
|
||||
<div class="sec-head reveal">
|
||||
<h2>Watch the chain prove itself</h2>
|
||||
<p>Blocks arrive every second. Miners prove them in shards. A checkpoint locks every 30 seconds. All of it will be on this page, live.</p>
|
||||
<p>Blocks arrive one a second at launch, rising as the proving layer allows. Miners prove them in shards. A checkpoint locks every 30 seconds. All of it will be on this page, live.</p>
|
||||
</div>
|
||||
<div class="card viz reveal" aria-label="Animated block DAG, simulated preview">
|
||||
<div class="viz-head">
|
||||
|
|
@ -327,6 +327,7 @@ footer .wrap{padding-block:48px 32px}
|
|||
</table>
|
||||
</div>
|
||||
<p class="reveal" style="margin-top:20px;font-size:15px;color:var(--ash);max-width:72ch">RandomX proved that a random program beats a chip when the only hardware that runs it well is the hardware everyone already owns. Igneum does the same for the card in your PC, and makes the program keep moving without a human. Run the benchmark on your own card from the repository and post the number.</p>
|
||||
<p class="reveal" style="margin-top:14px;font-size:14px;color:var(--ash);max-width:72ch">Built on the shoulders: Kaspa's GHOSTDAG and node, Monero's RandomX idea, Chia's class-group VDF, Ethereum's EVM, Succinct's SP1, BLS12-381 and Bitcoin's address format, each credited in public.<br>What changed, why, and how every change is measured: <a href="/litepaper#shoulders" style="color:var(--ember)">the provenance section of the litepaper</a>.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
@ -436,6 +437,7 @@ footer .wrap{padding-block:48px 32px}
|
|||
<a href="/litepaper">Litepaper</a>
|
||||
<a href="/litepaper#limits">What Igneum does not claim</a>
|
||||
<a href="/litepaper#randomx">Igneum vs RandomX</a>
|
||||
<a href="/litepaper#shoulders">Built on the shoulders</a>
|
||||
<a href="/bench">Engineering log</a>
|
||||
</nav>
|
||||
<nav class="foot-col" aria-label="Follow">
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ body.all .pager{display:none}
|
|||
<li><a href="#roadmap">Roadmap</a></li>
|
||||
<li><a href="#miners-ask">Questions miners ask</a></li>
|
||||
<li><a href="#builders-ask">Questions builders ask</a></li>
|
||||
<li><a href="#shoulders">Built on the shoulders</a></li>
|
||||
<li><a href="#limits">What Igneum does not claim</a></li>
|
||||
</ol>
|
||||
<div class="mode" role="group" aria-label="Reading mode"><button type="button" id="m-tabs" class="on">One section at a time</button><button type="button" id="m-all">Whole paper</button></div>
|
||||
|
|
@ -235,7 +236,7 @@ body.all .pager{display:none}
|
|||
<g>
|
||||
<rect x="50" y="152" width="400" height="72" rx="8" fill="var(--surface)" stroke="var(--line)" stroke-width="1.25"></rect>
|
||||
<text x="66" y="176" font-size="13" font-weight="600" fill="var(--ink)">2. BlockDAG ordering</text>
|
||||
<text x="66" y="194" fill="var(--ink)">Parallel blocks are ordered, about one block a second</text>
|
||||
<text x="66" y="194" fill="var(--ink)">Ordered in parallel, one block a second at launch, rising</text>
|
||||
<text x="66" y="210" fill="var(--quiet)">A transaction is included in roughly one second</text>
|
||||
</g>
|
||||
<g>
|
||||
|
|
@ -474,6 +475,24 @@ body.all .pager{display:none}
|
|||
<p>Point Hardhat or Foundry at an Igneum node with the chain id and deploy the same bytecode. Verify the source in the explorer. Register a developer address for the gas share. The afternoon is the hard part.</p>
|
||||
</section>
|
||||
|
||||
<section id="shoulders">
|
||||
<h2>Built on the shoulders</h2>
|
||||
<p>Every borrowed part of Igneum is credited here, in public. The rule, decided on 3 October 2026: credit every component, replace only what the design requires, and measure every change. Nothing was taken quietly.</p>
|
||||
<ul>
|
||||
<li><strong>Kaspa, rusty-kaspa (ISC).</strong> The GHOSTDAG ordering and the node Igneum is forked from, at v2.1.0; the sampled difficulty rule is kept as the retarget.</li>
|
||||
<li><strong>Monero, RandomX by tevador (BSD).</strong> The random-program idea and the small-cache, large-dataset design, rebuilt for GPUs with a program per hour instead of a program per hash.</li>
|
||||
<li><strong>ProgPoW and Ravencoin's KAWPOW.</strong> The first GPU randomisation precedents; they randomised the maths inside a fixed shape, Igneum regenerates the whole program.</li>
|
||||
<li><strong>LWMA by Zawy and Monero's trimmed window.</strong> Difficulty precedents studied for the hourly hash-speed step; no code taken.</li>
|
||||
<li><strong>Chia, chiavdf (Apache 2.0) and Wesolowski's proof.</strong> The class-group delay between a locked checkpoint and the next program seed, ported into the prototype.</li>
|
||||
<li><strong>Ethereum.</strong> The virtual machine itself, run through revm (MIT), with its semantics restated for a DAG.</li>
|
||||
<li><strong>Succinct, SP1 (MIT or Apache 2.0).</strong> The first proof system behind Igneum's versioned proving interface; any hash-based prover can replace it by a miner-signalled release.</li>
|
||||
<li><strong>BLS12-381 through blst (Apache 2.0).</strong> The vote-key signatures on every 30-second checkpoint.</li>
|
||||
<li><strong>Bitcoin's bech32 and Bitcoin Cash's CashAddr checksum.</strong> The address format, through Kaspa, with Igneum prefixes.</li>
|
||||
<li><strong>BLAKE2b, BLAKE3, SHA-256, Keccak.</strong> The hashes the node already uses, unchanged. ChaCha, SplitMix64 and FNV-1a inside the lottery hash, implemented from their definitions.</li>
|
||||
</ul>
|
||||
<p>What is Igneum's own: the hourly header-bound GPU program, the sustained-mining finality rule, two-dimensional gas with the per-frame app share, the shard market and proving precompile, and the automatic era draws. The full table, with what changed in each component, why the design needed it, and the measurement or specification section that covers it, is <code>docs/provenance.md</code> in the repository and is published with it in January 2027. Licences stated from memory are marked approximate there and verified before the repository opens.</p>
|
||||
</section>
|
||||
|
||||
<section id="limits">
|
||||
<h2>What Igneum does not claim</h2>
|
||||
<p>Here are the limits, stated before anyone else states them.</p>
|
||||
|
|
|
|||
96
tools/upstream/README.md
Normal file
96
tools/upstream/README.md
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
# 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.
|
||||
104
tools/upstream/sync-upstream.sh
Executable file
104
tools/upstream/sync-upstream.sh
Executable file
|
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/env bash
|
||||
# Fetch a rusty-kaspa release tag into the Igneum node fork and open the merge on a branch.
|
||||
# Commits nothing. A person reads the conflicts, runs the tests in tools/upstream/README.md,
|
||||
# does the consensus review against docs/spec, and commits.
|
||||
#
|
||||
# Usage:
|
||||
# tools/upstream/sync-upstream.sh <tag> [fork-dir] [upstream-url]
|
||||
# tag a rusty-kaspa release tag, for example v2.2.0
|
||||
# fork-dir default: vendor/igneum-node (relative to the repository root)
|
||||
# upstream-url used only if the fork has no remote named "upstream";
|
||||
# default: https://github.com/kaspanet/rusty-kaspa.git
|
||||
#
|
||||
# Refuses: a dirty working tree, a merge already in progress, a missing tag,
|
||||
# an existing merge branch. Never touches master and never runs the devnet.
|
||||
set -euo pipefail
|
||||
|
||||
tag="${1:-}"
|
||||
if [[ -z "$tag" ]]; then
|
||||
echo "usage: $0 <tag> [fork-dir] [upstream-url]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
root="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
fork="${2:-$root/vendor/igneum-node}"
|
||||
url="${3:-https://github.com/kaspanet/rusty-kaspa.git}"
|
||||
branch="merge/upstream-$tag"
|
||||
base="master"
|
||||
|
||||
if [[ ! -d "$fork/.git" ]]; then
|
||||
echo "no git repository at $fork" >&2
|
||||
exit 1
|
||||
fi
|
||||
cd "$fork"
|
||||
|
||||
if [[ -n "$(git status --porcelain)" ]]; then
|
||||
echo "refusing: working tree is not clean in $fork" >&2
|
||||
git status --short >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -f .git/MERGE_HEAD ]]; then
|
||||
echo "refusing: a merge is already in progress in $fork" >&2
|
||||
exit 1
|
||||
fi
|
||||
if git show-ref --verify --quiet "refs/heads/$branch"; then
|
||||
echo "refusing: branch $branch already exists" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! git show-ref --verify --quiet "refs/heads/$base"; then
|
||||
echo "refusing: no local branch $base" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! git remote get-url upstream >/dev/null 2>&1; then
|
||||
echo "adding remote upstream -> $url"
|
||||
git remote add upstream "$url"
|
||||
fi
|
||||
echo "upstream is $(git remote get-url upstream)"
|
||||
|
||||
echo "fetching tags from upstream"
|
||||
git fetch upstream --tags --prune
|
||||
|
||||
if ! git rev-parse --verify --quiet "refs/tags/$tag^{commit}" >/dev/null; then
|
||||
echo "refusing: tag $tag not found after fetch. Known release tags:" >&2
|
||||
git tag --list 'v*' | sort -V | tail -10 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "upstream changes in the consensus directories since the fork base (01b532e8):"
|
||||
git log --oneline "01b532e8..$tag" -- consensus crypto/hashes crypto/txscript crypto/addresses protocol/p2p/proto mining || true
|
||||
echo
|
||||
|
||||
git checkout -q -b "$branch" "$base"
|
||||
echo "on branch $branch (from $base)"
|
||||
|
||||
set +e
|
||||
git merge --no-commit --no-ff "$tag"
|
||||
status=$?
|
||||
set -e
|
||||
|
||||
echo
|
||||
conflicts="$(git diff --name-only --diff-filter=U)"
|
||||
if [[ -n "$conflicts" ]]; then
|
||||
echo "merge opened with conflicts in:"
|
||||
echo "$conflicts" | sed 's/^/ /'
|
||||
echo
|
||||
echo "expected conflict files and how to resolve each: tools/upstream/README.md"
|
||||
elif [[ $status -eq 0 ]]; then
|
||||
echo "merge opened cleanly, nothing committed"
|
||||
else
|
||||
echo "git merge exited $status without conflict markers; read the output above" >&2
|
||||
exit $status
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Nothing has been committed. Next:
|
||||
1. Resolve the conflicts, keeping every Igneum change (tools/upstream/README.md, "Where conflicts are expected").
|
||||
2. Review every upstream change under consensus/, crypto/hashes, crypto/txscript, crypto/addresses,
|
||||
protocol/p2p/proto and mining/ against docs/spec. A consensus-rule change needs a spec change first.
|
||||
3. Run the tests listed in tools/upstream/README.md.
|
||||
4. Commit on $branch with the tag, the conflicted files and the review result in the message.
|
||||
To abandon: git merge --abort && git checkout $base && git branch -D $branch
|
||||
EOF
|
||||
Loading…
Reference in a new issue