Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
24af316
Update Narya to latest Zen 5 verification optimizations
7layermagik Sep 12, 2026
5085453
Overlap Turbine signature verification with shred arrival
7layermagik Sep 12, 2026
443ab51
Document Zen 5 streaming verification and execution contention results
7layermagik Sep 12, 2026
166ed56
Avoid rebuilding cached shred component buffers at completion
7layermagik Sep 12, 2026
9a30c69
Reduce completion ordering and root work; bundle ready verification g…
7layermagik Sep 13, 2026
f35a851
Make streaming tests independent of FEC acceleration
7layermagik Sep 13, 2026
3f0da73
Allocate each prepared component transaction view once
7layermagik Sep 13, 2026
0f8e8b0
Document standalone streaming validation and live trial scope
7layermagik Sep 13, 2026
8944527
Improve leader packing and add near-limit synthetic block tests
7layermagik Sep 13, 2026
403305b
Document current-base leader benchmarks and finalized load results
7layermagik Sep 13, 2026
91c268f
Reduce VM allocation and observer overhead before Alpenglow voting
7layermagik Sep 13, 2026
7fef571
Fix Alpenglow Votor certificate compatibility with Firedancer
7layermagik Sep 13, 2026
fd12b56
Add opt-in durable signing reservations and restart voting bounds
7layermagik Sep 14, 2026
6f92f8f
Persist reserved vote history with one ordered background writer
7layermagik Sep 14, 2026
622053c
Order live vote admission and durable pruning behind replay
7layermagik Sep 14, 2026
55ed3b9
Advance replay progress without waiting for certificate verification
7layermagik Sep 14, 2026
4a5a976
Move transaction-status checkpoint encoding off the replay loop
7layermagik Sep 14, 2026
f03c60e
Document consolidated validator review, benchmarks and validation
7layermagik Sep 14, 2026
b24de8e
Preserve raw test-log whitespace in generated evidence
7layermagik Sep 14, 2026
667d002
Bound scheduler transaction references in both priority heaps
7layermagik Sep 14, 2026
bcada83
Run validator race regressions in CI and document queue bounds
7layermagik Sep 14, 2026
d1172b9
Fix vote deque ownership, prefetch reset accounting and voting startu…
7layermagik Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Keep raw benchmark evidence available without overwhelming the review.
# Retain raw Go CPU padding and test-framework space/tab indentation.
docs/results/**/*.json linguist-generated=true
docs/results/**/*.jsonl linguist-generated=true
docs/results/**/*.txt linguist-generated=true whitespace=-blank-at-eol
docs/results/**/*.log linguist-generated=true -whitespace
docs/results/**/*.tar.gz linguist-generated=true
28 changes: 28 additions & 0 deletions .github/workflows/go_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,31 @@ jobs:

- name: Build
run: go build -v ./cmd/mithril

regression-tests:
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
env:
GOMAXPROCS: "2"
steps:
- uses: actions/checkout@v3

- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: 1.26.4

- name: Voting, checkpoint, streaming and scheduler race regressions
# Run the complete affected package suites, including subprocess crash
# recovery and cancellation tests. The independent sealevel suite has
# known base-branch failures documented in the validation report.
run: >-
go test -race -p 2 -count=1
./pkg/alpenglow ./pkg/consensus ./pkg/replay
./pkg/turbine ./pkg/sigverify ./pkg/blockprod/...
./cmd/mithril/node ./cmd/mithril/configcmd

- name: Vote-program deque ownership race regression
run: go test -race -count=1 ./pkg/sealevel -run '^TestProcessNewVoteStateOwnsRetainedDeque$'
8 changes: 7 additions & 1 deletion cmd/mithril/configcmd/configcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,13 @@ max_rps = 8 # Verifier's own RPC budget (never shares the block-fe
# ── Replay tuning ────────────────────────────────────────────────────────
[tuning]
txpar = 24 # Validator auto-defaults to 2x CPU cores only when unset; explicit 0 = sequential
sigverify_backend = "auto" # auto|r51|generic|stdlib; stdlib uses Go's crypto/ed25519 impl after strict checks.
use_pool = true # Reuse execution buffers to reduce allocation

[sigverify]
backend = "auto" # auto|r51|generic|stdlib
workers = 0 # 0 = min(2, GOMAXPROCS); explicit value overrides the shared transaction pool
batch_target = 8 # 4 or 8 signature lanes; available work runs immediately
disable_shred_overlap = false # Diagnostic fallback: verify after complete block assembly

# ── Mithril's RPC server ─────────────────────────────────────────────────
[rpc]
Expand Down
25 changes: 25 additions & 0 deletions cmd/mithril/configcmd/configcmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package configcmd

import (
"strings"
"testing"

"github.com/spf13/viper"
"github.com/stretchr/testify/require"
)

func TestStarterConfigSignatureVerification(t *testing.T) {
for _, validator := range []bool{false, true} {
v := viper.New()
v.SetConfigType("toml")
require.NoError(t, v.ReadConfig(strings.NewReader(generateStarterConfig(validator))))
require.Equal(t, "auto", v.GetString("sigverify.backend"))
require.True(t, v.IsSet("sigverify.workers"))
require.Zero(t, v.GetInt("sigverify.workers"))
require.Equal(t, 8, v.GetInt("sigverify.batch_target"))
require.True(t, v.IsSet("sigverify.disable_shred_overlap"))
require.False(t, v.GetBool("sigverify.disable_shred_overlap"))
require.True(t, v.GetBool("tuning.use_pool"))
require.False(t, v.IsSet("tuning.sigverify_backend"))
}
}
213 changes: 128 additions & 85 deletions cmd/mithril/node/node.go

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion cmd/mithril/node/sigverify_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ func startSigverifyReporter(ctx context.Context) {
// against, and so the resolved backend is recorded even on a node that
// exits before the first tick.
previous := sigverify.Stats()
mlog.NamedFilef("sigverify", "startup: %s", previous)
mlog.NamedFilef("sigverify", "startup: %s workers=%d batch_target=%d shred_overlap=%t", previous,
sigverify.TransactionWorkers(), sigverify.TransactionBatchTarget(), !sigverify.Cfg.DisableShredOverlap)

for {
select {
Expand Down
40 changes: 40 additions & 0 deletions cmd/mithril/node/vote_startup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package node

import (
"fmt"
"math"
"strconv"

"github.com/Overclock-Validator/mithril/pkg/alpenglow"
"github.com/Overclock-Validator/mithril/pkg/config"
"github.com/spf13/cobra"
)

func configuredWaitToVoteSlot(cmd *cobra.Command) (uint64, error) {
if flag := cmd.Flags().Lookup("wait-to-vote-slot"); flag != nil && flag.Changed {
return cmd.Flags().GetUint64("wait-to-vote-slot")
}
const key = "validator.wait_to_vote_slot"
if !config.IsSet(key) {
return 0, nil
}
// Unlike GetUint64, parsing explicitly must not turn an invalid operator
// cutoff into zero and silently remove the requested voting restriction.
slot, err := strconv.ParseUint(config.GetString(key), 10, 64)
if err != nil {
return 0, fmt.Errorf("%s must be an unsigned 64-bit slot: %w", key, err)
}
return slot, nil
}

// The operator cutoff can postpone voting but cannot weaken the existing
// startup guard. Equality permits voting, subject to all other Votor checks.
func effectiveWaitToVoteSlot(startupWallSlot, configured uint64) uint64 {
automatic := startupWallSlot - startupWallSlot%alpenglow.LeaderWindowSlots
if automatic <= math.MaxUint64-2*alpenglow.LeaderWindowSlots {
automatic += 2 * alpenglow.LeaderWindowSlots
} else {
automatic = math.MaxUint64
}
return max(automatic, configured)
}
73 changes: 73 additions & 0 deletions cmd/mithril/node/vote_startup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package node

import (
"math"
"strings"
"testing"

"github.com/Overclock-Validator/mithril/pkg/config"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
)

func TestConfiguredWaitToVoteSlot(t *testing.T) {
for _, tc := range []struct {
name, toml, cli string
want uint64
invalid bool
}{
{name: "default"},
{name: "toml", toml: "wait_to_vote_slot = 1234", want: 1234},
{name: "cli wins", toml: "wait_to_vote_slot = 1234", cli: "5678", want: 5678},
{name: "explicit zero wins", toml: "wait_to_vote_slot = 1234", cli: "0"},
{name: "maximum CLI", cli: "18446744073709551615", want: math.MaxUint64},
{name: "negative TOML", toml: "wait_to_vote_slot = -1", invalid: true},
{name: "fractional TOML", toml: "wait_to_vote_slot = 1.5", invalid: true},
{name: "malformed TOML value", toml: `wait_to_vote_slot = "oops"`, invalid: true},
{name: "empty TOML value", toml: `wait_to_vote_slot = ""`, invalid: true},
{name: "overflow TOML value", toml: `wait_to_vote_slot = "18446744073709551616"`, invalid: true},
{name: "negative CLI", cli: "-1", invalid: true},
{name: "overflow CLI", cli: "18446744073709551616", invalid: true},
} {
t.Run(tc.name, func(t *testing.T) {
viper.Reset()
t.Cleanup(viper.Reset)
config.ApplyDefaults(viper.GetViper())
viper.SetConfigType("toml")
require.NoError(t, viper.ReadConfig(strings.NewReader("[validator]\n"+tc.toml)))
cmd := &cobra.Command{}
cmd.Flags().Uint64("wait-to-vote-slot", 0, "")
var err error
if tc.cli != "" {
err = cmd.Flags().Set("wait-to-vote-slot", tc.cli)
}
var got uint64
if err == nil {
got, err = configuredWaitToVoteSlot(cmd)
}
if tc.invalid {
require.Error(t, err)
return
}
require.NoError(t, err)
require.Equal(t, tc.want, got)
})
}
require.NotNil(t, Run.Flags().Lookup("wait-to-vote-slot"))
}

func TestEffectiveWaitToVoteSlot(t *testing.T) {
for _, tc := range []struct{ startup, configured, want uint64 }{
{100, 0, 108},
{103, 0, 108},
{103, 104, 108},
{103, 108, 108},
{103, 123, 123}, // Operator cutoff need not align with a leader window.
{103, math.MaxUint64, math.MaxUint64},
{math.MaxUint64 - 7, 0, math.MaxUint64},
{math.MaxUint64, 0, math.MaxUint64},
} {
require.Equal(t, tc.want, effectiveWaitToVoteSlot(tc.startup, tc.configured), "%+v", tc)
}
}
54 changes: 46 additions & 8 deletions config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,25 @@ name = "mithril"
# Signature-verification workers (0 = GOMAXPROCS).
tpu_sigverify_workers = 0

# Optional minimum slot for NEW votes (inclusive), also --wait-to-vote-slot.
# Useful when rejoining after recovery. CLI overrides this setting.
# Zero adds no operator cutoff; the automatic startup cutoff and normal
# consensus checks still apply. A lower value cannot bypass those checks.
# Replay/repair continue while waiting. Previously recorded, authenticated
# votes can still be restored/rebroadcast under the existing recovery rules.
# This does not coordinate a cluster restart or wait for supermajority,
# and does not allow resetting a corrupt vote-history file.
wait_to_vote_slot = 0

# Bounded cross-slot TPU queue. Zero keeps the 131,072-transaction default.
# Larger queues can prefill four busy leader slots, using additional memory.
tpu_max_buffered_transactions = 0

# Milliseconds reserved for local finalization and broadcast, not consensus
# finality. Zero keeps the conservative 75ms default. Tune from measured
# completion margins; this does not change the protocol slot deadline.
block_completion_reserve_ms = 0

# ============================================================================
# [consensus] - Alpenglow Consensus
# ============================================================================
Expand Down Expand Up @@ -524,14 +543,6 @@ name = "mithril"
# Number of borrowed accounts to preallocate in arena (0 to disable)
borrowed_account_arena_size = 1024

# ed25519 signature verification backend.
# auto - use the AVX-512 accelerated backend when the CPU has
# AVX512-IFMA (Zen 4/5, Ice Lake and newer), else portable
# r51 - force the accelerated backend; startup fails without AVX512-IFMA
# generic - force the portable pure-Go backend
# stdlib - use Go’s crypto/ed25519 implementation after the mandatory strict rejection checks.
sigverify_backend = "auto"

# Enable/disable pool allocator for slices
use_pool = true

Expand Down Expand Up @@ -574,6 +585,33 @@ name = "mithril"
# Filename to write CPU profile (for offline analysis with go tool pprof)
# cpu_profile_path = "/mnt/mithril-data/profiling/cpu.pprof"

# ============================================================================
# [sigverify] - Transaction Signature Verification
# ============================================================================

[sigverify]
# ed25519 backend: auto selects AVX-512 IFMA when available, else portable.
# r51 requires AVX-512 IFMA; generic and stdlib force portable backends.
# Strict signature checks are always enabled. The older
# tuning.sigverify_backend key remains supported when this key is absent.
backend = "auto"

# Shared Turbine transaction verification workers; 0 = min(2, GOMAXPROCS).
# Leaves execution and shred/consensus processing room to run concurrently.
# This does not change validator.tpu_sigverify_workers or replay's fallback pool.
workers = 0

# Signature lanes per group: 4 or 8 (0 also means 8). Transactions stay
# indivisible, so a multisignature transaction may exceed this target.
# Ready short groups run immediately; no timer waits for more shreds.
batch_target = 8

# Decode complete entry batches and verify while later shreds arrive.
# Set true to compare against completion-only verification.
# Early work reserves at most 8 slots and 64 MiB of encoded component bytes;
# decoded transactions and Go bookkeeping use additional heap memory.
disable_shred_overlap = false

# ============================================================================
# [debug] - Debug Logging
# ============================================================================
Expand Down
Loading
Loading