@@ -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
7874type 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
@@ -201,9 +197,12 @@ func getInitialState(ctx context.Context, genesis genesis.Genesis, signer signer
201197 },
202198 }
203199
204- var signature types.Signature
200+ var (
201+ data = & types.Data {}
202+ signature types.Signature
203+ pubKey crypto.PubKey
204+ )
205205
206- var pubKey crypto.PubKey
207206 // The signer is only provided in aggregator nodes. This enables the creation of a signed genesis header,
208207 // which includes a public key and a cryptographic signature for the header.
209208 // In a full node (non-aggregator), the signer will be nil, and only an unsigned genesis header will be initialized locally.
@@ -213,11 +212,12 @@ func getInitialState(ctx context.Context, genesis genesis.Genesis, signer signer
213212 return types.State {}, fmt .Errorf ("failed to get public key: %w" , err )
214213 }
215214
216- b , err := signaturePayloadProvider (& header )
215+ bz , err := managerOpts . SignaturePayloadProvider (& header )
217216 if err != nil {
218217 return types.State {}, fmt .Errorf ("failed to get signature payload: %w" , err )
219218 }
220- signature , err = signer .Sign (b )
219+
220+ signature , err = signer .Sign (bz )
221221 if err != nil {
222222 return types.State {}, fmt .Errorf ("failed to get header signature: %w" , err )
223223 }
@@ -232,14 +232,7 @@ func getInitialState(ctx context.Context, genesis genesis.Genesis, signer signer
232232 Signature : signature ,
233233 }
234234
235- // Set the same custom verifier used during normal block validation
236- if err := genesisHeader .SetCustomVerifier (func (h * types.Header ) ([]byte , error ) {
237- return signaturePayloadProvider (h )
238- }); err != nil {
239- return types.State {}, fmt .Errorf ("failed to set custom verifier for genesis header: %w" , err )
240- }
241-
242- err = store .SaveBlockData (ctx , genesisHeader , & types.Data {}, & signature )
235+ err = store .SaveBlockData (ctx , genesisHeader , data , & signature )
243236 if err != nil {
244237 return types.State {}, fmt .Errorf ("failed to save genesis block: %w" , err )
245238 }
@@ -269,6 +262,31 @@ func getInitialState(ctx context.Context, genesis genesis.Genesis, signer signer
269262 return s , nil
270263}
271264
265+ // ManagerOptions defines the options for creating a new block Manager.
266+ type ManagerOptions struct {
267+ SignaturePayloadProvider types.SignaturePayloadProvider
268+ ValidatorHasherProvider types.ValidatorHasherProvider
269+ }
270+
271+ func (opts * ManagerOptions ) Validate () error {
272+ if opts .SignaturePayloadProvider == nil {
273+ return fmt .Errorf ("signature payload provider cannot be nil" )
274+ }
275+ if opts .ValidatorHasherProvider == nil {
276+ return fmt .Errorf ("validator hasher provider cannot be nil" )
277+ }
278+
279+ return nil
280+ }
281+
282+ // DefaultManagerOptions returns the default options for creating a new block Manager.
283+ func DefaultManagerOptions () ManagerOptions {
284+ return ManagerOptions {
285+ SignaturePayloadProvider : types .DefaultSignaturePayloadProvider ,
286+ ValidatorHasherProvider : types .DefaultValidatorHasherProvider ,
287+ }
288+ }
289+
272290// NewManager creates new block Manager.
273291func NewManager (
274292 ctx context.Context ,
@@ -287,13 +305,9 @@ func NewManager(
287305 seqMetrics * Metrics ,
288306 gasPrice float64 ,
289307 gasMultiplier float64 ,
290- signaturePayloadProvider types. SignaturePayloadProvider ,
308+ managerOpts ManagerOptions ,
291309) (* Manager , error ) {
292- if signaturePayloadProvider == nil {
293- signaturePayloadProvider = defaultSignaturePayloadProvider
294- }
295-
296- s , err := getInitialState (ctx , genesis , signer , store , exec , logger , signaturePayloadProvider )
310+ s , err := getInitialState (ctx , genesis , signer , store , exec , logger , managerOpts )
297311 if err != nil {
298312 return nil , fmt .Errorf ("failed to get initial state: %w" , err )
299313 }
@@ -384,7 +398,8 @@ func NewManager(
384398 gasPrice : gasPrice ,
385399 gasMultiplier : gasMultiplier ,
386400 txNotifyCh : make (chan struct {}, 1 ), // Non-blocking channel
387- signaturePayloadProvider : signaturePayloadProvider ,
401+ signaturePayloadProvider : managerOpts .SignaturePayloadProvider ,
402+ validatorHasherProvider : managerOpts .ValidatorHasherProvider ,
388403 }
389404
390405 // initialize da included height
@@ -659,33 +674,12 @@ func (m *Manager) publishBlockInternal(ctx context.Context) error {
659674 return err
660675 }
661676
662- if err = m .store .SaveBlockData (ctx , header , data , & signature ); err != nil {
677+ if err = m .store .SaveBlockData (ctx , header , data , & signature ); err != nil { // saved early for crash recovery, will be overwritten later with the final signature
663678 return fmt .Errorf ("failed to save block: %w" , err )
664679 }
665680 }
666681
667- signature , err = m .getHeaderSignature (header .Header )
668- if err != nil {
669- return err
670- }
671-
672- // set the signature to current block's signed header
673- header .Signature = signature
674-
675- // Set the custom verifier to ensure proper signature validation (if not already set by executor)
676- // Note: The executor may have already set a custom verifier during transaction execution
677- if err := header .SetCustomVerifier (func (h * types.Header ) ([]byte , error ) {
678- return m .signaturePayloadProvider (h )
679- }); err != nil {
680- return fmt .Errorf ("failed to set custom verifier: %w" , err )
681- }
682-
683- if err := header .ValidateBasic (); err != nil {
684- // If this ever happens, for recovery, check for a mismatch between the configured signing key and the proposer address in the genesis file
685- return fmt .Errorf ("header validation error: %w" , err )
686- }
687-
688- newState , err := m .applyBlock (ctx , header , data )
682+ newState , err := m .applyBlock (ctx , header .Header , data )
689683 if err != nil {
690684 return fmt .Errorf ("error applying block: %w" , err )
691685 }
@@ -697,13 +691,24 @@ func (m *Manager) publishBlockInternal(ctx context.Context) error {
697691 Time : header .BaseHeader .Time ,
698692 LastDataHash : lastDataHash ,
699693 }
694+
695+ // we sign the header after executing the block, as a signature payload provider could depend on the block's data
696+ signature , err = m .getHeaderSignature (header .Header )
697+ if err != nil {
698+ return err
699+ }
700+
701+ // set the signature to current block's signed header
702+ header .Signature = signature
703+
704+ // set the custom verifier to ensure proper signature validation
705+ header .SetCustomVerifier (m .signaturePayloadProvider )
706+
700707 // Validate the created block before storing
701708 if err := m .Validate (ctx , header , data ); err != nil {
702709 return fmt .Errorf ("failed to validate block: %w" , err )
703710 }
704711
705- headerHeight := header .Height ()
706-
707712 headerHash := header .Hash ().String ()
708713 m .headerCache .SetSeen (headerHash )
709714
@@ -714,6 +719,7 @@ func (m *Manager) publishBlockInternal(ctx context.Context) error {
714719 }
715720
716721 // Update the store height before submitting to the DA layer but after committing to the DB
722+ headerHeight := header .Height ()
717723 if err = m .store .SetHeight (ctx , headerHeight ); err != nil {
718724 return err
719725 }
@@ -773,7 +779,7 @@ func (m *Manager) createBlock(ctx context.Context, height uint64, lastSignature
773779 return m .execCreateBlock (ctx , height , lastSignature , lastHeaderHash , m .lastState , batchData )
774780}
775781
776- func (m * Manager ) applyBlock (ctx context.Context , header * types.SignedHeader , data * types.Data ) (types.State , error ) {
782+ func (m * Manager ) applyBlock (ctx context.Context , header types.Header , data * types.Data ) (types.State , error ) {
777783 m .lastStateMtx .RLock ()
778784 defer m .lastStateMtx .RUnlock ()
779785 return m .execApplyBlock (ctx , m .lastState , header , data )
@@ -845,9 +851,15 @@ func (m *Manager) execCreateBlock(_ context.Context, height uint64, lastSignatur
845851 return nil , nil , fmt .Errorf ("proposer address is not the same as the genesis proposer address %x != %x" , address , m .genesis .ProposerAddress )
846852 }
847853
848- // Determine if this is an empty block
854+ // determine if this is an empty block
849855 isEmpty := batchData .Batch == nil || len (batchData .Transactions ) == 0
850856
857+ // build validator hash
858+ validatorHash , err := m .validatorHasherProvider (m .genesis .ProposerAddress , key )
859+ if err != nil {
860+ return nil , nil , fmt .Errorf ("failed to get validator hash: %w" , err )
861+ }
862+
851863 header := & types.SignedHeader {
852864 Header : types.Header {
853865 Version : types.Version {
@@ -857,13 +869,14 @@ func (m *Manager) execCreateBlock(_ context.Context, height uint64, lastSignatur
857869 BaseHeader : types.BaseHeader {
858870 ChainID : m .lastState .ChainID ,
859871 Height : height ,
860- Time : uint64 (batchData .UnixNano ()), //nolint:gosec // why is time unix? (tac0turtle)
872+ Time : uint64 (batchData .UnixNano ()),
861873 },
862874 LastHeaderHash : lastHeaderHash ,
863875 // DataHash is set at the end of the function
864876 ConsensusHash : make (types.Hash , 32 ),
865877 AppHash : m .lastState .AppHash ,
866878 ProposerAddress : m .genesis .ProposerAddress ,
879+ ValidatorHash : validatorHash ,
867880 },
868881 Signature : * lastSignature ,
869882 Signer : types.Signer {
@@ -891,13 +904,13 @@ func (m *Manager) execCreateBlock(_ context.Context, height uint64, lastSignatur
891904 return header , blockData , nil
892905}
893906
894- func (m * Manager ) execApplyBlock (ctx context.Context , lastState types.State , header * types.SignedHeader , data * types.Data ) (types.State , error ) {
907+ func (m * Manager ) execApplyBlock (ctx context.Context , lastState types.State , header types.Header , data * types.Data ) (types.State , error ) {
895908 rawTxs := make ([][]byte , len (data .Txs ))
896909 for i := range data .Txs {
897910 rawTxs [i ] = data .Txs [i ]
898911 }
899912
900- ctx = context .WithValue (ctx , types .SignedHeaderContextKey , header )
913+ ctx = context .WithValue (ctx , types .HeaderContextKey , header )
901914 newStateRoot , _ , err := m .exec .ExecuteTxs (ctx , rawTxs , header .Height (), header .Time (), lastState .AppHash )
902915 if err != nil {
903916 return types.State {}, fmt .Errorf ("failed to execute transactions: %w" , err )
@@ -985,9 +998,11 @@ func (m *Manager) getHeaderSignature(header types.Header) (types.Signature, erro
985998 if err != nil {
986999 return nil , err
9871000 }
1001+
9881002 if m .signer == nil {
9891003 return nil , fmt .Errorf ("signer is nil; cannot sign header" )
9901004 }
1005+
9911006 return m .signer .Sign (b )
9921007}
9931008
0 commit comments