diff --git a/go/common/host/identity.go b/go/common/host/identity.go index 64d9ec10eb..1bee00872f 100644 --- a/go/common/host/identity.go +++ b/go/common/host/identity.go @@ -17,6 +17,6 @@ func NewIdentity(cfg *hostconfig.HostConfig) Identity { ID: cfg.ID, P2PPublicAddress: cfg.P2PPublicAddress, IsGenesis: cfg.IsGenesis, - IsSequencer: cfg.NodeType == common.ActiveSequencer, + IsSequencer: cfg.NodeType == common.Sequencer, } } diff --git a/go/common/node_type.go b/go/common/node_type.go index 5d1d516f75..db2b108041 100644 --- a/go/common/node_type.go +++ b/go/common/node_type.go @@ -3,30 +3,26 @@ package common import "fmt" const ( - activeSequencer = "sequencer" - validator = "validator" - backupSequencer = "backup_sequencer" - unknown = "unknown" + sequencer = "sequencer" + validator = "validator" + unknown = "unknown" ) // NodeType represents the type of the node. type NodeType int const ( - ActiveSequencer NodeType = iota + Sequencer NodeType = iota Validator - BackupSequencer Unknown ) func (n NodeType) String() string { switch n { - case ActiveSequencer: - return activeSequencer + case Sequencer: + return sequencer case Validator: return validator - case BackupSequencer: - return backupSequencer case Unknown: return unknown default: @@ -45,12 +41,10 @@ func (n *NodeType) UnmarshalText(text []byte) error { func ToNodeType(s string) (NodeType, error) { switch s { - case activeSequencer: - return ActiveSequencer, nil + case sequencer: + return Sequencer, nil case validator: return Validator, nil - case backupSequencer: - return BackupSequencer, nil default: return Unknown, fmt.Errorf("string '%s' cannot be converted to a node type", s) } diff --git a/go/enclave/enclave_admin_service.go b/go/enclave/enclave_admin_service.go index ba9c8cd4eb..843e162b21 100644 --- a/go/enclave/enclave_admin_service.go +++ b/go/enclave/enclave_admin_service.go @@ -57,6 +57,7 @@ type enclaveAdminService struct { enclaveKeyService *crypto.EnclaveAttestedKeyService mempool *components.TxPool sharedSecretService *crypto.SharedSecretService + activeSequencer bool } func NewEnclaveAdminAPI(config *enclaveconfig.EnclaveConfig, storage storage.Storage, logger gethlog.Logger, blockProcessor components.L1BlockProcessor, registry components.BatchRegistry, batchExecutor components.BatchExecutor, gethEncodingService gethencoding.EncodingService, stopControl *stopcontrol.StopControl, subscriptionManager *events.SubscriptionManager, enclaveKeyService *crypto.EnclaveAttestedKeyService, mempool *components.TxPool, chainConfig *params.ChainConfig, mgmtContractLib mgmtcontractlib.MgmtContractLib, attestationProvider components.AttestationProvider, sharedSecretService *crypto.SharedSecretService, daEncryptionService *crypto.DAEncryptionService) common.EnclaveAdmin { @@ -119,9 +120,6 @@ func NewEnclaveAdminAPI(config *enclaveconfig.EnclaveConfig, storage storage.Sto if eas.isBackupSequencer(context.Background()) || eas.isActiveSequencer(context.Background()) { mempool.SetValidateMode(false) } - if eas.isActiveSequencer(context.Background()) { - eas.service = sequencerService - } return eas } @@ -129,7 +127,8 @@ func NewEnclaveAdminAPI(config *enclaveconfig.EnclaveConfig, storage storage.Sto // addSequencer is used internally to add a sequencer enclaveID to the pool of attested enclaves. // If it is the current enclave it will change the behaviour of this enclave to be a backup sequencer (ready to become active). func (e *enclaveAdminService) addSequencer(id common.EnclaveID, _ types.Receipt) common.SystemError { - err := e.storage.StoreNodeType(context.Background(), id, common.BackupSequencer) + e.logger.Info("Storing new sequencer enclaveID", log.EnclaveIDKey, id) + err := e.storage.StoreNodeType(context.Background(), id, common.Sequencer) if err != nil { return responses.ToInternalError(err) } @@ -150,12 +149,10 @@ func (e *enclaveAdminService) MakeActive() common.SystemError { return fmt.Errorf("only backup sequencer can become active") } - err := e.storage.StoreNodeType(context.Background(), e.enclaveKeyService.EnclaveID(), common.ActiveSequencer) - if err != nil { - return err - } - + e.activeSequencer = true e.service = e.sequencerService + e.logger.Info("Enclave is now active sequencer.") + return nil } @@ -195,9 +192,25 @@ func (e *enclaveAdminService) SubmitL1Block(ctx context.Context, blockData *comm ProducedSecretResponses: e.sharedSecretProcessor.ProcessNetworkSecretMsgs(ctx, blockData, canShareSecret), } + // doing this after the network secret msgs to make sure we have stored the attestation before promotion. + e.processSequencerPromotions(blockData) + return bsr, nil } +func (e *enclaveAdminService) processSequencerPromotions(blockData *common.ProcessedL1Data) { + // todo handle sequencer revoked - could move all of this into a separate processor + sequencerAddedTxs := blockData.GetEvents(common.SequencerAddedTx) + for _, tx := range sequencerAddedTxs { + if tx.HasSequencerEnclaveID() { + err := e.addSequencer(tx.SequencerEnclaveID, *tx.Receipt) + if err != nil { + e.logger.Crit("Encountered error while adding sequencer enclaveID", log.ErrKey, err) + } + } + } +} + func (e *enclaveAdminService) SubmitBatch(ctx context.Context, extBatch *common.ExtBatch) common.SystemError { if e.isActiveSequencer(ctx) { e.logger.Crit("Can't submit a batch to the active sequencer") @@ -497,17 +510,6 @@ func (e *enclaveAdminService) ingestL1Block(ctx context.Context, processed *comm // Unsure what to do here; block has been stored } - // todo handle sequencer revoked - could move all of this into a separate processor - sequencerAddedTxs := processed.GetEvents(common.SequencerAddedTx) - for _, tx := range sequencerAddedTxs { - if tx.HasSequencerEnclaveID() { - err = e.addSequencer(tx.SequencerEnclaveID, *tx.Receipt) - if err != nil { - e.logger.Crit("Encountered error while adding sequencer enclaveID", log.ErrKey, err) - } - } - } - if ingestion.IsFork() { e.registry.OnL1Reorg(ingestion) err := e.service.OnL1Fork(ctx, ingestion.ChainFork) @@ -548,11 +550,11 @@ func (e *enclaveAdminService) sequencer() nodetype.ActiveSequencer { } func (e *enclaveAdminService) isActiveSequencer(ctx context.Context) bool { - return e.getNodeType(ctx) == common.ActiveSequencer + return e.activeSequencer && e.getNodeType(ctx) == common.Sequencer } func (e *enclaveAdminService) isBackupSequencer(ctx context.Context) bool { - return e.getNodeType(ctx) == common.BackupSequencer + return e.getNodeType(ctx) == common.Sequencer && !e.activeSequencer } func (e *enclaveAdminService) isValidator(ctx context.Context) bool { //nolint:unused diff --git a/go/enclave/storage/enclavedb/config.go b/go/enclave/storage/enclavedb/config.go index 3ab018dd88..e733e43bb7 100644 --- a/go/enclave/storage/enclavedb/config.go +++ b/go/enclave/storage/enclavedb/config.go @@ -19,7 +19,7 @@ const ( attInsert = "insert into attestation (enclave_id, pub_key, node_type) values (?,?,?)" attSelect = "select pub_key, node_type from attestation where enclave_id=?" attUpdate = "update attestation set node_type=? where enclave_id=?" - attSelectSequencers = "select enclave_id from attestation where node_type = ? or node_type = ?" + attSelectSequencers = "select enclave_id from attestation where node_type = ?" ) func WriteConfigToTx(ctx context.Context, dbtx *sql.Tx, key string, value any) (sql.Result, error) { @@ -73,7 +73,7 @@ func readSingleRow(ctx context.Context, db *sql.DB, query string, v any) ([]byte // FetchSequencerEnclaveIDs returns all enclave IDs that are registered as sequencers func FetchSequencerEnclaveIDs(ctx context.Context, db *sql.DB) ([]common.EnclaveID, error) { - rows, err := db.QueryContext(ctx, attSelectSequencers, 0, 2) + rows, err := db.QueryContext(ctx, attSelectSequencers, common.Sequencer) if err != nil { return nil, err } diff --git a/go/enclave/storage/storage.go b/go/enclave/storage/storage.go index 3ed8e5d781..bdab873976 100644 --- a/go/enclave/storage/storage.go +++ b/go/enclave/storage/storage.go @@ -469,10 +469,19 @@ func (s *storageImpl) StoreNodeType(ctx context.Context, enclaveId common.Enclav return fmt.Errorf("could not create DB transaction - %w", err) } defer dbTx.Rollback() - _, err = enclavedb.UpdateAttestation(ctx, dbTx, enclaveId, nodeType) + res, err := enclavedb.UpdateAttestation(ctx, dbTx, enclaveId, nodeType) if err != nil { return err } + + // we always expect to update exactly one row here, shouldn't be permissioning an enclave we don't recognize + rowsAffected, err := res.RowsAffected() + if err != nil { + return fmt.Errorf("could not get rows affected - %w", err) + } + if rowsAffected != 1 { + return fmt.Errorf("expected to update nodetype for 1 attested enclave, but updated %d", rowsAffected) + } err = dbTx.Commit() if err != nil { return fmt.Errorf("could not commit transaction - %w", err) diff --git a/go/host/enclave/guardian.go b/go/host/enclave/guardian.go index 0eacb6160e..1cc42c43e5 100644 --- a/go/host/enclave/guardian.go +++ b/go/host/enclave/guardian.go @@ -530,7 +530,7 @@ func (g *Guardian) processL1BlockTransactions(block *types.Header, metadatas []c metaData, err := g.enclaveClient.GetRollupData(context.Background(), r.Header.Hash()) if err != nil { - g.logger.Error("Could not fetch rollup metadata from enclave.", log.ErrKey, err) + g.logger.Error("Could not fetch rollup metadata from enclave.", log.RollupHashKey, r.Header.Hash(), log.ErrKey, err) } else { // TODO - This is a temporary fix, arrays should always match in practice... extMetadata := common.ExtRollupMetadata{} diff --git a/go/host/host.go b/go/host/host.go index 4ca421a8b9..47c913bbab 100644 --- a/go/host/host.go +++ b/go/host/host.go @@ -282,10 +282,10 @@ func (h *host) NewHeadsChan() chan *common.BatchHeader { // Checks the host config is valid. func (h *host) validateConfig() { - if h.config.IsGenesis && h.config.NodeType != common.ActiveSequencer { + if h.config.IsGenesis && h.config.NodeType != common.Sequencer { h.logger.Crit("genesis node must be the sequencer") } - if !h.config.IsGenesis && h.config.NodeType == common.ActiveSequencer { + if !h.config.IsGenesis && h.config.NodeType == common.Sequencer { h.logger.Crit("only the genesis node can be a sequencer") } diff --git a/go/host/l2/batchrepository.go b/go/host/l2/batchrepository.go index f2beab6ce3..ffab1aa02b 100644 --- a/go/host/l2/batchrepository.go +++ b/go/host/l2/batchrepository.go @@ -68,7 +68,7 @@ func NewBatchRepository(cfg *hostconfig.HostConfig, hostService batchRepoService validatedBatchSubscribers: subscription.NewManager[host.L2BatchHandler](), sl: hostService, storage: storage, - isSequencer: cfg.NodeType == common.ActiveSequencer, + isSequencer: cfg.NodeType == common.Sequencer, latestBatchSeqNo: big.NewInt(0), latestValidatedSeqNo: big.NewInt(0), running: atomic.Bool{}, diff --git a/go/host/p2p/p2p.go b/go/host/p2p/p2p.go index d73e44f479..f695e15378 100644 --- a/go/host/p2p/p2p.go +++ b/go/host/p2p/p2p.go @@ -68,7 +68,7 @@ func NewSocketP2PLayer(config *hostconfig.HostConfig, serviceLocator p2pServiceL stopControl: stopcontrol.New(), sl: serviceLocator, - isSequencer: config.NodeType == common.ActiveSequencer, + isSequencer: config.NodeType == common.Sequencer, ourBindAddress: config.P2PBindAddress, ourPublicAddress: config.P2PPublicAddress, sequencerAddress: config.SequencerP2PAddress, diff --git a/go/node/cmd/cli.go b/go/node/cmd/cli.go index 5a9b88ea15..7d0584689d 100644 --- a/go/node/cmd/cli.go +++ b/go/node/cmd/cli.go @@ -226,7 +226,7 @@ func NodeCLIConfigToTenConfig(cliCfg *NodeConfigCLI) *config.TenConfig { // the sequencer does not store the executed transactions // todo - once we replace this launcher we'll configure this flag explicitly via an environment variable - if nodeType == common.ActiveSequencer { + if nodeType == common.Sequencer { tenCfg.Enclave.StoreExecutedTransactions = false } diff --git a/integration/simulation/devnetwork/dev_network.go b/integration/simulation/devnetwork/dev_network.go index 39d5cbdd14..9cffcce3b8 100644 --- a/integration/simulation/devnetwork/dev_network.go +++ b/integration/simulation/devnetwork/dev_network.go @@ -186,7 +186,7 @@ func (s *InMemDevNetwork) GetGatewayClient() (ethadapter.EthClient, error) { func (s *InMemDevNetwork) startNodes() { if s.tenSequencer == nil { // initialise node operators (sequencer is node 0, validators are 1..N) - s.tenSequencer = NewInMemNodeOperator(0, s.tenConfig, common.ActiveSequencer, s.l1SetupData, s.l1Network.GetClient(0), s.networkWallets.NodeWallets[0], s.logger) + s.tenSequencer = NewInMemNodeOperator(0, s.tenConfig, common.Sequencer, s.l1SetupData, s.l1Network.GetClient(0), s.networkWallets.NodeWallets[0], s.logger) for i := 1; i <= s.tenConfig.InitNumValidators; i++ { l1Client := s.l1Network.GetClient(i % s.l1Network.NumNodes()) s.tenValidators = append(s.tenValidators, NewInMemNodeOperator(i, s.tenConfig, common.Validator, s.l1SetupData, l1Client, s.networkWallets.NodeWallets[i], s.logger)) diff --git a/integration/simulation/devnetwork/node.go b/integration/simulation/devnetwork/node.go index 03319e6936..927e882571 100644 --- a/integration/simulation/devnetwork/node.go +++ b/integration/simulation/devnetwork/node.go @@ -72,7 +72,7 @@ func (n *InMemNodeOperator) StopHost() error { func (n *InMemNodeOperator) Start() error { var err error numEnclaves := n.config.NumSeqEnclaves - if n.nodeType != common.ActiveSequencer { + if n.nodeType != common.Sequencer { numEnclaves = 1 } n.enclaves = make([]*enclavecontainer.EnclaveContainer, numEnclaves) @@ -115,7 +115,7 @@ func (n *InMemNodeOperator) StartEnclave(idx int) error { func (n *InMemNodeOperator) createHostContainer() *hostcontainer.HostContainer { enclavePort := n.config.PortStart + integration.DefaultEnclaveOffset + n.operatorIdx var enclaveAddresses []string - if n.nodeType == common.ActiveSequencer { + if n.nodeType == common.Sequencer { for i := 0; i < n.config.NumSeqEnclaves; i++ { enclaveAddresses = append(enclaveAddresses, fmt.Sprintf("%s:%d", network.Localhost, enclavePort+(i*_multiEnclaveOffset))) } @@ -129,7 +129,7 @@ func (n *InMemNodeOperator) createHostContainer() *hostcontainer.HostContainer { hostConfig := &hostconfig.HostConfig{ ID: fmt.Sprintf("%d", n.operatorIdx), - IsGenesis: n.nodeType == common.ActiveSequencer, + IsGenesis: n.nodeType == common.Sequencer, NodeType: n.nodeType, HasClientRPCHTTP: true, ClientRPCPortHTTP: uint64(n.config.PortStart + integration.DefaultHostRPCHTTPOffset + n.operatorIdx), @@ -272,7 +272,7 @@ func NewInMemNodeOperator(operatorIdx int, config *TenConfig, nodeType common.No ) *InMemNodeOperator { // todo (@matt) - put sqlite and levelDB storage in the same temp dir numEnclaves := config.NumSeqEnclaves - if nodeType != common.ActiveSequencer { + if nodeType != common.Sequencer { numEnclaves = 1 } sqliteDBPaths := make([]string, numEnclaves) diff --git a/integration/simulation/network/obscuro_node_utils.go b/integration/simulation/network/obscuro_node_utils.go index a7aa131d4c..f135dcd36d 100644 --- a/integration/simulation/network/obscuro_node_utils.go +++ b/integration/simulation/network/obscuro_node_utils.go @@ -194,7 +194,7 @@ func isAddressAvailable(address string) bool { func GetNodeType(i int) common.NodeType { // Only the genesis node is assigned the role of sequencer. if i == 0 { - return common.ActiveSequencer + return common.Sequencer } return common.Validator }