# From Firefighting to Succinctness

**URL:** <https://talk.neptune.cash/t/from-firefighting-to-succinctness/401>\
**Category:** General\
**Created:** [October 5, 2026, 11:07am UTC](https://talk.neptune.cash/t/from-firefighting-to-succinctness/401 "2026-10-05T11:07:12Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![sword-smith](https://talk.neptune.cash/user_avatar/talk.neptune.cash/sword-smith/32/20_2.png) [@sword-smith](https://talk.neptune.cash/u/sword-smith)\
**Post date:** [October 5, 2026, 11:07am UTC](https://talk.neptune.cash/t/from-firefighting-to-succinctness/401/1 "2026-10-05T11:07:12Z")

</div>

When Neptune launched in February of 2025, I expected that we would spend about one year making it a good and secure L1 for private and post-quantum transactions. Once that was done, we could turn to the exciting stuff: succinctness and novel smart contracts.

Now, almost 19 months after launch, I can see that that timeline was too optimistic. In hindsight, we have spent more time putting out fires than I would have liked to. We went through a (balance preserving) network reset, and later, two resets of the lustration barrier to uphold the guarantee that past soundness errors have not inflated the total monetary amounts.

With the newly released version 0.19.0 of `neptune-core`, I believe that most of the fire-fighting is behind us, and that we can now focus on the qualities that can make Neptune Cash truly stand apart from other blockchains: succinctness and an approach to smart contracts that unburdens the network from having to track program state.

Succinctness is one of the features I’m most excited about and where I will put my focus the next months. It means you can decide canonicity of a block by just downloading a single block. This will reduce the time required to synchronize to the network, from hours to less than a second, and it will allow Neptune to run trustlessly on smart phones and even smaller devices. On multiple occasions I have predicted that Neptune Cash will achieve succinctness this year, in 2026, and I continue to stand by that claim. Unfortunately, though, it seems like we are going to have to do a hard fork to implement succinctness. The reason for this is that the witness data of the transaction inputs are a) too big, and b) too computationally complex to handle in Neptune Cash’s zk-STARK VM [Triton VM]([https://triton-vm.org/](https://triton-vm.org/)). Since succinctness is one of the core pillars of our vision of Neptune, we believe that this upcoming hardfork is worth the price.

---

<div class="post-metadata">

**Author:** ![nptbtc](https://talk.neptune.cash/letter_avatar_proxy/v4/letter/n/d6d6ee/32.png) [@nptbtc](https://talk.neptune.cash/u/nptbtc)\
**Post date:** [October 7, 2026, 6:37am UTC](https://talk.neptune.cash/t/from-firefighting-to-succinctness/401/3 "2026-10-07T06:37:54Z")

</div>

> [@sword-smith](#):
>
> will allow Neptune to run trustlessly on smart phones

Such a node is truly a full node / trustless (unlike e.g. “light nodes” in BTC that rely on Electrum servers)?

Are there any tradeoffs? Those who use succinctness on their node, do they have any disadvantages in features?

Who will still have to be running a full archival node, and why? And why would they (does it rely on generosity only?)

---

<div class="post-metadata">

**Author:** ![sword-smith](https://talk.neptune.cash/user_avatar/talk.neptune.cash/sword-smith/32/20_2.png) [@sword-smith](https://talk.neptune.cash/u/sword-smith)\
**Post date:** [October 7, 2026, 11:08am UTC](https://talk.neptune.cash/t/from-firefighting-to-succinctness/401/4 "2026-10-07T11:08:57Z")

</div>

Yes. Fully trustless in the sense that it can decide canonicity (which block builds on a chain of valid blocks and holds the most accumulated proof-of-work) without downloading any other blocks.

Tradeoffs? The composers will have to do more work. With succinctness we’re expecting them to have to do at least four proofs with padded height 2^{21} followed by three 2^{20} proofs. 2^{21} is the same complexity that building a coinbase requires. A 2^{21} proof currently takes 15 seconds on a Threadripper CPU. The fastest composer uses about 40 seconds today to build a block proposal. Expect that number to rise to about 120 seconds with succinctness.

Who will run full archival nodes, i.e. read all historical blocks? With succinctness there is no good reason to store historical block proofs. So those don’t have to be saved. But if you want to be able to serve old announcements and an index into those, then you have to know all blocks.

| Capability | 1. Light | 2. Archival mutator set | 3. Full archival |
| --- | --- | --- | --- |
| Stores | Latest block only | All mutator set data | All blocks, with or without proofs |
| Disk today | One block | ~60 MB | ~60 GB with proofs / 2 GB without |
| Determine block canonicity | ✅ | ✅ | ✅ |
| Restore own membership proofs | ❓ | ✅ | ✅ |
| Restore arbitrary membership proofs | ❌ | ✅ | ✅ |
| Can compose | ❌ | ✅ | ✅ |
| Can guess (PoW nonce search) | ❌ | ✅ | ✅ |
| Historical announcements (encrypted UTXO data for the receiver) | ❌ | ❌ | ✅ |
| UTXO index (instant address lookup of relevant block heights/hashes) | ❌ | ❌ | ✅ |
| Serve historical blocks without proofs | ❌ | ❌ | ✅ |
| Serve historical block proofs | ❌ | ❌ | ⚠ Only if proofs are stored |

---

<div class="post-metadata">

**Author:** ![nptbtc](https://talk.neptune.cash/letter_avatar_proxy/v4/letter/n/d6d6ee/32.png) [@nptbtc](https://talk.neptune.cash/u/nptbtc)\
**Post date:** [October 8, 2026, 8:56am UTC](https://talk.neptune.cash/t/from-firefighting-to-succinctness/401/5 "2026-10-08T08:56:14Z")

</div>

Great, thanks 🙏

As this requires some tech knowlegde to read for most users.. can you maybe add new “relevant for” column?

With a few categories, e.g.

1. normal users/savers/spenders who want full-node trustlessness
2. normal users/savers/spenders who can live without XYZ (not sure if relevant for NPT)
3. miners

This way those folks can jump directly to the rows relevant to them.

---

<div class="post-metadata">

**Author:** ![LostInTranslation](https://talk.neptune.cash/letter_avatar_proxy/v4/letter/l/e5b9ba/32.png) [@LostInTranslation](https://talk.neptune.cash/u/LostInTranslation)\
**Post date:** [October 9, 2026, 8:01pm UTC](https://talk.neptune.cash/t/from-firefighting-to-succinctness/401/6 "2026-10-09T20:01:00Z")

</div>

> [@sword-smith](#):
>
> Historical announcements (encrypted UTXO data for the receiver)

If a light wallet (that does not run its own node) wants to restore balance from an old seed, it needs to connect to a full archival node (proofs are not required)? So in that sense, it’s kind of must-have thing to keep some full archival nodes running?

On a related note, what about off-chain notifications? Is the plan to keep allowing off-chain sends at the protocol level? I’m mainly looking at this from a UX perspective: the sender randomness can’t be recovered from the receiver’s seed, even with a full archival node, so the receiver has to import the notification and back it up separately, since the seed alone won’t restore those funds.

---

<div class="post-metadata">

**Author:** ![sword-smith](https://talk.neptune.cash/user_avatar/talk.neptune.cash/sword-smith/32/20_2.png) [@sword-smith](https://talk.neptune.cash/u/sword-smith)\
**Post date:** [October 9, 2026, 9:36pm UTC](https://talk.neptune.cash/t/from-firefighting-to-succinctness/401/7 "2026-10-09T21:36:23Z")

</div>

> If a light wallet (that does not run its own node) wants to restore balance from an old seed, it needs to connect to a full archival node (proofs are not required)?

Proofs are not required for that server. That is correct. The block Merkle Mountain Range (A collection of Merkle trees commmitting to all historical block hashes) will allow for succinct verification that the content of an old block, that this server serves, is authentic. In my view, this light node will, realistically, get this from an archival node serving all historical blocks, without their proofs. So with today’s block height of about 50,000 blocks, that’s around 2GB. As a fallback, the sender of the transaction can also store this data. In fact, that already happens today: The sender stores all spending information that is required for the receiver to rediscover their UTXOs, and restore their balance.

> Is the plan to keep allowing off-chain sends at the protocol level?

Yes. We plan to keep allowing that. If someone wants to use an off-chain protocol to communicate receiver-information, they should be free to do so. On a personal note, I hope that this becomes practical, common, and secure in the future.

I understand that there are risks associated with this, namely that the information required to spend the UTXOs is somehow lost. But those are risks that will have to be mitigated through clever software engineering, on a higher abstraction level than the base layer.

In fact, I don’t even see a way to disallow off-chain notifications. Disallowing them would require every full node to decrypt the (on-chain) announcement to check if it matches the transaction output, the addition record. That would undermine the idea of a privacy-preserving blockchain.

---

<div class="post-metadata">

**Author:** ![sword-smith](https://talk.neptune.cash/user_avatar/talk.neptune.cash/sword-smith/32/20_2.png) [@sword-smith](https://talk.neptune.cash/u/sword-smith)\
**Post date:** [October 21, 2026, 7:29pm UTC](https://talk.neptune.cash/t/from-firefighting-to-succinctness/401/8 "2026-10-21T19:29:38Z")

</div>

PR opened:

> <https://github.com/Neptune-Crypto/neptune-core/pull/988>
>
> \*\*New required claims\*\*
> 1. \`PredecessorIsValid\`: Verifies validity and pow-sati…sfaction of the parent block.
> 2. \`SwbfUpdateAggregation\` update is correct: Verifies that the Bloom filter part of the mutator set is updated correctly, for the current block
> 3. \`KnowsMutatorSet\`: Verifies that the composer knows the \*archival\* mutator set for the block they are composing.
> 
> \`PredecessorIsValid\` loads the \*entire\* parent block into memory and calculates its hash inside the VM, thus validating all fields.
> 
> \*\*New requirements\*\*
> a. guesser must reveal a chunk in the Bloom filter MMR along with its authentication paths. This data goes into the unbound part of the \`pow\` field of the block header. (new block validity rule 2.v: \`GuesserSwbfiReveal\`.
> b. the proving complexity of the SWBF update (2 in above list) must sum to a padded height of $2^{23}$. This is to avoid that the composer has an incentive to \*not\* pick up transactions from the mempool. This threshold means that the first 152 inputs come at zero marginal proving cost for the composer.
> 
> \*\*Activation height and mining\*\*
> Up for debate, like everything else in this PR. But this PR is made public now, so that the miners know what to expect
> \- Composers: must do more proving work, about four times as much
> \- Guessers: Must have access to a server that knows the archival mutator set (which all current nodes do). The efficient (10 TIP5 permutations) guessing algorithm is unchanged.
> 
> This is currently being tested on \`testnet-0\`. I'm composing and guessing there. Join the party! Install from this branch and run: \`neptune-core --network testnet-0\`.
> 
> \*\*Epochs\*\*
> An abstraction called \`Epoch\` is introduced to make (hard) forking of some consensus parameters easier, without breaking the proof chain. Epochs are fed as input to the \`PredecessorIsValid\` program execution. They determine what rules the \*parent\* block must follow, binding its \`SingleProof\` program digest, \`BlockProgram\`, target block time, minimum block time, and some other consensus rules. The input allows for eight different epochs to be set through hard forks, which is hopefully plenty. Changing the epoch is \*always\* a hardfork.
> 
> \*\*Gap\*\*
> This PR contains one gap between the archival validation and the succinct validation where only the latest block is verified: The witness data in \`TransactionKernel::inputs\`, i.e., the chunk dictionaries. During this development it was found prohibitively expensive to unpack the chunk dictionary data and apply them to the mutator set. And carrying around this chunk dictionary data in each block was found prohibitive from the perspective of block sizes: An 8MB block size limit only allows for 150-200 inputs per block. So I excpect a future hardfork to remove the requirement of the presence of this data from a block. That future hardfork will close this gap.
> 
> 
> | Rule | Current block | Parent block |
> |---|---|---|
> | 0.a height | Own header height is the height of the \`PredecessorIsValid\` claim the appendix must contain | Claim's height equals parent header height plus one, and the leaf count of the current block's block MMR |
> | 0.b parent digest | Own header's previous digest equals the parent hash in the claim's output | Parent header's previous digest equals the first words of the parent's own claim output |
> | 0.c block MMR | Parent's hash appended to the parent body's block MMR equals own body's, authenticated against the body hash in the claim input | By the parent's own claim, found in its appendix |
> | 0.d minimum block time | Own timestamp against the parent timestamp in the claim's output | Parent timestamp against the grandparent timestamp in the parent's claim output, under the epoch's minimum |
> | 0.e difficulty | Difficulty control over the parent timestamp and difficulty in the claim's output | Difficulty control over the grandparent values in the parent's claim output |
> | 0.f cumulative proof of work | Parent's cumulative work in the claim's output plus the applicable difficulty | Same, from the parent's claim output |
> | 0.g future dating | Own timestamp against the host's clock | Not applicable |
> | 1.a required claims | Transaction, predecessor, knows-mutator-set and SWBF update claims present, computed from the given accumulator | Transaction claim, the parent's own predecessor claim and SWBF claim found in the parent's appendix; the knows-mutator-set claim by \`KnowsMutatorSet\`'s own parent check |
> | 1.b appendix size | Host | PredecessorIsValid |
> | 1.c single proof | Host | PredecessorIsValid |
> | 1.d block proof | Verified by the host, last | Parent's block proof verified inside PredecessorIsValid |
> | 1.e block size | Host | PredecessorIsValid |
> | 1.f version in PoW | Host | PredecessorIsValid |
> | 1.g named genesis | Not applicable | A parent hashing to the named genesis is subject to no parent rule |
> | 1.h SWBF children chain | Inside the SWBF aggregation proof, verified with the block proof | Same, inside the parent's block proof |
> | 2.a inputs unpack | Host | Not checked: the known chunk-data gap |
> | 2.b removal records valid | Host, against the given accumulator | Not checked: the known chunk-data gap; index sets are bound by 2.x |
> | 2.c inputs unique | Host | PredecessorIsValid |
> | 2.d, 2.e mutator set update | Host applies the update to the given accumulator and compares with own body | PredecessorIsValid recomputes from the SWBF claim's output and the parent's transaction, compares with the parent's body |
> | 2.f transaction timestamp | Host | PredecessorIsValid |
> | 2.g, 2.h coinbase | Host | PredecessorIsValid |
> | 2.i fee | Host | PredecessorIsValid |
> | 2.j, 2.k, 2.l counts | Host | PredecessorIsValid |
> | 2.m own lustration status parses | Host | PredecessorIsValid |
> | 2.n parent's lustration status parses | From the claim's output | Grandparent's, from the parent's claim output |
> | 2.o to 2.s lustration update | Host, with the parent status from the claim's output | PredecessorIsValid, with the grandparent status from the parent's claim output |
> | 2.t transaction's mutator set | Given accumulator hashes to the claim output's mutator-set hash and to own transaction's | Parent transaction's hash equals the parent's claim output and the witness's mutator set |
> | 2.u retirement | Host | PredecessorIsValid |
> | 2.v guesser reveal | Host, against the given accumulator's inactive SWBF | PredecessorIsValid, against the witness's mutator set, where the epoch requires it |
> | 2.w SWBF work floor | Host, SWBF claim's output | PredecessorIsValid, against the epoch's floor |
> | 2.x index commitment | Host, SWBF claim's output | PredecessorIsValid, peaks over the parent's inputs |
> | Proof of work | Caller, \`has\_proof\_of\_work\_against\` with the parent timestamp and difficulty from the claim's output | PredecessorIsValid, hash under the parent's target |

---

<div class="post-metadata">

**Author:** ![LostInTranslation](https://talk.neptune.cash/letter_avatar_proxy/v4/letter/l/e5b9ba/32.png) [@LostInTranslation](https://talk.neptune.cash/u/LostInTranslation)\
**Post date:** [October 21, 2026, 7:50pm UTC](https://talk.neptune.cash/t/from-firefighting-to-succinctness/401/9 "2026-10-21T19:50:07Z")

</div>

This is a major milestone that the community has been eagerly waiting for! Fantastic work! 🎉

Epsilon will be activated on mainnet at block height 61,000, which, based on the current block time, should be around November 1-2, right?

---

<div class="post-metadata">

**Author:** ![sword-smith](https://talk.neptune.cash/user_avatar/talk.neptune.cash/sword-smith/32/20_2.png) [@sword-smith](https://talk.neptune.cash/u/sword-smith)\
**Post date:** [October 21, 2026, 7:57pm UTC](https://talk.neptune.cash/t/from-firefighting-to-succinctness/401/10 "2026-10-21T19:57:27Z")

</div>

The activation height is still in flux. But since this is a softfork, I think it can happen faster than if it was a hardfork. The miners can be expected to upgrade to the latest version faster than other users can.

So in my opinion, ten days notice would be reasonable.

You shouldn’t upgrade your main net node before this PR has been merged and a new release has been made.
