diff --git a/ethdb/privateapi/ethbackend.go b/ethdb/privateapi/ethbackend.go
index f497c0372848ba2c48bf6e2fb117b842d6d65a00..08bf39fa386976b396950455b60dbf27b9057c88 100644
--- a/ethdb/privateapi/ethbackend.go
+++ b/ethdb/privateapi/ethbackend.go
@@ -317,6 +317,20 @@ func (s *EthBackendServer) EngineNewPayloadV1(ctx context.Context, req *types2.E
 		return &remote.EnginePayloadStatus{Status: remote.EngineStatus_INVALID_BLOCK_HASH}, nil
 	}
 
+	tx, err := s.db.BeginRo(ctx)
+	if err != nil {
+		return nil, err
+	}
+	parentTd, err := rawdb.ReadTd(tx, header.ParentHash, req.BlockNumber-1)
+	if err != nil {
+		return nil, err
+	}
+	if parentTd != nil && parentTd.Cmp(s.config.TerminalTotalDifficulty) < 0 {
+		log.Warn("[NewPayload] TTD not reached yet", "height", header.Number, "hash", common.Hash(blockHash))
+		return &remote.EnginePayloadStatus{Status: remote.EngineStatus_INVALID_TERMINAL_BLOCK}, nil
+	}
+	tx.Rollback()
+
 	// If another payload is already commissioned then we just reply with syncing
 	if s.stageLoopIsBusy() {
 		// We are still syncing a commissioned payload
@@ -416,6 +430,28 @@ func (s *EthBackendServer) EngineForkChoiceUpdatedV1(ctx context.Context, req *r
 		return nil, fmt.Errorf("not a proof-of-stake chain")
 	}
 
+	forkChoice := engineapi.ForkChoiceMessage{
+		HeadBlockHash:      gointerfaces.ConvertH256ToHash(req.ForkchoiceState.HeadBlockHash),
+		SafeBlockHash:      gointerfaces.ConvertH256ToHash(req.ForkchoiceState.SafeBlockHash),
+		FinalizedBlockHash: gointerfaces.ConvertH256ToHash(req.ForkchoiceState.FinalizedBlockHash),
+	}
+
+	tx1, err := s.db.BeginRo(ctx)
+	if err != nil {
+		return nil, err
+	}
+	td, err := rawdb.ReadTdByHash(tx1, forkChoice.HeadBlockHash)
+	if err != nil {
+		return nil, err
+	}
+	if td != nil && td.Cmp(s.config.TerminalTotalDifficulty) < 0 {
+		log.Warn("[ForkChoiceUpdated] TTD not reached yet", "forkChoice", forkChoice)
+		return &remote.EngineForkChoiceUpdatedReply{
+			PayloadStatus: &remote.EnginePayloadStatus{Status: remote.EngineStatus_INVALID_TERMINAL_BLOCK},
+		}, nil
+	}
+	tx1.Rollback()
+
 	// TODO(yperbasis): Client software MAY skip an update of the forkchoice state and
 	// MUST NOT begin a payload build process if forkchoiceState.headBlockHash doesn't reference a leaf of the block tree
 	// (i.e. it references an old block).
@@ -428,14 +464,8 @@ func (s *EthBackendServer) EngineForkChoiceUpdatedV1(ctx context.Context, req *r
 		}, nil
 	}
 
-	forkChoiceMessage := engineapi.ForkChoiceMessage{
-		HeadBlockHash:      gointerfaces.ConvertH256ToHash(req.ForkchoiceState.HeadBlockHash),
-		SafeBlockHash:      gointerfaces.ConvertH256ToHash(req.ForkchoiceState.SafeBlockHash),
-		FinalizedBlockHash: gointerfaces.ConvertH256ToHash(req.ForkchoiceState.FinalizedBlockHash),
-	}
-
-	log.Trace("[ForkChoiceUpdated] sending forkChoiceMessage", "head", forkChoiceMessage.HeadBlockHash)
-	s.requestList.AddForkChoiceRequest(&forkChoiceMessage)
+	log.Trace("[ForkChoiceUpdated] sending forkChoiceMessage", "head", forkChoice.HeadBlockHash)
+	s.requestList.AddForkChoiceRequest(&forkChoice)
 
 	payloadStatus := <-s.statusCh
 	log.Trace("[ForkChoiceUpdated] got reply", "payloadStatus", payloadStatus)
@@ -458,17 +488,17 @@ func (s *EthBackendServer) EngineForkChoiceUpdatedV1(ctx context.Context, req *r
 	// payload IDs start from 1 (0 signifies null)
 	s.payloadId++
 
-	tx, err := s.db.BeginRo(ctx)
+	tx2, err := s.db.BeginRo(ctx)
 	if err != nil {
 		return nil, err
 	}
-	headHash := rawdb.ReadHeadBlockHash(tx)
-	headNumber := rawdb.ReadHeaderNumber(tx, headHash)
-	headHeader := rawdb.ReadHeader(tx, headHash, *headNumber)
-	tx.Rollback()
+	headHash := rawdb.ReadHeadBlockHash(tx2)
+	headNumber := rawdb.ReadHeaderNumber(tx2, headHash)
+	headHeader := rawdb.ReadHeader(tx2, headHash, *headNumber)
+	tx2.Rollback()
 
-	if headHeader.Hash() != forkChoiceMessage.HeadBlockHash {
-		return nil, fmt.Errorf("unexpected head hash: %x vs %x", headHeader.Hash(), forkChoiceMessage.HeadBlockHash)
+	if headHeader.Hash() != forkChoice.HeadBlockHash {
+		return nil, fmt.Errorf("unexpected head hash: %x vs %x", headHeader.Hash(), forkChoice.HeadBlockHash)
 	}
 
 	emptyHeader := core.MakeEmptyHeader(headHeader, s.config, req.PayloadAttributes.Timestamp, nil)