Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
d4c7e7d
Add high availabiliy via raft
alpe Nov 12, 2025
820b9a3
Prefent duplicate peers
alpe Nov 12, 2025
35cf0c8
Merge branch 'main' into alex/adr023_ha-failover_raft7
alpe Nov 17, 2025
45a6e27
Go mod tidy
alpe Nov 17, 2025
3111158
Merge branch 'main' into alex/adr023_ha-failover_raft7
alpe Nov 17, 2025
4562ded
Minor updates
alpe Nov 17, 2025
4d47754
Merge branch 'main' into alex/adr023_ha-failover_raft7
alpe Nov 18, 2025
0804346
Fix test
alpe Nov 18, 2025
1c2e3f1
Leadership fix
alpe Nov 18, 2025
c320a7a
Fix test
alpe Nov 18, 2025
72ec5fe
Remove sleep
alpe Nov 19, 2025
b34d7a0
Increase buffer size for raft msgs
alpe Nov 19, 2025
7af5d1a
Merge branch 'main' into alex/adr023_ha-failover_raft7
alpe Nov 20, 2025
406377e
Review feedback
alpe Nov 20, 2025
0ff25b8
Merge branch 'main' into alex/adr023_ha-failover_raft7
alpe Nov 20, 2025
b92a67f
Merge branch 'main' into alex/adr023_ha-failover_raft7
alpe Nov 21, 2025
406ad8b
Add replace to go.mod
alpe Nov 21, 2025
1337bc6
Merge branch 'main' into alex/adr023_ha-failover_raft7
alpe Nov 24, 2025
abfa8d3
Fix merge conflicts
alpe Nov 24, 2025
aebbdff
Linter fix
alpe Nov 24, 2025
50d7caf
Minor test update
alpe Nov 24, 2025
5de9f0e
Remove store.Sync
alpe Nov 25, 2025
30094b2
Merge branch 'main' into alex/adr023_ha-failover_raft7
alpe Dec 3, 2025
695324e
Merge
alpe Dec 3, 2025
2463919
Add last submitted da heights to raft
alpe Dec 3, 2025
3e1cbca
Make test compile again
alpe Dec 4, 2025
567092f
Merge branch 'main' into alex/adr023_ha-failover_raft8
alpe Jan 6, 2026
640924b
Complete merge
alpe Jan 6, 2026
11038cd
Merge branch 'main' into alex/adr023_ha-failover_raft8
alpe Jan 7, 2026
095f882
Fix integration test
alpe Jan 7, 2026
99afdad
Review feedback and linting
alpe Jan 7, 2026
3f7f431
Convert raft state into proto type
alpe Jan 7, 2026
25a6185
Fix import and e2e tests
alpe Jan 8, 2026
adc05ed
Cufigurable leader_lease_timeout
alpe Jan 8, 2026
9b0bff4
Merge branch 'main' into alex/adr023_ha-failover_raft8
alpe Jan 9, 2026
49ba50f
Log raft state height when passing leadership
alpe Jan 9, 2026
00ae050
Recover with raft state
alpe Jan 12, 2026
490b286
Ensure block hash in state check
alpe Jan 12, 2026
d7fbf79
Merge branch 'main' into alex/adr023_ha-failover_raft8
alpe Jan 12, 2026
dfa2204
Merge branch 'main' into alex/adr023_ha-failover_raft8
alpe Jan 15, 2026
7edca17
x
alpe Jan 14, 2026
6502a47
More safety features, including db.sync
alpe Jan 14, 2026
a52d538
Ensure safe restart
alpe Jan 15, 2026
3203ce6
x
alpe Jan 15, 2026
1cf1167
Merge branch 'main' into alex/adr023_ha-failover_raft11
alpe Jan 16, 2026
e4e94f2
Resolve conflicts
alpe Jan 16, 2026
e444215
Fix test setup
alpe Jan 18, 2026
3b4fe3f
Fix dummyDA
alpe Jan 19, 2026
9b80c74
Merge branch 'main' into alex/adr023_ha-failover_raft11
alpe Jan 19, 2026
67d1ce7
Merge branch 'main' into alex/adr023_ha-failover_raft11
alpe Jan 26, 2026
51edca8
Review feedback
alpe Jan 26, 2026
5fc0b6b
Add grace period for test
alpe Jan 26, 2026
e8f9db0
Add raft doc
alpe Jan 27, 2026
c9b8166
Available ports for e2e tests
alpe Jan 27, 2026
acce8e4
Review feedback
alpe Jan 27, 2026
c1ef1d5
Merge branch 'main' into alex/adr023_ha-failover_raft11
alpe Jan 27, 2026
938f908
Fix integration test
alpe Jan 27, 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
Prev Previous commit
Next Next commit
Merge branch 'main' into alex/adr023_ha-failover_raft8
* main: (34 commits)
  feat: make reaper poll duration configurable (#2951)
  chore!: move sequencers to pkg (#2931)
  feat: Ensure Header integrity on DA (#2948)
  feat(testda): add header support with GetHeaderByHeight method (#2946)
  chore: improve code comments clarity (#2947)
  chore(sequencers): optimize store check (#2945)
  fix: make evm_execution more robust (#2942)
  fix(sequencers/single): deterministic queue (#2938)
  fix(block): fix init logic sequencer for da epoch fetching (#2926)
  feat: use DA timestamp (#2939)
  chore: improve code comments clarity (#2943)
  build(deps): bump libp2p (#2937)
  build(deps): Bump actions/cache from 4 to 5 (#2934)
  build(deps): Bump actions/download-artifact from 6 to 7 (#2933)
  build(deps): Bump actions/upload-artifact from 5 to 6 (#2932)
  feat: DA Client remove interface part 3, replace types with new code (#2910)
  DA Client remove interface: Part 2.5, create e2e test to validate that a blob is posted in DA layer. (#2920)
  fix(syncing): skip forced txs checks for p2p blocks (#2922)
  build(deps): Bump the all-go group across 5 directories with 5 updates (#2919)
  chore: loosen syncer state check (#2927)
  ...
  • Loading branch information
alpe committed Jan 6, 2026
commit 567092f1bd766953b76caa0d7bb24d169d33ee2e
40 changes: 39 additions & 1 deletion apps/evm/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,45 @@ var RunCmd = &cobra.Command{
return err
}

return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, nodeKey, datastore, nodeConfig, genesis, node.NodeOptions{})
// Start force inclusion API server if address is provided
forceInclusionAddr, err := cmd.Flags().GetString(flagForceInclusionServer)
if err != nil {
return fmt.Errorf("failed to get '%s' flag: %w", flagForceInclusionServer, err)
}

if forceInclusionAddr != "" {
ethURL, err := cmd.Flags().GetString(evm.FlagEvmEthURL)
if err != nil {
return fmt.Errorf("failed to get '%s' flag: %w", evm.FlagEvmEthURL, err)
}

forceInclusionServer, err := server.NewForceInclusionServer(
forceInclusionAddr,
daClient,
nodeConfig,
genesis,
logger,
ethURL,
)
if err != nil {
return fmt.Errorf("failed to create force inclusion server: %w", err)
}

if err := forceInclusionServer.Start(cmd.Context()); err != nil {
return fmt.Errorf("failed to start force inclusion API server: %w", err)
}

// Ensure server is stopped when node stops
defer func() {
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := forceInclusionServer.Stop(shutdownCtx); err != nil {
logger.Error().Err(err).Msg("failed to stop force inclusion API server")
}
}()
}

return rollcmd.StartNode(logger, cmd, executor, sequencer, nodeKey, datastore, nodeConfig, genesis, node.NodeOptions{})
},
}

Expand Down
223 changes: 14 additions & 209 deletions apps/evm/go.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/grpc/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ The execution client must implement the Evolve execution gRPC interface.`,
}

// Start the node
return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, nodeKey, datastore, nodeConfig, genesis, node.NodeOptions{})
return rollcmd.StartNode(logger, cmd, executor, sequencer, nodeKey, datastore, nodeConfig, genesis, node.NodeOptions{})
},
}

Expand Down
224 changes: 14 additions & 210 deletions apps/grpc/go.sum

Large diffs are not rendered by default.

15 changes: 12 additions & 3 deletions apps/testapp/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ import (
"github.com/evstack/ev-node/block"
coresequencer "github.com/evstack/ev-node/core/sequencer"
"github.com/evstack/ev-node/node"
rollcmd "github.com/evstack/ev-node/pkg/cmd"
genesispkg "github.com/evstack/ev-node/pkg/genesis"
"github.com/evstack/ev-node/pkg/cmd"
"github.com/evstack/ev-node/pkg/config"
blobrpc "github.com/evstack/ev-node/pkg/da/jsonrpc"
da "github.com/evstack/ev-node/pkg/da/types"
"github.com/evstack/ev-node/pkg/genesis"
"github.com/evstack/ev-node/pkg/p2p"
"github.com/evstack/ev-node/pkg/p2p/key"
"github.com/evstack/ev-node/pkg/sequencers/based"
"github.com/evstack/ev-node/pkg/sequencers/single"
Expand Down Expand Up @@ -92,7 +96,12 @@ var RunCmd = &cobra.Command{
return err
}

return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, nodeKey, datastore, nodeConfig, genesis, node.NodeOptions{})
p2pClient, err := p2p.NewClient(nodeConfig.P2P, nodeKey.PrivKey, datastore, genesis.ChainID, logger, p2p.NopMetrics())
if err != nil {
return err
}

return cmd.StartNode(logger, command, executor, sequencer, p2pClient, datastore, nodeConfig, genesis, node.NodeOptions{})
},
}

Expand Down
227 changes: 16 additions & 211 deletions apps/testapp/go.sum

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion block/internal/executing/executor_restart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,11 +323,15 @@ func TestExecutor_RestartNoPendingHeader(t *testing.T) {
mockExec1.EXPECT().ExecuteTxs(mock.Anything, mock.Anything, gen.InitialHeight+uint64(i), mock.AnythingOfType("time.Time"), lastStateRoot).
Return(newStateRoot, uint64(1024), nil).Once()
lastStateRoot = newStateRoot

require.NoError(t, exec1.produceBlock())
}
require.Equal(t, uint64(numBlocks), exec1.GetLastState().LastBlockHeight)

mockSeq1.EXPECT().GetDAHeight().Return(uint64(0)).Once()

err = exec1.produceBlock()
require.NoError(t, err)

// Stop first executor
exec1.cancel()

Expand Down
33 changes: 23 additions & 10 deletions block/internal/syncing/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ package syncing
import (
"bytes"
"context"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"reflect"
"sync"
"reflect"
"sync/atomic"
"time"

coreexecutor "github.com/evstack/ev-node/core/execution"
"github.com/evstack/ev-node/pkg/raft"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/rs/zerolog"
Expand All @@ -22,7 +21,6 @@ import (
"github.com/evstack/ev-node/block/internal/common"
"github.com/evstack/ev-node/block/internal/da"
"github.com/evstack/ev-node/pkg/config"
datypes "github.com/evstack/ev-node/pkg/da/types"
"github.com/evstack/ev-node/pkg/genesis"
"github.com/evstack/ev-node/pkg/store"
"github.com/evstack/ev-node/types"
Expand Down Expand Up @@ -104,6 +102,7 @@ type Syncer struct {
daRetriever DARetriever
p2pHandler p2pHandler
raftRetriever *raftRetriever
fiRetriever *da.ForcedInclusionRetriever

// Forced inclusion tracking
pendingForcedInclusionTxs sync.Map // map[string]pendingForcedInclusionTx
Expand Down Expand Up @@ -144,22 +143,37 @@ func NewSyncer(
errorCh chan<- error,
raftNode common.RaftNode,
) *Syncer {
daRetrieverHeight := &atomic.Uint64{}
daRetrieverHeight.Store(genesis.DAStartHeight)

// Initialize dynamic grace period state
initialMultiplier := 1.0
gracePeriodMultiplier := &atomic.Pointer[float64]{}
gracePeriodMultiplier.Store(&initialMultiplier)

initialFullness := 0.0
blockFullnessEMA := &atomic.Pointer[float64]{}
blockFullnessEMA.Store(&initialFullness)

s := &Syncer{
store: store,
exec: exec,
daClient: daClient,
cache: cache,
metrics: metrics,
config: config,
genesis: genesis,
options: options,
lastState: &atomic.Pointer[types.State]{},
daClient: daClient,
daRetrieverHeight: daRetrieverHeight,
headerStore: headerStore,
dataStore: dataStore,
lastState: &atomic.Pointer[types.State]{},
daRetrieverHeight: &atomic.Uint64{},
heightInCh: make(chan common.DAHeightEvent, 1_000),
errorCh: errorCh,
logger: logger.With().Str("component", "syncer").Logger(),
gracePeriodMultiplier: gracePeriodMultiplier,
blockFullnessEMA: blockFullnessEMA,
gracePeriodConfig: newForcedInclusionGracePeriodConfig(),
}
if raftNode != nil && !reflect.ValueOf(raftNode).IsNil() {
s.raftRetriever = newRaftRetriever(raftNode, genesis, logger, eventProcessorFn(s.pipeEvent), func(ctx context.Context, state *raft.RaftBlockState) error {
Expand Down Expand Up @@ -227,7 +241,6 @@ func (s *Syncer) Stop() error {
s.cancel = nil
return nil
}

// isCatchingUpState returns true if the syncer has pending events or is behind the current raft height
func (s *Syncer) isCatchingUpState() bool {
Comment thread
alpe marked this conversation as resolved.
Outdated
return len(s.heightInCh) != 0 || func() bool {
Expand All @@ -242,8 +255,8 @@ func (s *Syncer) isCatchingUpState() bool {
}()
}

// GetLastState returns the current state
func (s *Syncer) GetLastState() types.State {
// getLastState returns the current state
func (s *Syncer) getLastState() types.State {
state := s.lastState.Load()
if state == nil {
return types.State{}
Expand Down
21 changes: 21 additions & 0 deletions block/public.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,26 @@ func NewDAClient(
})
}

// ErrForceInclusionNotConfigured is returned when force inclusion is not configured.
// It is exported because sequencers needs to check for this error.
var ErrForceInclusionNotConfigured = da.ErrForceInclusionNotConfigured

// ForcedInclusionEvent represents forced inclusion transactions retrieved from DA
type ForcedInclusionEvent = da.ForcedInclusionEvent

// ForcedInclusionRetriever defines the interface for retrieving forced inclusion transactions from DA
type ForcedInclusionRetriever interface {
RetrieveForcedIncludedTxs(ctx context.Context, daHeight uint64) (*da.ForcedInclusionEvent, error)
}

// NewForcedInclusionRetriever creates a new forced inclusion retriever
func NewForcedInclusionRetriever(
client DAClient,
logger zerolog.Logger,
daStartHeight, daEpochSize uint64,
) ForcedInclusionRetriever {
return da.NewForcedInclusionRetriever(client, logger, daStartHeight, daEpochSize)
}

// Expose Raft types for consensus integration
type RaftNode = common.RaftNode
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.