@@ -3,6 +3,7 @@ package backend
33import (
44 "bytes"
55 "context"
6+ "encoding/binary"
67 "encoding/hex"
78 "encoding/json"
89 "errors"
@@ -426,11 +427,17 @@ func (s *SyncTester) forkchoiceUpdated(ctx context.Context, session *eth.SyncTes
426427 // Consider as sync error if read only EL interaction fails because we cannot validate
427428 return & eth.ForkchoiceUpdatedResult {PayloadStatus : eth.PayloadStatusV1 {Status : eth .ExecutionSyncing }, PayloadID : nil }, nil
428429 }
430+ // https://github.com/ethereum-optimism/specs/blob/510377c586d0cbede2d40402d2371fcadd5656a0/specs/protocol/jovian/exec-engine.md#minimum-base-fee-in-block-header
431+ // Implicitly determine whether jovian is enabled by inspecting extraData from read only EL data
432+ isJovian := eip1559 .ValidateMinBaseFeeExtraData (newBlock .Header ().Extra ) == nil
429433 // https://github.com/ethereum-optimism/specs/blob/972dec7c7c967800513c354b2f8e5b79340de1c3/specs/protocol/holocene/exec-engine.md#eip-1559-parameters-in-block-header
430434 // Implicitly determine whether holocene is enabled by inspecting extraData from read only EL data
431- isHolocene := eip1559 .ValidateHoloceneExtraData (newBlock .Header ().Extra ) == nil
435+ isHolocene := true // holocene is always activated when jovian is activated
436+ if ! isJovian {
437+ isHolocene = eip1559 .ValidateHoloceneExtraData (newBlock .Header ().Extra ) == nil
438+ }
432439 // Sanity check attr comparing with newBlock
433- if err := s .validateAttributesForBlock (attr , newBlock , isHolocene ); err != nil {
440+ if err := s .validateAttributesForBlock (attr , newBlock , isHolocene , isJovian ); err != nil {
434441 // https://github.com/ethereum/execution-apis/blob/584905270d8ad665718058060267061ecfd79ca5/src/engine/paris.md#specification-1
435442 // Client software MUST respond to this method call in the following way: {error: {code: -38003, message: "Invalid payload attributes"}} if the payload is deemed VALID and forkchoiceState has been applied successfully, but no build process has been started due to invalid payloadAttributes.
436443 return & eth.ForkchoiceUpdatedResult {PayloadStatus : eth.PayloadStatusV1 {Status : eth .ExecutionInvalid }, PayloadID : nil }, engine .InvalidPayloadAttributes .With (err )
@@ -488,9 +495,12 @@ func (s *SyncTester) forkchoiceUpdated(ctx context.Context, session *eth.SyncTes
488495// - Gas limit must match.
489496// - If Holocene is active: Extra data must be exactly 9 bytes, the version byte must equal to 0,
490497// the remaining 8 bytes must match the EIP-1559 parameters.
498+ // - If Jovian is active: Extra data must be exactly 17 bytes, the version byte must equal to 1,
499+ // the first 8 bytes must match the EIP-1559 parameters,
500+ // the remaining 8 bytes must match the MinBaseFee parameter.
491501//
492502// Returns an error if any mismatch or invalid condition is found, otherwise nil.
493- func (s * SyncTester ) validateAttributesForBlock (attr * eth.PayloadAttributes , block * types.Block , isHolocene bool ) error {
503+ func (s * SyncTester ) validateAttributesForBlock (attr * eth.PayloadAttributes , block * types.Block , isHolocene , isJovian bool ) error {
494504 h := block .Header ()
495505 if h .Time != uint64 (attr .Timestamp ) {
496506 return fmt .Errorf ("timestamp mismatch: header=%d, attr=%d" , h .Time , attr .Timestamp )
@@ -547,7 +557,7 @@ func (s *SyncTester) validateAttributesForBlock(attr *eth.PayloadAttributes, blo
547557 // Cannot validate since EL will fall back to prior eip1559 constants
548558 return nil
549559 }
550- if ! bytes .Equal (block .Extra ()[1 :], (* attr .EIP1559Params )[:]) {
560+ if ! bytes .Equal (block .Extra ()[1 :1 + 8 ], (* attr .EIP1559Params )[:]) {
551561 return fmt .Errorf ("eip1559Params mismatch: %s != 0x%s" , * attr .EIP1559Params , hex .EncodeToString (block .Extra ()[1 :]))
552562 }
553563 } else {
@@ -557,6 +567,23 @@ func (s *SyncTester) validateAttributesForBlock(attr *eth.PayloadAttributes, blo
557567 return fmt .Errorf ("holocene disabled but EIP1559Params not nil. eip1559Params: %s" , attr .EIP1559Params )
558568 }
559569 }
570+ if isJovian {
571+ // https://github.com/ethereum-optimism/specs/blob/510377c586d0cbede2d40402d2371fcadd5656a0/specs/protocol/jovian/exec-engine.md#minimum-base-fee-in-payloadattributesv3
572+ // Spec: The Engine API PayloadAttributesV3 is extended with a new field minBaseFee
573+ if attr .MinBaseFee == nil {
574+ return errors .New ("jovian enabled but MinBaseFee nil" )
575+ }
576+ minBaseFee := binary .BigEndian .Uint64 (block .Extra ()[1 + 8 : 1 + 8 + 8 ])
577+ if minBaseFee != * attr .MinBaseFee {
578+ return fmt .Errorf ("MinBaseFee mismatch: %d != %d" , * attr .MinBaseFee , minBaseFee )
579+ }
580+ } else {
581+ // https://github.com/ethereum-optimism/specs/blob/510377c586d0cbede2d40402d2371fcadd5656a0/specs/protocol/jovian/exec-engine.md#minimum-base-fee-in-payloadattributesv3
582+ // Spec: The minBaseFee MUST be null prior to the Jovian fork, and MUST be non-null after the Jovian fork.
583+ if attr .MinBaseFee != nil {
584+ return fmt .Errorf ("jovian disabled but MinBaseFee not nil. MinBaseFee: %d" , attr .MinBaseFee )
585+ }
586+ }
560587 return nil
561588}
562589
0 commit comments