For the complete documentation index, see llms.txt. This page is also available as Markdown.

Chain Upgrade Guide (v2-elemont)

Latest release

Version
Network
Status

v2.0.49-elemont

Testnet

Deployed fleet-wide 2026-08-24 (non-consensus). Latest — recommended for all fresh installs and new builds. Final security baseline at commit 8b88cc49d11e56635385413fe8f9eaec1969c1ac; binary sha256 678040e9f88a98331a8cc32b7bf5b9e0ae4acdf84919390465eeee584b7f56c1. Uses go-vinu v1.20.26-quota. It supersedes v2.0.48 for the 2026-08-29 one-install mainnet upgrade and adds no new consensus, rules, state, activation-height, or protocol-capability behavior.

v2.0.48-elemont

Testnet

Deployed fleet-wide 2026-08-24 (non-consensus); historical predecessor superseded by v2.0.49-elemont above. Hardened the Linux default-datadir fallback: an empty/read-only-command-created .vinuchain, an interrupted genesis, or an empty database-directory skeleton could no longer strand populated legacy .opera state; inspection errors failed closed. Explicit --datadir behavior and all chain rules/state were unchanged. Binary sha256 b3415753e27f3a1586150330c69940d676edb6d0369a6100d6d15bea14f221eb. The v2.0.47 post-Patch10 snapshot below remains compatible.

v2.0.47-elemont

Testnet

Deployed fleet-wide 2026-08-20 (CONSENSUS); superseded by v2.0.48-elemont above. Activates SfcV2Patch10: reflashes Cycle-165 SFC bytecode fixing lockup-reward destruction under chunked settlement. Cycle-164's _stashRewards deleted a delegator's lockup record on a wall-clock-only condition, so the first partial claim after a lockup expired destroyed the record and every later 100-epoch chunk was paid at the unlocked rate instead of the lockup rate. Cycle-165 defers the delete until the reward cursor has fully settled, gates lockStake/relockStake/restakeRewards on full settlement so unswept history cannot be repriced, and makes stashRewards succeed through a zero-reward window instead of reverting and rolling back its own cursor advance. undelegate is deliberately never gated. No storage-layout change and no ABI change (129 selectors, identical). Also carries the mainnet feature-parity staging for the 2026-08-29 mainnet upgrade. Requires the v2.0.47 chaindata snapshot (below) for fresh or divergent nodes; every published testnet genesis is refused for fresh installs under this binary until the post-Patch10 genesis is regenerated.

v2.0.46-elemont

Testnet

Deployed fleet-wide 2026-07-17 (non-consensus); superseded by v2.0.47-elemont above. Pins Go 1.25.12 in go.mod for GO-2026-5856 (Invoking Encrypted Client Hello privacy leak in crypto/tls, fixed upstream in go1.25.12; the advisory was published after the v2.0.44 rollout, so it is unrelated to any chain change). Requires Go 1.25.12+ to build — make opera fetches the toolchain automatically. Includes everything in v2.0.45-elemont below. No rules, flag, contract, or persisted-state change: vc_getRules is byte-identical before and after (verified post-rollout). Rolled to RPC + V1–V4 on 2026-07-17 05:37–05:46 UTC; binary sha256 9420e0c1e09439b1fe5b09e7bcf6f99271d9caa302d33cf5bc7c0d49dbb72df6, built independently on both boxes and byte-identical. A convenience snapshot was published below (not required for this release).

v2.0.45-elemont

Testnet

Published 2026-07-17 (non-consensus); superseded by v2.0.46-elemont and later releases above. Ships the regenerated 2026-07-11 genesis as the trusted preset VinuChain testnet with history (2026-07-11), so a fresh install no longer needs --genesis.allowExperimental. Refuses the stale 2024-06-21 / 2026-04-19 genesis files for fresh installs, and refuses to start any datadir whose upgrade activation history disagrees with the live chain's (SfcV2Patch7 from epoch 6017, SfcV2Patch8 from 6118, SfcV2Patch9 from 6119) — the state that forked testnet validators 17 and 18 on 2026-06-21. No rules, flag, contract, or persisted-state change: vc_getRules is identical before and after and no snapshot is required. A node stopped inside epoch 6118 is still resumable — only SfcV2Patch9 remains and it activates at the canonical 6118→6119 seal.

v2.0.44-elemont

Testnet

Deployed fleet-wide 2026-07-08 (CONSENSUS). Activates SfcV2Patch9: reflashes Cycle-164 SFC bytecode with two reward-accounting fixes on top of Patch8 — (1) _rawDelegate seeds the reward cursor at currentSealedEpoch+1 (not E) for any zero-stake delegation and keeps it monotonic, closing a one-epoch reward over-mint for new/returning delegators; (2) reactivateValidator physically backfills a prior offline gap on repeated reactivation so a passive delegator across two gaps is not re-stranded. Activated at block 1,529,442 (epoch seal 6118→6119, 2026-07-08 15:49:06 UTC). Requires the v2.0.44 chaindata snapshot (below) or the regenerated 2026-07-11 genesis (see the Fresh install? note under Upgrade Steps); non-upgraded / divergent nodes must recover from the snapshot.

v2.0.43-elemont

Testnet

Deployed fleet-wide 2026-07-08 (CONSENSUS). Activates SfcV2Patch8: reflashes Cycle-163 SFC bytecode making reactivateValidator self-service — a validator's own (immutable) auth key may reactivate it from a pure-OFFLINE status after an anti-flap cooldown, without the contract owner (owner keeps the looser power for lost-key recovery). Doublesign/cheater validators stay permanently un-reactivatable for ALL callers. Two appended storage mappings capture the pre-gap reward rate at reactivation and carry it forward, so delegators are never frozen across the offline gap. Activated at block 1,529,200 (epoch seal 6117→6118). Superseded by v2.0.44-elemont; recover from the current snapshot below.

v2.0.41-elemont

Testnet

Deployed fleet-wide 2026-06-21 (CONSENSUS). Activates SfcV2Patch7: reflashes Cycle-162 SFC bytecode (initializes stashedRewardsUntilEpoch on first delegation in _rawDelegate, fixing the reward-cursor dead-zone where post-genesis delegators' claimRewards/restakeRewards reverted "zero rewards" while pendingRewards over-reported) + a testnet-only one-shot migration that raised 12 stuck delegator cursors to their join epochs. Activated at block 1,508,211 (epoch seal 6016→6017). Superseded by v2.0.44-elemont; recover from the current snapshot below.

What's new

  • Fixes lockup-reward destruction under chunked settlement (v2.0.47, CONSENSUS — SfcV2Patch10, Cycle-165). The V2 SFC settles rewards in bounded chunks: each call advances the reward cursor by at most 100 epochs. Cycle-164 deleted a delegator's lockup record the first time rewards were settled after the lockup expired — judged on wall-clock alone, with no regard for whether the cursor had caught up. A position with a long cursor gap therefore had the lockup bonus applied to only its first 100-epoch window and the entire remainder paid at the unlocked rate. Measured against live chain state before the fix: ~394,000 VC across 42 delegations, worst case 48% of the amount owed. Cycle-165 deletes the record only once the cursor has settled every payable epoch, which reproduces the pre-chunking single-sweep accounting exactly — verified on a forked chain to the wei (47 chunked claims summing to the unclamped pendingRewards total, residual 0). Two supporting changes prevent the retained record from being abused or stranded: lockStake/relockStake/restakeRewards now require full settlement before mutating an existing lockup record (its fromEpoch/duration/lockedStake are scaling inputs for the not-yet-swept window), and stashRewards reports cursor movement as progress so settlement is not blocked by a 100-epoch window that happens to contain no reward. undelegate is never gated — the fund-escape path always works.

  • Bumps go-vinu to v1.20.25-quota (v2.0.40, non-consensus). Picks up the cherry-picked CVE-2023-40591 fix that bounds the devp2p ping-handler goroutine spawn (prevents a ping-flood memory-exhaustion DoS on a node's networking layer), plus a consensus-behavior-preserving FeeRefund nil-vs-zero decode normalization. No upgrade flag, contract address, receipt format, or consensus state changes — vc_getRules is identical before and after. lachesis-base remains v0.1.6-elemont.

  • Fixes the mid-epoch restart consensus divergence (A1). v2.0.39 rebuilds the volatile PaybackCache on startup by replaying epochs E−1 and E from raw stored receipts, so a restarted node seals the same FeeRefund / block.Root as never-restarted peers. The warm-up is fail-closed: an unreadable tx-bearing block inside the replay window (e.g. TxIndex disabled) refuses to start instead of silently diverging; leading gaps on pruned/genesis-imported nodes are tolerated with a Warn. Operational rule: do not restart validators within two epochs after a QuotaCacheAddress-changing upgrade (see docs/payback-cache-restart-determinism.md in the VinuChain repo).

  • Stages VinuChain-specific BLS12-381 and latest-EVM forks on testnet. VinuBLS12381 enables the EIP-2537/BLS12-381 precompile family at 0x0b-0x11 as an explicit VinuChain fork flag. VinuLatestEVM then enables P256VERIFY at 0x0100, CLZ, MODEXP bounds/repricing, and the EIP-7825 per-transaction gas cap. These are staged in order and activate only at epoch seals.

  • Adds eth_config support. The public RPC now reports the sealed execution configuration, chain ID, fork ID, activation block/time, and active precompile set. eth_config does not expose pending DirtyRules; use vc_getRules("latest") after each seal to confirm fork activation.

  • Adds explicit gas-cap enforcement and tests. v2.0.36 rejects transactions above the VinuLatestEVM per-transaction gas cap in txpool, state transition, and block execution, and caps eth_estimateGas once the fork is active.

  • Consumes the go-vinu precompile/ModExp vector-test release. v2.0.37 pins go-vinu v1.20.24-quota, which carries the broader BLS12-381, secp256r1/P256, CLZ, MODEXP, and gas-cap vector coverage used for this testnet hard-fork validation. lachesis-base remains v0.1.6-elemont.

  • Suppresses false-positive SFC balance warnings. v2.0.38 exempts the SFC contract from the EvmWriter setBalance large-balance warning and raises the non-system warning threshold to 10,000,000 VC. This is log-only and does not change staking, balances, consensus rules, or hard-fork state.

  • Carries forward ERC-4337 account abstraction on testnet. The canonical EntryPoint v0.7 (0x0000000071727De22E5E9d8BAf0edAc6f37da032), SimpleAccountFactory (0x27e13cC69A1d0cb6205153f89Be711B1872CfFd6), and a public Skandha bundler (https://bundler-testnet.vinuexplorer.org/rpc) are live, and the explorer indexes and renders UserOperations. See Account Abstraction (ERC-4337).

  • Adds the --rpc.allow-unprotected-txs node flag (v2.0.29) so operators can admit pre-EIP-155 (chain-id-less) transactions over RPC — required to land the Arachnid deterministic deployer and the canonical EntryPoint. The flag is refused on mainnet (NetworkID 207) by a gossip-layer guard; it is for non-mainnet networks only.

  • Adds a mainnet allowlist (v2.0.30) for the single canonical Arachnid deterministic-deployer transaction, pinned by exact tx hash, so the canonical EntryPoint can eventually land on mainnet without otherwise relaxing replay protection. It is replay-benign and independent of the flag above.

  • Hardens the unprotected-tx mainnet guard (v2.0.31): extracts it into a tested helper with all-network regression coverage and adds an ethapi call-site test. No consensus or state change — testnet/mainnet behavior is identical to v2.0.30, so this release activates no new flag.

  • Carries forward Prague/EIP-7702 set-code support (v2.0.28), Shanghai/Cancun execution compatibility, the SfcV2Patch6 Cycle-162 backfill, and the corrected PaybackV2 address 0x89D1cBD9DEAaB4dFf6f800a336FBDd9A5c6829e4.

  • Mainnet reached testnet feature parity in the 2026-08-29 ELEMONT upgrade — see the Mainnet Upgrade Guide (ELEMONT). Mainnet now runs Shanghai, Cancun, Prague, SfcV2, Elemont, ElemontPubkeyValidation, VinuBLS12381, VinuLatestEVM, and PaybackV2 alongside the pre-existing Berlin, London, Llr, and Podgorica flags, on the V2 SFC contract. PaybackV2 repointed Economy.QuotaCacheAddress off the V1 Quota proxy 0x1c4269fbbd4a8254f69383eef6af720bcd0acda6 onto the deployed QuotaContractV2 at 0x5d989a2d65d049e2198d91d8ddc31c918f2544ab. Because the EVM forks staged sequentially, activation crossed five consecutive epoch seals. The SfcV2Patch* and PaybackV2Patch flags remain false on mainnet: they only re-flash bytecode on a chain that already activated with stale bytecode, and mainnet's first SfcV2 activation installed the identical Cycle-165 blob directly (48,757 bytes, sha256 134a508b13d46647052b64f8d6691f0b939d2afaa0fa400882c6653a40a77887, byte-identical to testnet).

Current Testnet Rollout State

The RPC and validators V1–V4 run v2.0.49-elemont, deployed one node at a time on 2026-08-24 from the published linux/amd64 binary (commit 8b88cc49d11e56635385413fe8f9eaec1969c1ac, sha256 678040e9f88a98331a8cc32b7bf5b9e0ae4acdf84919390465eeee584b7f56c1). This was a non-consensus binary swap: v2.0.49 adds the security baseline but no new consensus, rules, state, activation-height, or protocol-capability behavior; sealed rules, SFC bytecode, and chain state were unchanged. All four validators resumed event production after the restart protection interval.

v2.0.44-elemont (consensus) was built once on the validator host and distributed byte-identically to all five nodes on 2026-07-08 (RPC first, then validators V1-V4 one-at-a-time with 20s spacing). Binary sha256 d060210f793d7d38019d41a3bfb6cc48a52a5878d544d0b6bf6bd094c7d04a72 (one build distributed via S3, byte-identical by construction). It activates SfcV2Patch9 at the first epoch seal after boot, which reflashes Cycle-164 SFC bytecode (raw-bytes sha256 b25a749fe4fa4191bafc2f48d62f046176e1c9ba8fb914fa4a6f81651c4344af, 48,336 bytes) with two reward-accounting fixes on top of Patch8: (1) _rawDelegate now seeds the reward cursor at currentSealedEpoch+1 — the first epoch whose stake snapshot includes the new stake — for any zero-stake delegation (first OR returning delegator), skips the immediate _stashRewards on a zero-stake delegation, and makes the cursor monotonic in _stashRewards, closing a one-epoch reward over-mint (seeding at E let a delegation opened during E+1 claim the E→E+1 accumulator delta whose _epochEndReceivedStake[E] per-token denominator excluded the just-added stake). A residual one-epoch over-mint remains, by design, only when ADDING to an existing non-zero position (not fixable with a single per-delegator cursor). (2) reactivateValidator physically backfills a PRIOR offline gap's snapshot rates (bounded at MAX_REACTIVATION_BACKFILL=300 ≈ 7.5M gas, under the 20.5M block-gas limit) before overwriting its single heal record, so a fully-passive delegator across two consecutive offline gaps is not re-stranded. No new storage slots (a constant + existing mappings only). Because this is a persisted-state consensus change, a fresh chaindata snapshot IS required once the activation seals; non-upgraded nodes diverge with wrong event epoch hash. The previous binary is preserved as opera.v2.0.43.bak.<timestamp> beside each deployed binary. Activation sealed at block 1,529,442 (epoch 6118→6119) on 2026-07-08 15:49:06 UTC — all five nodes reflashed the Cycle-164 bytecode at the same block, each logging exactly one Re-applying SFC V2 bytecode upgrade (patch 9) with no Multiple SfcV2Patch* warning and no wrong event epoch hash (clean single-patch activation). Post-rollout vc_getRules("latest") reports SfcV2Patch9=true and eth_getCode(0xFC00FACE…) is the 48,336-byte Cycle-164 (b25a749f…); the chain advanced past the activation block with all four validators active and producing (quorum reached the reflash with no divergence). The replacement v2.0.44 chaindata snapshot is published below.

The latest public recovery snapshot is the v2.0.47-elemont object (taken 2026-08-20 at block 1,585,766 / epoch 6,375). It is the required recovery artefact for v2.0.47 and newer: SfcV2Patch10 is a persisted-state consensus change, so a pre-Patch10 snapshot replays the reflash at the wrong seal and diverges with wrong event epoch hash. It is also the only valid bootstrap for a fresh install, because every published genesis pre-dates the Patch10 activation.

Snapshot SHA256:

It was produced under the 20260820T113052Z object name; SNAPSHOT_INFO.txt records snapshot timestamp 2026-08-20T11:30:52Z, tip block 1,585,766, and epoch 6,375, with all 24 upgrade flags sealed — SfcV2Patch7/8/9 plus SfcV2Patch10, alongside VinuBLS12381, VinuLatestEVM, PaybackV2 and PaybackV2Patch. It also pins the sealed SFC bytecode: Cycle-165, 48,757 bytes, sha256 134a508b13d46647052b64f8d6691f0b939d2afaa0fa400882c6653a40a77887. Tarball sha256 56fb6ed4ca88f4fe202444180036b1a5920560d1879110716d6ae74befa2409d (1.39 GiB); identity files (nodekey, keystore/, opera.ipc, static-/trusted-nodes) are excluded, so it is safe to distribute. A stale snapshot (pre-SfcV2Patch10) will replay historical forks under the wrong rule set and hit wrong event epoch hash; always use the current object above.


Network Details

Network
Chain ID
RPC
Status

Mainnet

207 (0xcf)

https://rpc.vinuchain.org

ELEMONT feature-parity upgrade complete (2026-08-29/30). Active as checked 2026-09-03: Berlin, London, Shanghai, Cancun, Prague, VinuBLS12381, VinuLatestEVM, Llr, Podgorica, SfcV2 (+30% base-fee burn), Elemont, ElemontPubkeyValidation, PaybackV2; SFC V2 (version() = "305"); Quota contract 0x5d989a2d…2544ab. Only the SfcV2Patch* / PaybackV2Patch re-flash flags stay unset

Testnet

206 (0xce)

https://vinufoundation-rpc.com

v2.0.49-elemont deployed; the above plus the testnet-only re-flashes — SfcV2Patch7 + SfcV2Patch8 (self-service reactivateValidator) + SfcV2Patch9 (reward-cursor over-mint + repeated-reactivation fixes) + SfcV2Patch10 (Cycle-165 lockup preservation under chunked settlement) active; Quota proxy 0x89D1cBD9…29e4


Prerequisites

Build requirements

  • Go 1.25+ (check with go version)

  • gcc (or clang) and standard C library headers — required for building go-vinu's crypto and LevelDB C bindings.

  • git

  • At least 50 GB free disk space

Required Ports

Ensure these remain open in your firewall:

Port
Protocol
Purpose

5050

TCP/UDP

P2P networking

18545

TCP

HTTP JSON-RPC (if exposing RPC)

18546

TCP

WebSocket JSON-RPC (if exposing WS)


Upgrade Steps

Fresh install? Do not replay any published testnet genesis under v2.0.49. Every one predates the sealed SfcV2Patch10 activation, and the binary refuses it to prevent a wrong-seal divergence. Restore the verified v2.0.47 post-Patch10 chaindata snapshot in Wrong event epoch hash / snapshot recovery, then start v2.0.49 with an explicit --datadir.

1

Stop your node

If the process doesn't exit cleanly within ~10 seconds, check the logs and stop to investigate. pkill sends SIGTERM by default, allowing graceful shutdown. Never send SIGKILL to opera.

Send Ctrl+C (SIGINT) to the foreground process and wait for it to exit cleanly. In tmux/screen, attach first, then send the interrupt.

Verify the process has exited:

2

Download and build the new binary

Pick a persistent path with at least ~2GB free for the source tree, the Go module cache, and the resulting ~38MB binary. Either $HOME or a system path like /opt works — choose whichever lives on a partition with headroom (mainnet operators with large chaindata may prefer /opt or another volume so the build doesn't compete with $HOME for space). Avoid /tmp: some Linux distributions clear it on reboot, which would wipe a pre-staged build.

The build directory is independent of your node's --datadir. The build process never reads or writes chain data, so a build that runs out of space fails cleanly without affecting the running node.

Or download the published binary instead of building. Attached to the v2.0.49-elemont release:

Substitute /opt/vinuchain-upgrade (or any other path) if $HOME is not the right partition for your setup — every later command in this guide that references $HOME/vinuchain-upgrade should be adjusted to match.

Dependency pins. v2.0.49-elemont builds with Go 1.25.13+ and patched golang.org/x/net/x/text releases. It uses go-vinu v1.20.26-quota and lachesis-base v0.1.6-elemont; the EVM, consensus rules, state, and activation behavior are unchanged from v2.0.48. make opera fetches dependencies on first build.

3

Verify the new binary

The newly-built binary is at vinuchain-upgrade/build/opera. Move into that directory so the rest of the steps can use a relative ./opera path:

opera version prints 2.0.49-elemont — this matches the git tag v2.0.49-elemont. See the note at the top of this page.

4

Start your node

From the build directory you cd'd into in the previous step, start the node:

The --bootnodes value above lists all four live testnet validators at 44.239.129.39 (ports 3000–3003). Use them as-is — they are the same enodes hardcoded into the binary's testnet defaults and will give a new or restarted node a working entrypoint into the peer mesh.

Monitor the logs:

Optional flags (add only if you were using them before):

  • --datadir /custom/path — if chain data is not in the default location (~/.vinuchain on Linux; a pre-existing ~/.opera keeps priority as the legacy directory)

Slow peer discovery on small networks? On a small or freshly restarted testnet, discv5 discovery via --bootnodes can take several minutes to populate the peer table — and may fail entirely if the bootnode itself is restarting at the same time. The most reliable fix is to drop a static-nodes.json file inside <datadir>/go-opera/ that lists every peer enode you want a persistent connection to. Opera reads it on every startup and dials those peers immediately, bypassing discovery.

Adjust the path if you use a non-default --datadir.

Ensure your docker run command (or compose file) still mounts the datadir volume and exposes the same ports.

For testing or development, you can run in the foreground:

Optional flags:

  • --datadir /path/to/chaindata — if chain data is in a custom location. On Linux the default is ~/.vinuchain; a populated legacy ~/.opera keeps priority while ~/.vinuchain is absent or only an unused shell, and if both hold chain state ~/.vinuchain wins. Pass --datadir explicitly to remove the ambiguity.

5

Verify the upgrade

What to expect:

Startup banner. Every v2.x build prints the VinuChain banner. This is the first visual confirmation that you are running v2.0.49-elemont and not the previous binary:

Staging logs (testnet only, first-time Shanghai/Cancun/Prague/BLS/latest-EVM install). On the first boot of a node that has not yet sealed Shanghai (e.g. a genesis replay rather than a snapshot restore), you will see Shanghai staged while later forks are deferred:

This confirms EIP-3651, EIP-3855, and EIP-3860 are pending for the next epoch seal, while Cancun is intentionally held back so skipped-binary nodes do not collapse Shanghai and Cancun into the same activation height.

After vc_getRules reports Upgrades.Shanghai = true, v2.0.37 stages Cancun automatically on the same continuous process:

This confirms EIP-1153, EIP-5656, and EIP-6780 behavior are pending for the next epoch seal.

After vc_getRules reports Upgrades.Cancun = true, v2.0.37 stages Prague automatically on the same continuous process:

After vc_getRules reports Upgrades.Prague = true, v2.0.37 stages VinuBLS12381:

After vc_getRules reports Upgrades.VinuBLS12381 = true, v2.0.37 stages VinuLatestEVM:

On current post-latest-EVM testnet datadirs, both VinuBLS12381 and VinuLatestEVM are already sealed. The staging lines above are expected only on older datadirs that have not already crossed those seal points. eth_config reports sealed execution config only; it does not show pending DirtyRules, so use vc_getRules("latest") after the seal to confirm that the flag is active. If you do not see a staging line, you may be running the wrong binary (opera version check), the flag may already be pending in DirtyRules from an earlier boot, or the flag may already be sealed on this datadir. Absence of the staging line by itself is not proof that the fork has sealed; confirm with vc_getRules. Mainnet does not stage VinuBLS12381 or VinuLatestEVM in v2.0.37.

Older staging logs (testnet only, first-time SfcV2Patch6 install). Nodes upgrading from before v2.0.21 that have not yet sealed SfcV2Patch6 can also see this older staging line:

This confirms the Cycle-162 SFC bytecode re-flash and automatic testnet delegation backfill are pending. Mainnet nodes never show this line because SfcV2Patch6 is testnet-only. Nodes upgrading directly from v2.0.18 or earlier may also see the older Staged PaybackV2Patch ... line if that edge has not yet sealed on their datadir.

Seal-time activation (testnet only). At the next epoch seal after Shanghai staging, vc_getRules must report Upgrades.Shanghai = true. At the next epoch seal after Cancun staging, it must also report Upgrades.Cancun = true. At the next epoch seal after Prague staging, it must also report Upgrades.Prague = true. At the next epoch seal after VinuBLS12381 staging, vc_getRules must report Upgrades.VinuBLS12381 = true and eth_config.current.precompiles must include the BLS12-381 precompiles. At the next epoch seal after VinuLatestEVM staging, vc_getRules must report Upgrades.VinuLatestEVM = true and eth_config.current.precompiles must include P256VERIFY. There is no SFC bytecode re-flash, contract address change, or registry update for these EVM fork flags.

If SfcV2Patch6 is also still pending, the same seal can include the older SFC Patch6 re-flash:

If the node writes SFC storage, you will also see the backfill log:

If every listed pair is already visible in stakes[] or has dropped to zero stake, the re-flash log can appear without a Backfilled ... line. After it fires, vc_getRules must report Upgrades.SfcV2Patch6 = true, and eth_call to SFC version() must return 0x333035 ("305"). The Backfilled ... counts are lower if a listed pair already became visible or dropped to zero stake before the seal; repaired may be non-zero if a pair is present in stakes[] but its stakePosition points at a stale row. Economy.QuotaCacheAddress remains the corrected PaybackV2 address 0x89D1cBD9DEAaB4dFf6f800a336FBDd9A5c6829e4.

Mainnet SfcV2 activation (live, ELEMONT). The mainnet ELEMONT upgrade activated SfcV2, not SfcV2Patch6. The first v2.x boot on a pre-SfcV2 mainnet datadir stages SfcV2 and, at the activation seal, installs the latest SFC bytecode directly and runs the mainnet-only delegation backfill:

Now that the mainnet seal has happened (2026-08-29), vc_getRules reports Upgrades.SfcV2 = true and SFC version() returns 0x333035 ("305"), and the Backfilled ... counts should reconcile against the mainnet missing-delegation audit taken immediately before the release. Counts can be lower if a listed pair became visible or dropped to zero stake; repaired can be non-zero for stale stakePosition rows. The staging network (NetworkID = 205) inherits mainnet rules and exercises this same SfcV2 activation/backfill path, so it is the rehearsal host for the mainnet upgrade; it does not use the testnet SfcV2Patch6 edge.

Verification checklist

Check
Expected

Startup banner

VINUCHAIN v2.0 - ELEMONT ASCII art printed to stderr

opera version

Version: 2.0.49-elemont

Block production

Resumes within seconds of startup; block numbers advance

Peer count

Returns to prior steady-state within minutes

Shanghai staging logs (testnet, first pre-Shanghai boot)

Staged Shanghai upgrade …; Cancun and Prague may log as deferred until predecessors are active

Shanghai rule after seal

vc_getRules reports Upgrades.Shanghai = true

Cancun staging logs (testnet, post-Shanghai process)

Staged Cancun upgrade … after Shanghai seals; no restart required

Cancun rule after seal

vc_getRules reports Upgrades.Cancun = true

Prague staging logs (testnet, post-Cancun process)

Staged Prague upgrade … after Cancun seals; already-active testnet nodes will not show it again

Prague rule after seal

vc_getRules reports Upgrades.Prague = true

EIP-7702 transaction support after Prague seal

Set-code transactions (type: 0x04) accepted; blob transactions (type: 0x03) remain rejected

VinuBLS12381 staging logs (testnet, post-Prague process)

Staged VinuBLS12381 upgrade …; VinuLatestEVM remains deferred until BLS is active

VinuBLS12381 rule after seal

vc_getRules reports Upgrades.VinuBLS12381 = true; eth_config includes BLS12_G1ADD through BLS12_MAP_FP2_TO_G2

VinuLatestEVM staging logs (testnet, post-BLS process)

Staged VinuLatestEVM upgrade … after BLS seals; no restart required

VinuLatestEVM rule after seal

vc_getRules reports Upgrades.VinuLatestEVM = true; eth_config includes P256VERIFY at 0x0000000000000000000000000000000000000100

VinuLatestEVM transaction gas cap

Over-cap transactions are rejected by txpool/state transition; eth_estimateGas caps at the fork limit

SfcV2Patch6 staging logs (older unsealed datadirs only)

Staged SfcV2Patch6 …

SfcV2Patch6 staging log — all other cases

None

Mainnet staging logs (ELEMONT SfcV2, pre-SfcV2 datadir)

Staged SfcV2 upgrade … on a pre-SfcV2 mainnet datadir

Staging-network SfcV2 rehearsal

Same SfcV2 logs as mainnet; no SfcV2Patch6 staging line

Seal-time logs (testnet, first epoch seal after staging)

Re-applying SFC V2 bytecode upgrade (patch 6) …; normally 1× Backfilled SFC Patch6 testnet delegations … appended=3 repaired=0

Mainnet seal-time logs (ELEMONT SfcV2 activation)

Applying SFC V2 bytecode upgrade …; compare both state-dependent appended and repaired fields with the near-activation audit; verify the compiled pair count separately

SFC version after seal

version() returns 0x333035 ("305")

PaybackV2 address after seal

0x89D1cBD9DEAaB4dFf6f800a336FBDd9A5c6829e4

Block hash vs peer

Identical

rpc_modules returns

Includes "vc":"1.0" (vc_getPaybackBalance)

vc_getPaybackBalance call

Returns hex-encoded wei (or 0x0 for ineligible addresses / Podgorica inactive)

eth_config before BLS/latest seals

Reports the sealed current config; pending DirtyRules are not shown

6

Verify you're on the correct chain

Confirm your node is on the same chain as the network:

The block number is returned as a hex quantity (e.g. 0x1705f0) — jq's tonumber does not parse hex, so print it as-is. Compare the block number and hash against the public RPC or another validator's node; if they match, you are on the correct chain. (For a decimal value, run printf '%d\n' 0x1705f0.)

7

Clean up rollback artifacts

If you kept a copy of your previous opera binary (or any other upgrade-related files) outside the scope of this guide, you can delete them once your validator has been running cleanly on the new binary for at least one full epoch and you've confirmed the chain hash matches in the previous step.

The build directory under $HOME/vinuchain-upgrade can also be removed if you don't plan to rebuild locally.


Setting Up a New Validator

New validator setup is not covered on this page. If you are installing a fresh validator for the first time rather than upgrading an existing one, follow the dedicated guide: Become a Validator.

That guide uses the correct opera validator new command for generating a validator key. A plain opera account new creates a regular externally-owned account, not a validator key.


Rollback

Before a staged fork seals, rollback is a normal coordinated binary swap back to the previous testnet binary. After VinuBLS12381 seals, do not roll back below v2.0.33 without operator coordination: older binaries do not know the BLS12-381 rule bit or precompile set. After VinuLatestEVM seals, do not roll back below v2.0.36 without operator coordination: older binaries lack the latest-EVM execution rules and complete per-transaction gas-cap enforcement. The earlier Prague rollback constraint still applies: after Prague seals, do not roll back below v2.0.28 without operator coordination. The earlier Shanghai/Cancun rollback constraints also still apply: after Shanghai seals, do not roll back below v2.0.26 without operator coordination, and after Cancun seals do not roll back below the release that sealed Cancun on that datadir.

The earlier SfcV2Patch6 rollback constraints still apply. After SfcV2Patch6 seals, do not roll back below v2.0.21 without operator coordination: the Cycle-162 bytecode and automatic testnet delegation backfill persist in chain state, and older binaries do not contain the activation-time backfill logic. The corrected PaybackV2 v2.0.19 rollback constraints still apply if PaybackV2Patch was also part of the node's upgrade path.

The later SfcV2Patch7, SfcV2Patch8, SfcV2Patch9 and SfcV2Patch10 constraints also apply. After those patches seal, do not roll back below v2.0.41, v2.0.43, v2.0.44 or v2.0.47 respectively without operator coordination: each patch reflashes the SFC contract and its bytecode persists in chain state. The current testnet runs v2.0.49 and has all four patches sealed. A coordinated v2.0.49→v2.0.47 binary rollback is state-compatible because v2.0.49 adds no consensus, rules, state, or activation change; do not go below v2.0.47. Use the current post-Patch10 snapshot instead of replaying older state.

After the SfcV2Patch10 seal, no published genesis is a valid fresh-install bootstrap. Every testnet genesis preset — including the 2026-07-11 one — pre-dates the Patch10 activation, so replaying it under v2.0.47-elemont or newer stages Patch10 at a local seal the live chain never performed and diverges with wrong event epoch hash. The binary refuses those presets for fresh installs and points at the current snapshot instead. Until a post-Patch10 genesis is regenerated, fresh installs restore from the snapshot.

For mainnet SfcV2, the seal has already happened: the ELEMONT activation began 2026-08-29 10:00 UTC and is complete. Live vc_getRules on https://rpc.vinuchain.org reports SfcV2, Elemont, ElemontPubkeyValidation and PaybackV2 all true, and SFC version() at 0xFC00FACE... returns 0x333035 ("305"). A mainnet rollback is therefore no longer a routine binary swap: v2.0.0-rc.1 predates ELEMONT, so do not roll below the activation binary v2.0.49-elemont without operator coordination — the Cycle-165 SFC bytecode and the mainnet delegation backfill persist in chain state. Fresh or recovering mainnet nodes must bootstrap from a post-ELEMONT artefact — the post-seal chaindata snapshot or the regenerated post-ELEMONT genesis; replaying from a pre-activation genesis/datadir under a different binary re-stages the transition at the wrong seal. Mainnet operators: see the Mainnet Upgrade Guide (ELEMONT).

  1. Stop the node (clean shutdown).

  2. Replace opera with a prior elemont release binary (e.g., v2.0.10-elemont, v2.0.9-elemont, or earlier).

  3. Start the node.

No datadir changes are needed for a pre-seal rollback. A post-seal rollback must be treated as a coordinated incident response, not a routine downgrade.

Per-version rollback deltas. Each bullet describes the only functional difference between the two versions.

  • v2.0.44 → v2.0.43 rollback: SfcV2Patch9 has reflashed Cycle-164 SFC bytecode with the reward-cursor and repeated-reactivation fixes. After the Patch9 seal, that bytecode persists in chain state and v2.0.43 lacks the Patch9 rule bit, startup guard, and staging logic; downgrade only as coordinated incident response.

  • v2.0.43 → v2.0.41 rollback: SfcV2Patch8 has reflashed Cycle-163 SFC bytecode with self-service reactivation and offline-gap reward mappings. After the Patch8 seal, that bytecode persists in chain state and v2.0.41 lacks the Patch8 rule bit, startup guard, and staging logic; downgrade only as coordinated incident response.

  • v2.0.41 → earlier rollback: SfcV2Patch7 has reflashed Cycle-162 SFC bytecode and ran the testnet migration for stuck delegator reward cursors. After the Patch7 seal, that bytecode and migrated state persist; older binaries lack the Patch7 rule bit and staging logic, so downgrade only as coordinated incident response.

  • v2.0.40 → v2.0.39 rollback: v2.0.40's only delta is the go-vinu bump to v1.20.25-quota (the CVE-2023-40591 p2p ping-flood goroutine bound plus a consensus-behavior-preserving FeeRefund nil-vs-zero decode normalization). It adds no fork flag, rules, snapshot, SFC, or persisted-state change, so a binary-only rollback to v2.0.39 is state-compatible at any point and safe as a routine downgrade — there is no seal to cross and no mid-epoch-restart divergence risk (the FeeRefund decode change re-encodes byte-identically in both directions). The only thing lost is the p2p ping-flood DoS hardening on the networking layer; mitigate at the infra/firewall layer while rolled back.

  • v2.0.39 → v2.0.38/v2.0.37 rollback: v2.0.39's only delta is the startup PaybackCache warm-up (consensus A1 fix) — no fork flag, rules, snapshot, SFC, or dependency change — so a binary-only rollback is state-compatible at any point. But it reintroduces the divergence the fix closes: a rolled-back node that restarts mid-epoch can seal FeeRefund/block.Root values that differ from never-restarted peers. If you must roll back, avoid any further restart of the rolled-back node until it is re-upgraded; treat an unplanned mid-epoch restart on the old binary as a potential-fork incident and compare the node's latest state root against a healthy peer before letting it emit.

  • v2.0.37 → earlier rollback: v2.0.37 consumes the go-vinu precompile/ModExp vector-test release. Treat rollback like v2.0.36: safe only before the relevant BLS/latest-EVM seal, and never below the binary that sealed an already-active flag without operator coordination.

  • v2.0.36 → earlier rollback: Safe only before the VinuLatestEVM seal. After the seal, older binaries do not consistently reject over-cap transactions across txpool, state transition, block execution, and eth_estimateGas.

  • v2.0.34/v2.0.35 → earlier rollback: Safe only before the VinuLatestEVM seal. After the seal, older binaries lack P256VERIFY, CLZ, MODEXP bounds/repricing, eth_config latest-EVM reporting, and the VinuLatestEVM RLP/config bits.

  • v2.0.33 → earlier rollback: Safe only before the VinuBLS12381 seal. After the seal, older binaries lack the BLS12-381 precompile set, RLP bit, EVM chain-config mapping, and staged activation logic.

  • v2.0.32 → earlier rollback: Mainnet/staging rehearsal release for SfcV2/Podgorica/Shanghai/Cancun/Prague rule defaults and the mainnet Quota proxy pointer. Existing testnet datadirs are governed by the already-sealed testnet flags above.

  • v2.0.28 → earlier rollback: Safe only before the Prague seal. After Prague seals, older binaries lack EIP-7702 set-code transaction decoding, authorization-list validation, delegated EOA execution, event serialization, txpool policy, and RPC/signer support; downgrade can diverge on valid post-Prague transactions.

  • v2.0.26 → earlier rollback: Safe only before the relevant Shanghai/Cancun seal. After Shanghai seals, v2.0.21 and older lack Shanghai support, v2.0.22-v2.0.24 lack the fixed VinuChain-local Shanghai transaction checks, and v2.0.25 lacks the full event-admission, txpool reset, skipped-transaction accounting, and continuous Cancun-staging hardening. After Cancun seals, older binaries also lack the final Cancun opcode/SELFDESTRUCT behavior and downgrade can diverge on valid post-Cancun transactions or gas accounting.

  • v2.0.25 → earlier rollback: Safe only before the relevant Shanghai/Cancun seal. After Shanghai seals, v2.0.21 and older lack Shanghai support, and v2.0.22-v2.0.24 lack the fixed VinuChain-local Shanghai transaction checks. After Cancun seals, older binaries also lack the final Cancun opcode/SELFDESTRUCT behavior and downgrade can diverge on valid post-Cancun transactions or gas accounting.

  • v2.0.21 → v2.0.20 rollback: Safe only before SfcV2Patch6 seals. During the pending Patch6 window, v2.0.20 can stage the bytecode re-flash but does not perform the automatic testnet delegation backfill, so validators should run v2.0.21 before the Patch6 seal.

  • v2.0.20 → v2.0.19 rollback: Safe only before SfcV2Patch6 seals. After the seal, Cycle-162 SFC bytecode persists in chain state, but v2.0.19 lacks the SfcV2Patch6 rule bit, startup guard, and staging logic; downgrade only as coordinated incident response.

  • v2.0.19 → v2.0.18 rollback: Safe only before PaybackV2Patch seals. After the seal, stored rules point at the corrected V2 contract and v2.0.18 lacks the patch flag plus unstakeFor(address,uint256) Payback classification, so downgrade would make Payback accounting observability incomplete.

  • v2.0.14 → v2.0.13 rollback: v2.0.13 was a same-day scaffolding release with the deadbeef-placeholder Cycle-161 bytecode and both flags defaulted off; the v2.0.13 binary refuses to start with SfcV2Patch5: true set against the placeholder, so this rollback path is not safe if SfcV2Patch5 has already sealed on testnet. Rollback further to v2.0.12 instead.

  • v2.0.14 → v2.0.12 rollback: Loses both SfcV2Patch5 staging and the ElemontPubkeyValidation sealer guard. If SfcV2Patch5 has already sealed on testnet, the Cycle-161 bytecode at 0xFC00FACE... persists in chain state (see Testnet note below); the v2.0.12 binary continues to dispatch against it unchanged. If ElemontPubkeyValidation has already sealed, validator 16 stays ejected from the active set in stored epoch state regardless of the binary running. eth_feeHistory reverts to the hardcoded gasUsedRatio: 0.99 (the rollback target restores that pre-v2.0.13 behaviour).

  • v2.0.11 → v2.0.10 rollback: Loses the SfcV2Patch4 staging logic in binary rules and the sfc.EnforcePatch4StartupCheck build guard. If SfcV2Patch4 has already sealed on testnet, the Cycle-160 bytecode at 0xFC00FACE... persists in chain state (see Testnet note below); the v2.0.10 binary continues to dispatch against it unchanged. The relock invariant remains endTime >= ld.endTime because that logic lives in the deployed bytecode, not the binary.

  • v2.0.10 → v2.0.9 rollback: Loses the SfcV2Patch3 staging logic. If SfcV2Patch3 has already sealed, the Cycle-159 reentrancy-guard-fixed bytecode persists in chain state; all nonReentrant entrypoints continue to work because the _reentrancyGuardCounter < 2 check is in the deployed bytecode.

  • v2.0.9 → v2.0.8 rollback: Loses the trusted-preset entry for vitainu-genesis-testnet-20260419.g. Fresh installs on v2.0.8 from that genesis file again require --genesis.allowExperimental and print the SECURITY WARNING: Genesis file doesn't refer to any trusted preset line on startup; existing datadirs are unaffected.

  • v2.0.8 → v2.0.7 rollback: validatePeerProgress re-applies its drift caps (maxPeerEpochDrift=1000, maxPeerBlockDrift=5000). Safe as long as the node is not offline long enough to fall past those caps; an offline stretch beyond ~1,000 epochs on v2.0.7 will lock the node out of re-peering (the bug v2.0.8 fixes).

  • v2.0.7 → v2.0.6 rollback: The per-peer event-processing quota reverts to its smaller value (200 DAG events / 100 stream items), so the Peer exceeded event processing quota warning storm returns during sync.

  • v2.0.6 → v2.0.5 rollback: The vc_getPaybackBalance JSON-RPC method disappears. Clients calling it receive method not found.

Sealed patch
Introduced in
Testnet seal
Installed bytecode

SfcV2Patch2

v2.0.5

Mid-v2.0.5 boot

Cycle-158 SFC (45,240 bytes)

SfcV2Patch3

v2.0.10

2026-04-19 · block 1,424,440

Cycle-159 SFC — inline reentrancy guard fix

SfcV2Patch4

v2.0.11

2026-04-23 · block 1,430,436

Cycle-160 SFC — _lockStake / relockStake fix

SfcV2Patch5

v2.0.14

Active by 2026-05-17

Cycle-161 SFC — canonical-pubkey validation

SfcV2Patch6

v2.0.21

2026-05-16 · block 1,460,329

Cycle-162 SFC — orphan-delegation auto-backfill

SfcV2Patch7

v2.0.41

2026-06-21 · block 1,508,211

Cycle-162 SFC — reward-cursor initialization and stuck-cursor migration

SfcV2Patch8

v2.0.43

2026-07-08 · block 1,529,200

Cycle-163 SFC — self-service reactivation and offline-gap reward mappings

SfcV2Patch9

v2.0.44

2026-07-08 · block 1,529,442

Cycle-164 SFC — reward-cursor and repeated-reactivation fixes

SfcV2Patch10

v2.0.47

2026-08-20 · block 1,585,699

Cycle-165 SFC — lockup preservation under chunked settlement


Troubleshooting

Node won't start after upgrade

  1. Check logs: journalctl -u opera -f (systemd) or your terminal / Docker output.

  2. Verify the binary: opera version must print 2.0.49-elemont.

  3. If the database is reported as corrupted, restore from the chaindata snapshot below.

  4. If startup ends with Fatal: this datadir belongs to the VinuChain Testnet network but ..., see the next section — the datadir is stale or divergent and must be replaced, not restarted.

Fatal: this datadir belongs to the VinuChain Testnet network

v2.0.45-elemont and later refuse to start a testnet datadir that has not genuinely crossed the live chain's upgrade activation seals. The refusal is deliberate and there is no override flag: starting such a datadir would activate SfcV2Patch7/8/9 at a local epoch seal the live chain never performed, and the node would fork and reject every peer event with wrong event epoch hash. This is the state that stranded testnet validators 17 and 18 on 2026-06-21 — earlier binaries started anyway and only failed later, after the damage was sealed into chaindata.

You will see one of these, depending on how the datadir went stale:

What to do: replace the chaindata with the current post-Patch10 snapshot per Troubleshooting → Wrong event epoch hash. No published genesis is a safe fresh bootstrap under v2.0.47 or newer. Your nodekey and keystore/ are preserved by the snapshot procedure, so the node keeps its identity.

Do not try to work around it by downgrading to v2.0.44-elemont and starting the same datadir: the older binary has no such check, so it will start, fork at its next epoch seal, and leave you with a divergent database to replace anyway.

For reference, the live testnet activated SfcV2Patch7 at epoch 6017 (block 1,508,212 — the first block under the new rules; the seal itself is block 1,508,211), SfcV2Patch8 at epoch 6118 (block 1,529,201), and SfcV2Patch9 at epoch 6119 (block 1,529,443). A node stopped inside epoch 6118 was resumable under v2.0.44–46, when only SfcV2Patch9 remained; v2.0.47 and newer also stage Patch10, so they refuse that boundary rather than co-stage both patches at one local seal. Generated private networks (opera network new) and fakenets are never affected — the check matches on the published testnet genesis ID, which they do not share.

Node starts but doesn't produce events

  1. Confirm --validator.password points to a readable file via absolute path.

  2. Confirm --validator.id and --validator.pubkey match your on-chain registration.

  3. Confirm peers are connecting — an isolated node cannot produce events.

WARN Incoming event rejected ... err="wrong event epoch hash"

Your locally-computed epoch state hash does not match the network's. The check rejects any event whose PrevEpochHash differs from the local store's EpochState.Hash(). There is no protocol-level recovery; chaindata must be replaced with a snapshot.

After the VinuBLS12381 and VinuLatestEVM seals on 2026-06-03, live validators rejected stale peer events such as event=5907:1:42bc39 creator=17 err="wrong event epoch hash". If your node logs that shape around epoch 5907 or later, it is on stale or otherwise divergent chaindata and should restore from the post-latest-EVM snapshot below.

Recovery procedure (testnet) — chaindata snapshot:

  1. Stop opera cleanly (pkill -TERM opera or systemctl stop opera).

  2. Back up your validator identity. Copy <datadir>/keystore/ and <datadir>/go-opera/nodekey somewhere safe before deleting anything. These are your validator key material — losing them means losing validator identity on-chain.

  3. Delete the stale chaindata in place (keeping keystore + nodekey):

  4. Download the latest post-seal testnet snapshot and extract it in-place over the datadir (the tar is written with relative paths, so extract at the datadir root; published tarballs exclude nodekey, keystore/, opera.ipc, static-nodes.json, trusted-nodes.json so your identity files are preserved). Always use the latest snapshot — older objects may be removed and must not be reused after a newer fork seal.

    Sanity-check the extraction before restarting opera. Every snapshot published from 2026-04-24 onwards (including this one) includes a SNAPSHOT_INFO.txt at the tarball root, so it lands in your datadir automatically on extraction. Read it before starting opera:

    The file lists the network, snapshot timestamp, binary version, tip block, tip epoch, and the full set of sealed upgrade flags. The tip block listed there is the minimum block number your first New block log line should show after restart. If cat returns nothing, the tarball did not extract correctly — do not start opera; re-extract at the datadir root.

    The current object name is published in this guide (above) and in the GitHub release notes for the matching tag — those are the source of truth. Bucket listing is not public (?list-type=2 returns AccessDenied), so there is no URL that enumerates snapshots without AWS credentials; with credentials, use aws s3 ls s3://vinu-blockchain-genesis/chaindata-snapshots/. Superseded objects are removed, so an old URL will 403 rather than serve stale chaindata.

    The tarball is flat (top-level is chaindata/, go-opera/, and SNAPSHOT_INFO.txt — no datadir/ prefix to nest) and excludes nodekey, keystore/, opera.ipc, static-nodes.json, trusted-nodes.json, archived chaindata.bak.*/, and shell history files. New snapshots are published under s3://vinu-blockchain-genesis/chaindata-snapshots/. As of the v2.0.47-elemont fleet rollout (2026-08-20), the current public object is testnet-chaindata-v2.0.47-elemont-20260820T113052Z-clean (sha256 56fb6ed4ca88f4fe202444180036b1a5920560d1879110716d6ae74befa2409d, tip block 1,585,766 / epoch 6,375, all flags through SfcV2Patch10 sealed); older objects are removed and must not be reused after a newer fork seal — the v2.0.46 object named here previously now returns 403.

  5. Ensure --nat extip:<your_public_ip> is set and <datadir>/go-opera/static-nodes.json contains the canonical bootnode list from the Start your node section.

  6. Restart opera. The node resumes from the snapshot's tip and syncs forward. Expect New DAG summary age=<few seconds> within 1-2 minutes of restart.

Trace/RPC recovery from a current validator datadir. If no fresh public snapshot exists after a new seal, recover internal trace/RPC nodes from a current validator snapshot instead of replaying an old tarball. Stop one validator cleanly, archive only its active <validator-datadir>/chaindata directory, restart that validator, verify the archive checksum on the RPC host, then replace only the RPC node's chaindata while preserving go-opera/nodekey and static/trusted nodes. The 2026-06-03 trace RPC recovery used this path after an older May snapshot replayed historical forks under v2.0.37 and hit wrong event epoch hash; restoring current validator chaindata brought the trace node back at the current head with eth_syncing=false and working trace_block("latest").

Stuck at net.peerCount == 1 with one stale peer

Symptom: admin.peers shows exactly one peer on a prior opera version, frozen at an old epoch. Your node catches up to that single peer's last block and then stops advancing.

This almost always means your enode record is advertising 127.0.0.1 (no peers outside that one random discovery hit can dial you back). Fix:

  1. Confirm the startup log line New local node record ... ip=… — if ip=127.0.0.1, --nat extip is missing.

  2. Stop opera, add --nat extip:<your_public_ipv4> to the launch command, ensure static-nodes.json lists the canonical testnet bootnodes (see the Start your node section), and restart.

  3. Within a few minutes net.peerCount should be 4+ and age on New DAG summary lines should drop into the second / millisecond range.

If the peer count stays stuck at 1 after fixing --nat, check your host firewall / cloud security group: TCP and UDP on your --port (default 3000) must be open to 0.0.0.0/0.

Receipt feeRefund field is 0x0 after PaybackV2Patch

After the PaybackV2Patch seal, all feeRefund calculations resolve against corrected QuotaContractV2 at 0x89D1cBD9DEAaB4dFf6f800a336FBDd9A5c6829e4. Existing depositors on the old V1 proxy at 0x824B93dE7221cf8a35FBd29d5202f6eFa3A29C5D keep their stake balance there but no longer earn fee refunds, because the node stops consulting that contract once Economy.QuotaCacheAddress is swapped. To resume earning refunds, withdraw from V1 (unstake() then wait holdTime then withdrawStake(wrID)) and stake() on the corrected V2 with the same wallet.

If the transaction is already using corrected V2 and feeRefund is still 0x0, check the sender's V2 Quota stake against minStake(). The sender must meet the contract minimum before any refund is available. On the corrected testnet deployment, the initial minStake() value is 1000 VC, but the Quota owner can update it with setMinStake(uint256); for stakeFor(receiver), the receiver must meet the current minimum because the receiver is the refunding sender.

Verify activation:

vc_getPaybackBalance returns -32005

The RPC-safe payback accessor is gated by a process-wide semaphore (8 in-flight, 2 s acquire timeout). Error code -32005 is the rate-limit rejection. Clients should retry with exponential backoff; operators running high-volume scanners should either spread load across multiple RPC endpoints or reduce concurrent caller count. See Changelog → Payback Fee Refunds.


Current State and Post-Upgrade Verification

As checked 2026-09-03, mainnet (chain 207) is fully ELEMONT-activated. Berlin, London, Shanghai, Cancun, Prague, VinuBLS12381, VinuLatestEVM, Llr, Podgorica, SfcV2, Elemont, ElemontPubkeyValidation and PaybackV2 are all active. Economy.QuotaCacheAddress now points at the mainnet QuotaContractV2 0x5d989a2d65d049e2198d91d8ddc31c918f2544ab. Confirm the live state directly against the public RPC:

PaybackV2, VinuBLS12381, and VinuLatestEVM all report true on mainnet since the 2026-08-29 ELEMONT upgrade, which activated all three (see the Mainnet Upgrade Guide). They arrived at different seals: PaybackV2 at seal 1, VinuBLS12381 at seal 4, VinuLatestEVM at seal 5. SFC version() returns 0x333035 ("305") once SfcV2 is active.

Routine binary swaps. When a new mainnet or testnet release is published, pre-stage the binary on every validator (Upgrade Steps step 2), perform the binary swap during the agreed window, then confirm block production resumed and opera version reports the expected tag.

Missed an activation window? A seal-bound edge does not replay if you boot the new binary after the seal. On testnet, SfcV2Patch6 sealed at block 1,460,329 in epoch 5801 on 2026-05-16; if your node was not already running v2.0.21 before that seal, a later binary swap will not replay the edge or apply the automatic backfill. Stop the node, preserve keystore/ and go-opera/nodekey, and restore from the latest post-seal chaindata snapshot in Troubleshooting before rejoining.

After any Shanghai, Cancun, Prague, SfcV2, VinuBLS12381, or VinuLatestEVM seal, the same rule applies: nodes that missed the activation window should restore from the newest post-seal snapshot instead of replaying the edge at a different block.


Contact

If you encounter issues during the upgrade, reach out to the VinuChain team through the official channels.


Changelog

Network upgrades and testnet seal points

The codebase uses several internal upgrade names. The base SfcV2, Podgorica, and Elemont flags activate together when SfcV2 first fires; later testnet-only patch flags re-flash specific bytecode or operational state at their own epoch seals. The same table carries the live testnet seal or staging state so operators do not need to reconcile a separate seal-point table.

Name
Introduced / testnet seal state
What it covers

SfcV2

Active on testnet; live on mainnet since the 2026-08-29 ELEMONT upgrade

Replaces the on-chain SFC contract bytecode at 0xFC00FACE... and turns on the 30% base fee burn.

Podgorica

Active on testnet; live on mainnet (already live pre-ELEMONT)

Payback fee refund mechanism. Source of the optional feeRefund field on receipts and transactions.

Elemont

Active on testnet; live on mainnet since the 2026-08-29 ELEMONT upgrade

Cheater fee zeroing at SealEpoch plus the broader v2.0+ release-series naming used in version strings.

Shanghai

Introduced in v2.0.22; sealed on testnet 2026-05-17 at block 1,461,622; live on mainnet since the 2026-08-29 ELEMONT upgrade

EVM execution compatibility with Ethereum Shanghai changes that apply to VinuChain: EIP-3651 warm coinbase, EIP-3855 PUSH0, and EIP-3860 initcode metering plus the 49,152-byte initcode limit.

Cancun

Introduced in v2.0.24; sealed on testnet 2026-05-18 at block 1,461,786; live on mainnet since the 2026-08-29 ELEMONT upgrade

Selected Cancun/Dencun EVM compatibility that applies without blob transactions: EIP-1153 transient storage (TLOAD / TSTORE), EIP-5656 MCOPY, and EIP-6780 SELFDESTRUCT behavior.

Prague

Introduced in v2.0.28; sealed on testnet 2026-05-18 at block 1,462,637; live on mainnet since the 2026-08-29 ELEMONT upgrade

Scoped Prague/EIP-7702 compatibility for abstract-account delegation: set-code transaction type 0x04, authorization lists, `0xef0100

VinuBLS12381

Introduced in v2.0.33; sealed on testnet 2026-06-03 at block 1,482,823

VinuChain-specific EIP-2537/BLS12-381 precompile fork. Adds BLS12_G1ADD, BLS12_G1MSM, BLS12_G2ADD, BLS12_G2MSM, BLS12_PAIRING_CHECK, BLS12_MAP_FP_TO_G1, and BLS12_MAP_FP2_TO_G2 at 0x0b-0x11 without coupling the rollout to upstream Prague/KZG behavior.

VinuLatestEVM

Introduced in v2.0.34; sealed on testnet 2026-06-03 at block 1,482,978

VinuChain-specific latest-EVM compatibility fork. Adds P256VERIFY at 0x0100, CLZ, MODEXP bounds/repricing, and EIP-7825 per-transaction gas-cap enforcement. This flag is intentionally separate from VinuBLS12381 so BLS can bake first. Activation time was 2026-06-03 09:47:52 UTC.

PaybackV2

Introduced in v2.0.18; active on testnet

Binary-level swap of Economy.QuotaCacheAddress from the original TransparentUpgradeableProxy-based Quota proxy to a freshly-deployed non-proxy QuotaContractV2 whose owner is a recoverable EOA. Activates at the first epoch seal after the v2.0.18+ binary boots. Replaces the original proxy's upgrade path without losing access to existing depositor stake (V1 unstake/withdrawStake remain permissionless after activation).

PaybackV2Patch

Introduced in v2.0.19; active on testnet

One-shot testnet repair edge that rebinds an already-active PaybackV2 chain from the superseded V2 address to corrected QuotaContractV2 0x89D1cBD9DEAaB4dFf6f800a336FBDd9A5c6829e4.

SfcV2Patch6

Introduced in v2.0.20 and sealed with v2.0.21 on 2026-05-16 at block 1,460,329

One-shot testnet SFC bytecode re-flash to Cycle-162, adding orphan-delegation registration/backfill and an undelegate-to-zero fix for legacy orphaned stake pairs. v2.0.21 also performs the known live testnet delegation backfill in node state at the seal.

SfcV2Patch10

Introduced in v2.0.47; sealed on testnet 2026-08-20

One-shot SFC bytecode re-flash to Cycle-165. Fixes lockup-reward destruction under chunked settlement: the lockup record is now deleted only once the reward cursor has fully settled, lockStake/relockStake/restakeRewards require full settlement before mutating an existing lockup record, and stashRewards advances through zero-reward windows instead of reverting. undelegate is never gated. No storage-layout or ABI change. Mainnet receives the same bytecode directly at its first SfcV2 activation and therefore never needs this flag.

Mainnet SfcV2 backfill

Mainnet-only activation hook; not a testnet seal point

At mainnet's first SfcV2 activation (sealed 2026-08-29) the node installed the latest Cycle-165 bytecode directly and ran a mainnet-only node-state backfill hook for live delegation rows that have non-zero getStake but are missing from the SFC stakes[] enumeration. Re-derive the bounded pair set from live chain state at T−2. Record its compiled length separately from the state-dependent expected appended and repaired results; zero-stake or already-visible pairs do not append. This is an enumeration defect rather than fund loss — getStake stays authoritative for balances and withdrawals — but it is only repairable at the seal. The repair runs exactly once at SfcV2 activation.

Testnet has Shanghai, Cancun, Prague, the SFC re-flashes through SfcV2Patch10, the ElemontPubkeyValidation sealer guard, PaybackV2, PaybackV2Patch, VinuBLS12381, and VinuLatestEVM active. Mainnet has completed the ELEMONT upgrade — the activation window opened 2026-08-29 at 10:00 UTC and, as verified against the public RPC on 2026-09-03, Berlin, London, Shanghai, Cancun, Prague, VinuBLS12381, VinuLatestEVM, Llr, Podgorica, SfcV2, Elemont, ElemontPubkeyValidation and PaybackV2 are all active, on the V2 SFC contract (version() returns 305), with Economy.QuotaCacheAddress repointed off the V1 Quota proxy 0x1c4269fbbd4a8254f69383eef6af720bcd0acda6 onto the mainnet QuotaContractV2 0x5d989a2d65d049e2198d91d8ddc31c918f2544ab. The SfcV2Patch* and PaybackV2Patch re-flash flags stay unset on mainnet — its first SfcV2 activation installs the identical Cycle-165 bytecode directly.

Release overview

Version
Type
What changed

v2.0.49-elemont

security baseline (non-consensus)

Raises the audited go-ethereum advisory floor and uses go-vinu v1.20.26-quota with the applicable p2p/crypto hardening. No new consensus, rules, state, activation-height, or protocol-capability change relative to v2.0.48; supersedes v2.0.48 for the 2026-08-29 one-install mainnet upgrade. Deployed to testnet RPC + V1-V4 on 2026-08-24 at commit 8b88cc49d11e56635385413fe8f9eaec1969c1ac; binary sha256 678040e9f88a98331a8cc32b7bf5b9e0ae4acdf84919390465eeee584b7f56c1.

v2.0.40-elemont

go-vinu bump — p2p CVE hardening (non-consensus)

Bumps go-vinu to v1.20.25-quota, picking up the cherry-picked CVE-2023-40591 fix that bounds the devp2p ping-handler goroutine spawn (ping-flood DoS hardening on the networking layer) plus a consensus-behavior-preserving FeeRefund nil-vs-zero decode normalization. No fork flag, contract address, receipt format, SFC, snapshot, or consensus-state change — vc_getRules is identical before and after. Deployed to testnet RPC + V1-V4 on 2026-06-19; the rollout also restored systemd management of the validators (units left failed since the 2026-06-11 rollout).

v2.0.39-elemont

PaybackCache restart warm-up (consensus A1 fix)

Rebuilds the volatile PaybackCache at startup by replaying epochs E−1 and E from raw stored receipts, so a mid-epoch restart seals the same FeeRefund/block.Root as never-restarted peers. Fail-closed on unreadable tx-bearing blocks in the replay window (TxIndex required); leading-gap tolerant on pruned/genesis-imported datadirs. No consensus-rule, fork-flag, snapshot, SFC, or dependency change — the fix changes startup behavior only.

v2.0.38-elemont

EvmWriter SFC warning hygiene

Raises the non-system setBalance large-balance warning threshold to 10,000,000 VC and exempts the SFC contract, preventing valid restake calls from logging scary false positives. Log-only release; no consensus, SFC bytecode, snapshot, fork flag, or dependency change.

v2.0.37-elemont

Release hygiene + precompile vectors

Bumps the release to 2.0.37-elemont and consumes go-vinu v1.20.24-quota, carrying the broader precompile and MODEXP vector-test coverage used to validate the BLS12-381 / P256 / CLZ / MODEXP / gas-cap hard-fork surface. Deployed to testnet RPC + V1-V4 on 2026-06-03.

v2.0.36-elemont

VinuLatestEVM gas-cap enforcement

Enforces the VinuLatestEVM per-transaction gas cap in txpool, state transition, block execution, and eth_estimateGas, with focused tests for each path. This is the consensus-critical release for the latest-EVM gas-cap behavior.

v2.0.35-elemont

Release bump

Release hygiene bump after the latest-EVM implementation landed. Functional behavior is the v2.0.34 latest-EVM surface plus dependency/version updates.

v2.0.34-elemont

Vinu latest-EVM fork + eth_config

Adds the VinuLatestEVM rule bit, RLP serialization, staged activation after VinuBLS12381, P256VERIFY / CLZ / MODEXP latest-EVM behavior via go-vinu, and the public eth_config RPC that reports sealed execution configuration and active precompiles.

v2.0.33-elemont

Vinu BLS12-381 fork

Adds the VinuBLS12381 rule bit, RLP serialization, staged activation after Prague, and BLS12-381 precompile activation at 0x0b-0x11. Mainnet stayed false for this flag until a separate activation release.

v2.0.32-elemont

Mainnet hard-fork staging defaults

Set the mainnet/staging SfcV2, Podgorica, ElemontPubkeyValidation, Shanghai, Cancun, and Prague defaults that the ELEMONT mainnet upgrade activated, and fixed the hardcoded mainnet Quota proxy pointer (0x1c4269fbbd4a8254f69383eef6af720bcd0acda6) for fresh mainnet rule construction. Testnet consensus behavior is governed by its already-sealed flags plus later BLS/latest-EVM releases.

v2.0.31-elemont

Unprotected-tx guard hardening (non-consensus)

Extracts the mainnet AllowUnprotectedTxs refusal from NewService into a tested checkUnprotectedTxsPolicy helper with all-network regression coverage so the guard cannot be silently dropped or separated from the flag, adds an ethapi call-site test proving the Arachnid carve-out is admitted only on mainnet (NetworkID 207) and refused elsewhere, and corrects the --rpc.allow-unprotected-txs usage string. No consensus or persisted-state change; activates no flag. Deployed to testnet RPC + V1-V4 on 2026-05-28.

v2.0.30-elemont

Mainnet Arachnid deployer allowlist (ERC-4337 enablement)

Adds opera/unprotected_allowlist.go, allowlisting exactly one pre-EIP-155 transaction on mainnet — the canonical Arachnid deterministic-deployment-proxy tx, pinned by exact hash 0xeddf9e61…033d26 — so the deterministic deployer (0x4e59b448…4956C) and, via CREATE2, the canonical ERC-4337 EntryPoint v0.7 (0x0000000071727De…f37da032) can land on mainnet. The allowlist is part of the ELEMONT release that activated on mainnet on 2026-08-29; the EntryPoint singleton itself is a separate CREATE2 deployment step. Replay-benign (deploys a stateless, fund-less factory) and independent of AllowUnprotectedTxs, which stays refused on mainnet.

v2.0.29-elemont

--rpc.allow-unprotected-txs flag (testnet AA enabler)

Exposes a --rpc.allow-unprotected-txs CLI flag wiring gossip.Config.AllowUnprotectedTxs, letting non-mainnet operators admit pre-EIP-155 (chain-id-less) transactions over RPC — the testnet enabler for the Arachnid deployer and the canonical EntryPoint. The existing gossip/service.go guard refuses the flag on mainnet (NetworkID 207). This release is what unlocked ERC-4337 account abstraction on testnet; keeps go-vinu at v1.20.19-quota.

v2.0.28-elemont

Prague / EIP-7702 abstract-account release

Adds the Prague upgrade flag on testnet and updates go-vinu to v1.20.19-quota. Enables EIP-7702 set-code transaction type 0x04, authorization lists, delegated EOA execution via `0xef0100

v2.0.26-elemont

EIP audit hardening

Extends fork-aware Shanghai transaction validation into event admission, drops pre-Shanghai pending/queued contract creations that become invalid when Shanghai activates, keeps skipped intrinsic/initcode failures from mutating sender balance or block gas, and stages Cancun automatically after Shanghai seals on continuous nodes. Keeps go-vinu at v1.20.17-quota.

v2.0.25-elemont

Shanghai/Cancun local execution fix

Wires Shanghai transaction-level gas checks into VinuChain's local evmcore execution and txpool paths, adds regression coverage for local evmcore, sequences skipped-binary activation so Cancun cannot seal at the same height as Shanghai, and keeps go-vinu at v1.20.17-quota. Superseded by v2.0.26 for event-admission, txpool reset, skipped-transaction accounting, and no-restart Cancun staging hardening.

v2.0.24-elemont

Cancun SELFDESTRUCT behavior

Updates go-vinu to v1.20.17-quota for EIP-6780-style SELFDESTRUCT behavior. Superseded by v2.0.25 because v2.0.24 did not yet wire the Shanghai transaction-level gas rules into VinuChain's local evmcore path.

v2.0.23-elemont

Cancun opcode support

Updates go-vinu to v1.20.16-quota and adds the Cancun upgrade flag for selected non-blob Cancun behavior: EIP-1153 transient storage and EIP-5656 MCOPY. Superseded by v2.0.25 for the local evmcore Shanghai gas fix and activation sequencing guard.

v2.0.22-elemont

Shanghai execution compatibility

Adds the Shanghai upgrade flag on testnet and updates go-vinu to v1.20.15-quota. Enables EIP-3651 warm coinbase access, EIP-3855 PUSH0, and EIP-3860 initcode metering plus the 49,152-byte initcode limit. Superseded by v2.0.25 because VinuChain's local evmcore transaction path also needed the Shanghai transaction-level gas checks. Shanghai arrives on mainnet with the ELEMONT release on 2026-08-29.

v2.0.21-elemont

SfcV2 automatic delegation backfill

Keeps the Cycle-162 SFC bytecode and adds activation-time node storage repair for the three known live testnet validator-1 delegation rows missing from stakes[]. Also pre-wires mainnet SfcV2 activation to backfill the 82 live mainnet rows audited on 2026-05-17. The repair runs only if each pair still has non-zero getStake, validates whether the row is already present, and handles stale stakePosition values that point at a different stake.

v2.0.20-elemont

Testnet SfcV2Patch6 bytecode release

Adds the SfcV2Patch6 testnet epoch edge and Cycle-162 SFC bytecode. New SFC version 3.0.5 adds registerStake(uint256) for delegator self-registration, owner-only backfillStakes(address[],uint256[]) for bounded batch remediation, and an orphan-tolerant full undelegate-to-zero path for legacy pairs where getStake > 0 but stakePosition == 0. Superseded by v2.0.21 before testnet Patch6 sealed so the known live missing rows are backfilled automatically.

v2.0.19-elemont

Testnet PaybackV2Patch corrected contract rebind

Deployed corrected QuotaContractV2 0x89D1cBD9DEAaB4dFf6f800a336FBDd9A5c6829e4 on 2026-05-16 (tx 0xd99e4111a87dee6b9a16802f9696f5e6663d953ff7de54e43572ab75f8241ce4, owner = recoverable EOA 0xf9c82B1117e8BeA97843042521B8FBC93044f347). Adds Upgrades.PaybackV2Patch = true on testnet so the next epoch seal rebinds Economy.QuotaCacheAddress from the superseded V2 address to the corrected staker-owned withdrawal contract.

v2.0.18-elemont

Testnet PaybackV2 activation (binary-level Quota proxy replacement)

Tagged and deployed to testnet RPC + V1–V4 on 2026-05-15. Flips Upgrades.PaybackV2 = true on VinuChainTestNetRules. At the first epoch seal after binary boot, the seal-time activation branch in gossip/block_processor.go::sealEpochIfNeeded swaps Economy.QuotaCacheAddress from the V1 proxy 0x824B93dE7221cf8a35FBd29d5202f6eFa3A29C5D to QuotaContractV2 at 0xdEA4687FDBA2528d1b30222e199c90b63AF8c850 (deploy tx 0x3ed6fc5e1f0b6c14aaf74f9cfbc611ee5eae7973f4aa10f608d4605020bb505a, owner = recoverable EOA 0xf9c82B1117e8BeA97843042521B8FBC93044f347). Post-release testing on 2026-05-16 found that this deployed V2 address assigns third-party stakeFor(receiver) withdrawal ownership to the receiver; v2.0.19 supersedes it.

v2.0.17-elemont

Payback/Quota receiver staking

Deployed to testnet RPC + validators on 2026-05-10. The node PaybackCache recognizes stakeFor(address) as Payback quota credit for the receiver, preserving same-epoch duration accounting for the refunding address. The V1 receiver-implementation rollout was superseded by v2.0.18-elemont's PaybackV2 binary-level Quota proxy replacement and v2.0.19-elemont's corrected V2 rebind.

v2.0.14-elemont

Testnet consensus flags (Patch5 + ElemontPubkeyValidation)

Cycle-161 SFC bytecode. Adds canonical-pubkey validation (length == 66 && pubkey[0] == 0xc0) at createValidator, _rawCreateValidator, and NodeDriverAuth.updateValidatorPubkey. Off-chain sealer guard ejects validators with malformed stored pubkeys (testnet validator 16) at the next epoch seal. Also: real gasUsedRatio in eth_feeHistory.

v2.0.13-elemont

Same-day scaffolding (no live activation)

Defines flags + ships the deadbeef-placeholder Cycle-161 bytecode; flipped to v2.0.14 same day with the real bytecode and activation. Don't deploy v2.0.13 standalone.

v2.0.12-elemont

Diagnostic + tooling

Multi-SfcV2Patch* divergence warn at single seal; chaindata snapshot producer (scripts/create-chaindata-snapshot.sh with SNAPSHOT_INFO.txt). Non-consensus.

v2.0.11-elemont

Testnet consensus flag (Patch4)

Cycle-160 SFC bytecode. Fixes _lockStake / relockStake: invariant becomes endTime >= ld.endTime.

v2.0.10-elemont

Testnet consensus flag (Patch3)

Cycle-159 SFC bytecode. Fixes inline reentrancy guard (_reentrancyGuardCounter < 2); unblocks delegate, undelegate, withdraw, claimRewards, restakeRewards, stashRewards, createValidator.

v2.0.9-elemont

Trusted-preset entry

Recognizes vitainu-genesis-testnet-20260419.g — fresh installs no longer need --genesis.allowExperimental.

v2.0.8-elemont

Hotfix

Removes validatePeerProgress drift caps so long-offline validators can rejoin.

v2.0.7-elemont

Hotfix

Raises per-peer event-processing quota to 3,250 (matches EventsBufferLimit.Num); kills the warning storm during sync.

v2.0.6-elemont

RPC addition

New vc_getPaybackBalance JSON-RPC method (rate-limited).

v2.0.5-elemont

Testnet consensus flag (Patch2)

Cycle-158 SFC bytecode re-flash at 0xFC00FACE....

v2.0.4-elemont

Internal

lachesis-base bumped to v0.1.6-elemont: vecengine cap, dagprocessor drain, kvdb flushable race fix, gossip deadlock fix.

v2.0.3-elemont

RPC defensive caps

go-vinu fork v1.20.14-quota: batch-size cap (100), in-flight cap (50, configurable), state-override caps.

v2.0.2-elemont

Consensus rules

feeRefund receipt field, 30% base fee burn, cheater fee zeroing, payback fee refunds.

Mainnet activated ELEMONT on 2026-08-29. That release staged Shanghai, Cancun, Prague, SfcV2, PaybackV2, VinuBLS12381, and VinuLatestEVM; the first SfcV2 seal installed Cycle-165 directly and ran the re-derived mainnet delegation backfill. The testnet-only SfcV2Patch* edges do not fire on mainnet.

Activation timing. Consensus flags and seal-bound rebinding (SfcV2, Podgorica, Elemont, Shanghai, Cancun, Prague, VinuBLS12381, VinuLatestEVM, SfcV2Patch2/3/4/5/6, ElemontPubkeyValidation, PaybackV2, PaybackV2Patch, and v2.0.2 rules) activate at the next epoch seal after the binary is first installed or the pending DirtyRules edge is staged (up to MaxEpochDuration = 4h). On skipped-binary boots, v2.x deliberately stages Shanghai before Cancun, Cancun before Prague, Prague before VinuBLS12381, and VinuBLS12381 before VinuLatestEVM; each follow-up flag is staged by the same continuous node after its predecessor seals, without a restart. RPC caps, RPC additions, peer-quota resize, drift-cap removal, eth_feeHistory.gasUsedRatio fix, lachesis-base internals, and non-consensus release hygiene are immediate on restart, no epoch-seal wait.

feeRefund receipt field

Transaction receipts include an optional feeRefund field (hex-encoded wei) for transactions where the sender received a gas refund. The field is omitted when there is no refund — receipts for ineligible senders look identical to pre-upgrade receipts.

The same field also appears on the transaction object returned by eth_getTransactionByHash, eth_getTransactionByBlockHashAndIndex, and eth_getTransactionByBlockNumberAndIndex.

Consumer impact. Most JSON parsers ignore unknown fields → non-breaking. Strict-schema validators must allow optional feeRefund (hex string). Off-chain receipt-hash computers must include it when present.

SFC V2 contract upgrade

When SfcV2 activates, the on-chain SFC contract at 0xfc00face00000000000000000000000000000000 is rewritten with the network's current V2 bytecode. Existing function selectors remain stable — dApps and on-chain contracts calling pre-existing SFC methods continue to work without modification. Cycle-162 added the orphan-delegation recovery helpers; current Cycle-165 retains them. All existing delegations, stakes, and validator registrations remain valid.

Subsequent testnet patches re-flash the same address with newer bytecode at additional epoch seals:

Patch
Introduced
Sealed (testnet)
Bytecode

SfcV2Patch2

v2.0.5

Mid-v2.0.5 boot

Cycle-158 (45,240 bytes)

SfcV2Patch3

v2.0.10

2026-04-19, block 1,424,440

Cycle-159 — inline reentrancy guard fix

SfcV2Patch4

v2.0.11

2026-04-23, block 1,430,436

Cycle-160 — _lockStake / relockStake fix

SfcV2Patch5

v2.0.14

Active by 2026-05-17

Cycle-161 — canonical-pubkey validation

SfcV2Patch6

v2.0.21

2026-05-16, block 1,460,329

Cycle-162 — orphan-delegation auto-backfill

SfcV2Patch7

v2.0.41

2026-06-21, block 1,508,211

Cycle-162 — reward-cursor migration

SfcV2Patch8

v2.0.43

2026-07-08, block 1,529,200

Cycle-163 — self-service reactivation

SfcV2Patch9

v2.0.44

2026-07-08, block 1,529,442

Cycle-164 — reward/reactivation fixes

SfcV2Patch10

v2.0.47

2026-08-20, block 1,585,699

Cycle-165 — chunked-settlement lockup preservation

Cycle-162 extends the ABI with RegisteredStake, registerStake(uint256), and backfillStakes(address[],uint256[]); earlier Cycle-158/159/160/161 selectors remain stable. Binary startup guards (sfc.EnforcePatch4StartupCheck, sfc.EnforcePatch5StartupCheck, and sfc.EnforcePatch6StartupCheck) refuse to start a build with invalid embedded SFC patch bytecode.

Blockscout verification. Bytecode swaps via the evmwriter precompile bypass Blockscout's normal contract-discovery path. After each seal, re-verify with: DELETE the stale smart_contracts row, UPDATE addresses.contract_code with fresh eth_getCode, then POST /api/v2/smart-contracts/.../verification/via/flattened-code. Solc settings: 0.5.17+commit.d19bba13, --optimize --optimize-runs=10000 --evm-version=istanbul. Source: vinuchain-lists/contracts/vinuchain/SFC.sol.

EIP-7702 set-code transactions

When Prague is active, VinuChain accepts EIP-7702 set-code transactions (type: 0x04). These transactions carry an authorizationList; each authorization can install or clear a delegation designator on an EOA. The installed code shape is 0xef0100 followed by the 20-byte target address. Contract calls to the delegated EOA execute one level of target code while preserving the delegated EOA as the account being called.

Important boundaries:

  • Blob transactions (type: 0x03) remain unsupported and are rejected.

  • Set-code transactions must have a non-empty authorizationList and a concrete to address; they cannot be contract creations.

  • Authorization chainId, r, and s fields must fit uint256 bounds. Invalid authorization signatures are skipped according to EIP-7702, but malformed over-width tuple values are rejected before execution.

  • EIP-3607 sender validation is relaxed only after Prague and only for accounts whose code is a valid EIP-7702 delegation designator.

  • JSON-RPC transaction objects include authorizationList for set-code transactions. Existing non-set-code transaction responses are unchanged.

  • No contracts, ABIs, token lists, SFC bytecode, or deployed-address registries change for this upgrade.

BLS12-381 and latest-EVM surfaces

VinuBLS12381 and VinuLatestEVM are intentionally separate VinuChain fork flags. BLS activates first; latest-EVM activates only after BLS is already sealed. This avoids bundling every new precompile, opcode, and gas-rule change into one epoch seal.

After VinuBLS12381 is active:

  • eth_config.current.precompiles includes BLS12_G1ADD, BLS12_G1MSM, BLS12_G2ADD, BLS12_G2MSM, BLS12_PAIRING_CHECK, BLS12_MAP_FP_TO_G1, and BLS12_MAP_FP2_TO_G2.

  • The active precompile addresses are 0x0b through 0x11.

  • Mainnet also has this flag active since the 2026-08-29 ELEMONT upgrade; it is no longer testnet-only.

After VinuLatestEVM is active:

  • eth_config.current.precompiles includes P256VERIFY at 0x0000000000000000000000000000000000000100.

  • CLZ and MODEXP bounds/repricing are active through the go-vinu EVM.

  • Transactions above the per-transaction gas cap are rejected consistently in txpool, state transition, and block execution; eth_estimateGas caps estimates at the same limit.

  • Mainnet also has this flag active since the 2026-08-29 ELEMONT upgrade; it is no longer testnet-only.

Before either flag seals, eth_config continues to show the last sealed configuration. Use vc_getRules("latest") after each epoch seal to verify the rule bit, then re-run precompile/opcode smoke checks.

30% base fee burn

When SfcV2 is active, 30% of each transaction's base fee is burned. The remaining 70% of the base fee plus all priority tips continue to flow to the validator.

  • Priority tips are never burned.

  • Refunds are calculated first, then the burn is applied to what remains.

  • Burned funds accumulate at the zero address 0x0000…0000. There is no separate burn counter — indexers tracking circulating supply should subtract the zero-address balance.

Cheater fee zeroing

When Elemont is active, validators flagged as cheaters in an epoch lose all their accumulated transaction fees for that epoch at SealEpoch time — including fees from blocks they produced before being flagged.

Payback fee refunds

Stakers meeting the minimum V2 Quota stake threshold automatically receive gas refunds. No new VC is created — refunds redistribute fees from validator earnings to eligible stakers. On the corrected 2026-05-16 testnet deployment, the initial QuotaContractV2.minStake() value is 1000 VC; the Quota owner can update this parameter later if protocol economics change.

  1. User submits a transaction; full gasUsed × gasPrice is debited as before.

  2. Full fee is credited to the validator pre-refund.

  3. After epoch seal, the payback system queries the sender's stake. If eligible, a refund is returned from the validator's earned fees.

  4. Validator earnings decrease by the refund; sender balance increases by it.

With PaybackV2, a funding wallet may call QuotaContractV2.stakeFor(receiver) instead of stake(). The receiver receives Payback quota credit, so refunds still follow the transaction sender: the receiver gets refunds for transactions the receiver signs, while the funding wallet does not gain refund eligibility from that delegated stake. The funding wallet keeps ownership of the VC it funded and must use unstakeFor(receiver, amount) to begin withdrawing that stake back to itself. The receiver's total V2 Quota stake must be at least minStake() before those signed transactions can receive refunds.

The minimum stake is only an eligibility floor, not a spam throttle that grows automatically. Each refund is capped by the sender's available Payback quota, and every refunded transaction consumes quota for that epoch. If an eligible wallet sends enough transactions to exhaust its quota, later transactions receive smaller refunds or feeRefund: 0x0; they still pay normal gas. When network congestion pushes the base fee above the chain-configured floor, Payback refunds are suppressed so fee escalation can still deter spam.

The feeRefund receipt field reports the refund amount. dApps showing "gas spent" should subtract feeRefund from gasUsed × effectiveGasPrice.

vc_getPaybackBalance

Field
Value

Namespace

vc (not eth)

Method

vc_getPaybackBalance

Params

[address] (20-byte hex). Optional second param: block tag (default "latest").

Returns

Hex-encoded wei. Returns 0x0 for the zero address, when Podgorica is inactive, or sub-minimum stake.

Rate limit

8 in-flight, 2 s acquire timeout. Rejection error -32005 payback query rate-limited.

The vc namespace is intentionally separate from eth — the accessor is RPC-safe (never reads/writes PaybackCache.blkCtx, never mutates StakesMap), so concurrent RPC traffic cannot corrupt block-processing state.

JSON-RPC defensive caps

Cap
RPC method(s)
Limit
Error on exceed

Batch size

Any batched call

100 messages per batch

invalid request: batch too large

In-flight concurrency

All HTTP & WS RPC

50 concurrent (--rpc.maxconcurrent N to tune; 0 to disable)

HTTP 503

StateOverride.code size

eth_call, eth_estimateGas, debug_traceCall

24,576 bytes per account

code size exceeds MaxCodeSize

StateOverride.stateDiff entries

same as above

1,000 entries per account

stateDiff size exceeds 1000 entries

feeRefund P2P ingress

Internal (peer RLP decoding)

32 bytes / 256 bits

Peer drops the receipt

Graceful shutdown

Any RPC method during shutdown

Handler returns proper JSON-RPC error

handler is stopping

Indexers batching block-range queries should paginate at ≤100 messages. Heavy analytics workloads can raise concurrency with --rpc.maxconcurrent N or distribute across endpoints.

Pruning

Operator-facing controls for managing chaindata size on long-lived nodes.

Surface
Purpose

--prune-keep-epochs <N>

Retain the last N sealed epochs of state; prune older. Negative values are rejected with a clear error (previously wrapped to large unsigned values and pruned everything).

--prune-keep-blocks <N>

Same semantics, applied to receipt/log retention.

opera snapshot prune-receipts

One-shot subcommand for fine-grained receipt retention control outside the live retention flags.

Crash-safe. If a prune operation is interrupted (node crash, OOM kill), the next startup automatically resumes the interrupted prune — no manual intervention. The Snapshots count=128 default produces enough snapshot density for prune to find recoverable boundaries on restart.

Other reliability fixes

  • Peer-progress drift caps removed (v2.0.8). validatePeerProgress no longer rejects peers more than 1,000 epochs / 5,000 blocks ahead. The deeper acceptance gate (lightCheck, epochcheck.ErrNotRelevant) already prevents abuse.

  • Per-peer event quota raised (v2.0.7). peerEventQuota and peerStreamQuota raised from 200/100 to 3,250 (matches EventsBufferLimit.Num). DoS guarantee preserved by Config.Validate() — a single peer is bounded to ≤50% of capacity.

  • Tracing. trace_filter with Count==0 caps at 10,000 entries (was unbounded). Span-leak fix on tracing on/off. traceBlock bounds-checks malformed receipts.

  • eth_feeHistory copies the tips slice per entry (was sharing backing array — mutations cross-contaminated).

  • Gas accounting. Block-vote gas calc uses overflow-safe addition. Gas oracle guards against MaxAllocPeriod=0. MinGasPrice=0 is rejected.

  • EVM. eth_call enforces MaxCodeSize even when code comes from stateOverride.


Last updated: 2026-08-24 · latest guide target v2.0.49-elemont, deployed fleet-wide 2026-08-24 (non-consensus security baseline; all testnet rules and state unchanged). Recovery snapshot and fresh-install bootstrap: the v2.0.47-elemont post-Patch10 object above.

Last updated