Skip to content

Commit 0dedb82

Browse files
committed
feat: fill in validator hasher
1 parent 4fbb330 commit 0dedb82

File tree

14 files changed

+108
-48
lines changed

14 files changed

+108
-48
lines changed

apps/evm/based/cmd/run.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
coreda "github.com/rollkit/rollkit/core/da"
1212
"github.com/rollkit/rollkit/execution/evm" // Import the evm flags package
13+
"github.com/rollkit/rollkit/node"
1314

1415
"github.com/rollkit/rollkit/da/jsonrpc"
1516
rollcmd "github.com/rollkit/rollkit/pkg/cmd"
@@ -172,7 +173,7 @@ func NewExtendedRunNodeCmd(ctx context.Context) *cobra.Command {
172173
// StartNode might need adjustment if it strictly requires coreda.Client methods.
173174
// For now, assume it can work with coreda.DA or will be adjusted later.
174175
// We also need to pass the namespace config for rollDA.
175-
return rollcmd.StartNode(logger, cmd, executor, sequencer, rollDA, p2pClient, datastore, nodeConfig, nil)
176+
return rollcmd.StartNode(logger, cmd, executor, sequencer, rollDA, p2pClient, datastore, nodeConfig, node.NodeOptions{})
176177
},
177178
}
178179

apps/evm/single/cmd/run.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"path/filepath"
77

88
"github.com/rollkit/rollkit/da/jsonrpc"
9+
"github.com/rollkit/rollkit/node"
910
"github.com/rollkit/rollkit/sequencers/single"
1011

1112
"github.com/ethereum/go-ethereum/common"
@@ -77,7 +78,7 @@ var RunCmd = &cobra.Command{
7778
return err
7879
}
7980

80-
return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, p2pClient, datastore, nodeConfig, nil)
81+
return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, p2pClient, datastore, nodeConfig, node.NodeOptions{})
8182
},
8283
}
8384

apps/testapp/cmd/run.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
kvexecutor "github.com/rollkit/rollkit/apps/testapp/kv"
1111
"github.com/rollkit/rollkit/da/jsonrpc"
12+
"github.com/rollkit/rollkit/node"
1213
rollcmd "github.com/rollkit/rollkit/pkg/cmd"
1314
"github.com/rollkit/rollkit/pkg/p2p"
1415
"github.com/rollkit/rollkit/pkg/p2p/key"
@@ -93,6 +94,6 @@ var RunCmd = &cobra.Command{
9394
return err
9495
}
9596

96-
return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, p2pClient, datastore, nodeConfig, nil)
97+
return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, p2pClient, datastore, nodeConfig, node.NodeOptions{})
9798
},
9899
}

block/manager.go

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,6 @@ type MetricsRecorder interface {
7070
RecordMetrics(gasPrice float64, blobSize uint64, statusCode coreda.StatusCode, numPendingBlocks uint64, includedBlockHeight uint64)
7171
}
7272

73-
func defaultSignaturePayloadProvider(header *types.Header) ([]byte, error) {
74-
return header.MarshalBinary()
75-
}
76-
7773
// NewHeaderEvent is used to pass header and DA height to headerInCh
7874
type NewHeaderEvent struct {
7975
Header *types.SignedHeader
@@ -168,14 +164,14 @@ type Manager struct {
168164
// signaturePayloadProvider is used to provide a signature payload for the header.
169165
// It is used to sign the header with the provided signer.
170166
signaturePayloadProvider types.SignaturePayloadProvider
167+
168+
// validatorHasherProvider is used to provide the validator hash for the header.
169+
// It is used to set the validator hash in the header.
170+
validatorHasherProvider types.ValidatorHasherProvider
171171
}
172172

173173
// getInitialState tries to load lastState from Store, and if it's not available it reads genesis.
174-
func getInitialState(ctx context.Context, genesis genesis.Genesis, signer signer.Signer, store storepkg.Store, exec coreexecutor.Executor, logger logging.EventLogger, signaturePayloadProvider types.SignaturePayloadProvider) (types.State, error) {
175-
if signaturePayloadProvider == nil {
176-
signaturePayloadProvider = defaultSignaturePayloadProvider
177-
}
178-
174+
func getInitialState(ctx context.Context, genesis genesis.Genesis, signer signer.Signer, store storepkg.Store, exec coreexecutor.Executor, logger logging.EventLogger, managerOpts ManagerOptions) (types.State, error) {
179175
// Load the state from store.
180176
s, err := store.GetState(ctx)
181177

@@ -213,7 +209,7 @@ func getInitialState(ctx context.Context, genesis genesis.Genesis, signer signer
213209
return types.State{}, fmt.Errorf("failed to get public key: %w", err)
214210
}
215211

216-
b, err := signaturePayloadProvider(&header)
212+
b, err := managerOpts.SignaturePayloadProvider(&header)
217213
if err != nil {
218214
return types.State{}, fmt.Errorf("failed to get signature payload: %w", err)
219215
}
@@ -234,7 +230,7 @@ func getInitialState(ctx context.Context, genesis genesis.Genesis, signer signer
234230

235231
// Set the same custom verifier used during normal block validation
236232
if err := genesisHeader.SetCustomVerifier(func(h *types.Header) ([]byte, error) {
237-
return signaturePayloadProvider(h)
233+
return managerOpts.SignaturePayloadProvider(h)
238234
}); err != nil {
239235
return types.State{}, fmt.Errorf("failed to set custom verifier for genesis header: %w", err)
240236
}
@@ -269,6 +265,31 @@ func getInitialState(ctx context.Context, genesis genesis.Genesis, signer signer
269265
return s, nil
270266
}
271267

268+
// ManagerOptions defines the options for creating a new block Manager.
269+
type ManagerOptions struct {
270+
SignaturePayloadProvider types.SignaturePayloadProvider
271+
ValidatorHasherProvider types.ValidatorHasherProvider
272+
}
273+
274+
func (opts *ManagerOptions) Validate() error {
275+
if opts.SignaturePayloadProvider == nil {
276+
return fmt.Errorf("signature payload provider cannot be nil")
277+
}
278+
if opts.ValidatorHasherProvider == nil {
279+
return fmt.Errorf("validator hasher provider cannot be nil")
280+
}
281+
282+
return nil
283+
}
284+
285+
// DefaultManagerOptions returns the default options for creating a new block Manager.
286+
func DefaultManagerOptions() ManagerOptions {
287+
return ManagerOptions{
288+
SignaturePayloadProvider: types.DefaultSignaturePayloadProvider,
289+
ValidatorHasherProvider: types.DefaultValidatorHasherProvider,
290+
}
291+
}
292+
272293
// NewManager creates new block Manager.
273294
func NewManager(
274295
ctx context.Context,
@@ -287,13 +308,9 @@ func NewManager(
287308
seqMetrics *Metrics,
288309
gasPrice float64,
289310
gasMultiplier float64,
290-
signaturePayloadProvider types.SignaturePayloadProvider,
311+
managerOpts ManagerOptions,
291312
) (*Manager, error) {
292-
if signaturePayloadProvider == nil {
293-
signaturePayloadProvider = defaultSignaturePayloadProvider
294-
}
295-
296-
s, err := getInitialState(ctx, genesis, signer, store, exec, logger, signaturePayloadProvider)
313+
s, err := getInitialState(ctx, genesis, signer, store, exec, logger, managerOpts)
297314
if err != nil {
298315
return nil, fmt.Errorf("failed to get initial state: %w", err)
299316
}
@@ -384,7 +401,8 @@ func NewManager(
384401
gasPrice: gasPrice,
385402
gasMultiplier: gasMultiplier,
386403
txNotifyCh: make(chan struct{}, 1), // Non-blocking channel
387-
signaturePayloadProvider: signaturePayloadProvider,
404+
signaturePayloadProvider: managerOpts.SignaturePayloadProvider,
405+
validatorHasherProvider: managerOpts.ValidatorHasherProvider,
388406
}
389407

390408
// initialize da included height
@@ -845,9 +863,15 @@ func (m *Manager) execCreateBlock(_ context.Context, height uint64, lastSignatur
845863
return nil, nil, fmt.Errorf("proposer address is not the same as the genesis proposer address %x != %x", address, m.genesis.ProposerAddress)
846864
}
847865

848-
// Determine if this is an empty block
866+
// determine if this is an empty block
849867
isEmpty := batchData.Batch == nil || len(batchData.Transactions) == 0
850868

869+
// build validator hash
870+
validatorHash, err := m.validatorHasherProvider(m.genesis.ProposerAddress, key)
871+
if err != nil {
872+
return nil, nil, fmt.Errorf("failed to get validator hash: %w", err)
873+
}
874+
851875
header := &types.SignedHeader{
852876
Header: types.Header{
853877
Version: types.Version{
@@ -857,13 +881,14 @@ func (m *Manager) execCreateBlock(_ context.Context, height uint64, lastSignatur
857881
BaseHeader: types.BaseHeader{
858882
ChainID: m.lastState.ChainID,
859883
Height: height,
860-
Time: uint64(batchData.UnixNano()), //nolint:gosec // why is time unix? (tac0turtle)
884+
Time: uint64(batchData.UnixNano()),
861885
},
862886
LastHeaderHash: lastHeaderHash,
863887
// DataHash is set at the end of the function
864888
ConsensusHash: make(types.Hash, 32),
865889
AppHash: m.lastState.AppHash,
866890
ProposerAddress: m.genesis.ProposerAddress,
891+
ValidatorHash: validatorHash,
867892
},
868893
Signature: *lastSignature,
869894
Signer: types.Signer{

block/manager_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func getManager(t *testing.T, da da.DA, gasPrice float64, gasMultiplier float64)
5353
metrics: NopMetrics(),
5454
store: mockStore,
5555
txNotifyCh: make(chan struct{}, 1),
56-
signaturePayloadProvider: defaultSignaturePayloadProvider,
56+
signaturePayloadProvider: types.DefaultSignaturePayloadProvider,
5757
}
5858

5959
m.publishBlock = m.publishBlockInternal
@@ -77,7 +77,7 @@ func TestInitialStateClean(t *testing.T) {
7777
mockExecutor.On("InitChain", ctx, genesisData.GenesisDAStartTime, genesisData.InitialHeight, genesisData.ChainID).
7878
Return([]byte("mockAppHash"), uint64(1000), nil).Once()
7979

80-
s, err := getInitialState(ctx, genesisData, nil, emptyStore, mockExecutor, logger, nil /* uses default signature verification */)
80+
s, err := getInitialState(ctx, genesisData, nil, emptyStore, mockExecutor, logger, DefaultManagerOptions())
8181
require.NoError(err)
8282
initialHeight := genesisData.InitialHeight
8383
require.Equal(initialHeight-1, s.LastBlockHeight)
@@ -108,7 +108,7 @@ func TestInitialStateStored(t *testing.T) {
108108
mockExecutor := mocks.NewMockExecutor(t)
109109

110110
// getInitialState should not call InitChain if state exists
111-
s, err := getInitialState(ctx, genesisData, nil, store, mockExecutor, logger, nil /* uses default signature verification */)
111+
s, err := getInitialState(ctx, genesisData, nil, store, mockExecutor, logger, DefaultManagerOptions())
112112
require.NoError(err)
113113
require.Equal(s.LastBlockHeight, uint64(100))
114114
require.Equal(s.InitialHeight, uint64(1))
@@ -143,7 +143,7 @@ func TestInitialStateUnexpectedHigherGenesis(t *testing.T) {
143143
require.NoError(err)
144144
mockExecutor := mocks.NewMockExecutor(t)
145145

146-
_, err = getInitialState(ctx, genesis, nil, store, mockExecutor, logger, nil /* uses default signature verification */)
146+
_, err = getInitialState(ctx, genesis, nil, store, mockExecutor, logger, DefaultManagerOptions())
147147
require.EqualError(err, "genesis.InitialHeight (2) is greater than last stored state's LastBlockHeight (0)")
148148

149149
// Assert mock expectations (InitChain should not have been called)

block/publish_block_p2p_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ func setupBlockManager(t *testing.T, ctx context.Context, workDir string, mainKV
217217
NopMetrics(),
218218
1.,
219219
1.,
220-
nil, // using default signature verification
220+
DefaultManagerOptions(),
221221
)
222222
require.NoError(t, err)
223223
return result, headerSyncService, dataSyncService

block/publish_block_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func setupManagerForPublishBlockTest(
9292
metrics: NopMetrics(),
9393
pendingHeaders: nil,
9494
pendingData: nil,
95-
signaturePayloadProvider: defaultSignaturePayloadProvider,
95+
signaturePayloadProvider: types.DefaultSignaturePayloadProvider,
9696
}
9797
manager.publishBlock = manager.publishBlockInternal
9898

@@ -184,7 +184,7 @@ func Test_publishBlock_NoBatch(t *testing.T) {
184184
},
185185
lastStateMtx: &sync.RWMutex{},
186186
metrics: NopMetrics(),
187-
signaturePayloadProvider: defaultSignaturePayloadProvider,
187+
signaturePayloadProvider: types.DefaultSignaturePayloadProvider,
188188
}
189189

190190
m.publishBlock = m.publishBlockInternal
@@ -274,7 +274,7 @@ func Test_publishBlock_EmptyBatch(t *testing.T) {
274274
return nil
275275
}),
276276
daHeight: &daH,
277-
signaturePayloadProvider: defaultSignaturePayloadProvider,
277+
signaturePayloadProvider: types.DefaultSignaturePayloadProvider,
278278
}
279279

280280
m.publishBlock = m.publishBlockInternal

node/full.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"github.com/rollkit/rollkit/pkg/signer"
3030
"github.com/rollkit/rollkit/pkg/store"
3131
rollkitsync "github.com/rollkit/rollkit/pkg/sync"
32-
"github.com/rollkit/rollkit/types"
3332
)
3433

3534
// prefixes used in KV store to separate rollkit data from execution environment data (if the same data base is reused)
@@ -81,7 +80,7 @@ func newFullNode(
8180
da coreda.DA,
8281
metricsProvider MetricsProvider,
8382
logger logging.EventLogger,
84-
signaturePayloadProvider types.SignaturePayloadProvider,
83+
nodeOpts NodeOptions,
8584
) (fn *FullNode, err error) {
8685
seqMetrics, _ := metricsProvider(genesis.ChainID)
8786

@@ -113,7 +112,7 @@ func newFullNode(
113112
seqMetrics,
114113
nodeConfig.DA.GasPrice,
115114
nodeConfig.DA.GasMultiplier,
116-
signaturePayloadProvider,
115+
nodeOpts.ManagerOptions,
117116
)
118117
if err != nil {
119118
return nil, err
@@ -200,7 +199,7 @@ func initBlockManager(
200199
seqMetrics *block.Metrics,
201200
gasPrice float64,
202201
gasMultiplier float64,
203-
signaturePayloadProvider types.SignaturePayloadProvider,
202+
managerOpts block.ManagerOptions,
204203
) (*block.Manager, error) {
205204
logger.Debug("Proposer address", "address", genesis.ProposerAddress)
206205

@@ -221,7 +220,7 @@ func initBlockManager(
221220
seqMetrics,
222221
gasPrice,
223222
gasMultiplier,
224-
signaturePayloadProvider,
223+
managerOpts,
225224
)
226225
if err != nil {
227226
return nil, fmt.Errorf("error while initializing BlockManager: %w", err)

node/helpers_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func newTestNode(
126126
ds,
127127
DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()),
128128
logging.Logger("test"),
129-
nil,
129+
NodeOptions{},
130130
)
131131
require.NoError(t, err)
132132

@@ -191,7 +191,7 @@ func createNodesWithCleanup(t *testing.T, num int, config rollkitconfig.Config)
191191
ds,
192192
DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()),
193193
logging.Logger("test"),
194-
nil,
194+
NodeOptions{},
195195
)
196196
require.NoError(err)
197197

@@ -229,7 +229,7 @@ func createNodesWithCleanup(t *testing.T, num int, config rollkitconfig.Config)
229229
dssync.MutexWrap(datastore.NewMapDatastore()),
230230
DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()),
231231
logging.Logger("test"),
232-
nil,
232+
NodeOptions{},
233233
)
234234
require.NoError(err)
235235
// Update cleanup to cancel the context instead of calling Stop

node/node.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
ds "github.com/ipfs/go-datastore"
77
logging "github.com/ipfs/go-log/v2"
88

9+
"github.com/rollkit/rollkit/block"
910
coreda "github.com/rollkit/rollkit/core/da"
1011
coreexecutor "github.com/rollkit/rollkit/core/execution"
1112
coresequencer "github.com/rollkit/rollkit/core/sequencer"
@@ -14,7 +15,6 @@ import (
1415
"github.com/rollkit/rollkit/pkg/p2p"
1516
"github.com/rollkit/rollkit/pkg/service"
1617
"github.com/rollkit/rollkit/pkg/signer"
17-
"github.com/rollkit/rollkit/types"
1818
)
1919

2020
// Node is the interface for an application node
@@ -24,6 +24,10 @@ type Node interface {
2424
IsRunning() bool
2525
}
2626

27+
type NodeOptions struct {
28+
ManagerOptions block.ManagerOptions
29+
}
30+
2731
// NewNode returns a new Full or Light Node based on the config
2832
// This is the entry point for composing a node, when compiling a node, you need to provide an executor
2933
// Example executors can be found in apps/
@@ -39,12 +43,16 @@ func NewNode(
3943
database ds.Batching,
4044
metricsProvider MetricsProvider,
4145
logger logging.EventLogger,
42-
signaturePayloadProvider types.SignaturePayloadProvider,
46+
nodeOptions NodeOptions,
4347
) (Node, error) {
4448
if conf.Node.Light {
4549
return newLightNode(conf, genesis, p2pClient, database, logger)
4650
}
4751

52+
if err := nodeOptions.ManagerOptions.Validate(); err != nil {
53+
nodeOptions.ManagerOptions = block.DefaultManagerOptions()
54+
}
55+
4856
return newFullNode(
4957
ctx,
5058
conf,
@@ -57,6 +65,6 @@ func NewNode(
5765
da,
5866
metricsProvider,
5967
logger,
60-
signaturePayloadProvider,
68+
nodeOptions,
6169
)
6270
}

0 commit comments

Comments
 (0)