diff --git a/.github/workflows/manual-deploy-testnet-l2.yml b/.github/workflows/manual-deploy-testnet-l2.yml index 821bc1e37..ab714004d 100644 --- a/.github/workflows/manual-deploy-testnet-l2.yml +++ b/.github/workflows/manual-deploy-testnet-l2.yml @@ -359,11 +359,43 @@ jobs: -postgres_db_host=postgres://tenuser:${{ secrets.TEN_POSTGRES_USER_PWD }}@postgres-ten-${{ github.event.inputs.testnet_type }}.postgres.database.azure.com:5432/ \ start' - check-obscuro-is-healthy: + grant-sequencer-enclaves: needs: - build - deploy runs-on: ubuntu-latest + environment: + name: ${{ github.event.inputs.testnet_type }} + steps: + - uses: actions/checkout@v4 + + - name: 'Grant permission to sequencer enclave(s)' + id: grantSequencerPermission + shell: bash + run: | + go run ./testnet/launcher/l1grantsequencers/cmd \ + -l1_http_url=${{ secrets.L1_HTTP_URL }} \ + -l2_ws_port=81 \ + -private_key=${{ secrets.ACCOUNT_PK_WORKER }} \ + -management_contract_addr=${{ needs.build.outputs.MGMT_CONTRACT_ADDR }} \ + -docker_image=${{ vars.L2_HARDHATDEPLOYER_DOCKER_BUILD_TAG }} \ + + - name: 'Save sequencer permissioning container logs' + run: | + docker logs `docker ps -aqf "name=grant-sequencers"` > grant-sequencers.out 2>&1 + + - name: 'Upload sequencer permissioning container logs' + uses: actions/upload-artifact@v4 + with: + name: grant-sequencers + path: | + grant-sequencers.out + retention-days: 7 + + check-obscuro-is-healthy: + needs: + - grant-sequencer-enclaves + runs-on: ubuntu-latest environment: name: ${{ github.event.inputs.testnet_type }} steps: diff --git a/testnet/launcher/docker.go b/testnet/launcher/docker.go index 48a199359..d175c9ca1 100644 --- a/testnet/launcher/docker.go +++ b/testnet/launcher/docker.go @@ -2,7 +2,6 @@ package launcher import ( "fmt" - "strings" "time" "github.com/ethereum/go-ethereum/common" @@ -304,27 +303,6 @@ func waitForHealthyNode(port int) error { // todo: hook the cfg func (t *Testnet) grantSequencerStatus(mgmtContractAddr string) error { // fetch enclaveIDs hostURL := fmt.Sprintf("http://localhost:%d", 80) - client, err := rpc.NewNetworkClient(hostURL) - if err != nil { - return fmt.Errorf("failed to create network client: %w", err) - } - defer client.Stop() - - obsClient := obsclient.NewObsClient(client) - health, err := obsClient.Health() - if err != nil { - return fmt.Errorf("failed to get health status: %w", err) - } - - if len(health.Enclaves) == 0 { - return fmt.Errorf("could not retrieve enclave IDs from health endpoint") - } - - var enclaveIDs []string - for _, status := range health.Enclaves { - enclaveIDs = append(enclaveIDs, status.EnclaveID.String()) - } - enclaveIDsStr := strings.Join(enclaveIDs, ",") l1grantsequencers, err := l1gs.NewGrantSequencers( l1gs.NewGrantSequencerConfig( @@ -332,7 +310,7 @@ func (t *Testnet) grantSequencerStatus(mgmtContractAddr string) error { l1gs.WithPrivateKey("f52e5418e349dccdda29b6ac8b0abe6576bb7713886aa85abea6181ba731f9bb"), l1gs.WithDockerImage(t.cfg.contractDeployerDockerImage), l1gs.WithMgmtContractAddress(mgmtContractAddr), - l1gs.WithEnclaveIDs(enclaveIDsStr), + l1gs.WithSequencerURL(hostURL), ), ) if err != nil { diff --git a/testnet/launcher/l1grantsequencers/cmd/cli.go b/testnet/launcher/l1grantsequencers/cmd/cli.go index 15e141814..9aa2a7347 100644 --- a/testnet/launcher/l1grantsequencers/cmd/cli.go +++ b/testnet/launcher/l1grantsequencers/cmd/cli.go @@ -11,6 +11,7 @@ type L1GrantSequencersConfigCLI struct { mgmtContractAddress string enclaveIDs string dockerImage string + sequencerURL string } // ParseConfigCLI returns a NodeConfigCLI based the cli params and defaults. @@ -23,6 +24,7 @@ func ParseConfigCLI() *L1GrantSequencersConfigCLI { mgmtContractAddress := flag.String(mgmtContractAddressFlag, "", flagUsageMap[mgmtContractAddressFlag]) enclaveIDs := flag.String(enclaveIDsFlag, "", flagUsageMap[enclaveIDsFlag]) dockerImage := flag.String(dockerImageFlag, "testnetobscuronet.azurecr.io/obscuronet/hardhatdeployer:latest", flagUsageMap[dockerImageFlag]) + sequencerURL := flag.String(sequencerURLFlag, "", flagUsageMap[sequencerURLFlag]) flag.Parse() cfg.l1HTTPURL = *l1HTTPURL @@ -30,6 +32,7 @@ func ParseConfigCLI() *L1GrantSequencersConfigCLI { cfg.mgmtContractAddress = *mgmtContractAddress cfg.enclaveIDs = *enclaveIDs cfg.dockerImage = *dockerImage + cfg.sequencerURL = *sequencerURL return cfg } diff --git a/testnet/launcher/l1grantsequencers/cmd/cli_flags.go b/testnet/launcher/l1grantsequencers/cmd/cli_flags.go index e85a6a9ae..067f57925 100644 --- a/testnet/launcher/l1grantsequencers/cmd/cli_flags.go +++ b/testnet/launcher/l1grantsequencers/cmd/cli_flags.go @@ -8,6 +8,7 @@ const ( enclaveIDsFlag = "enclave_ids" dockerImageFlag = "docker_image" contractsEnvFileFlag = "contracts_env_file" + sequencerURLFlag = "sequencer_url" ) // Returns a map of the flag usages. @@ -17,8 +18,9 @@ func getFlagUsageMap() map[string]string { l1HTTPURLFlag: "Layer 1 network http RPC addr", privateKeyFlag: "L1 and L2 private key used in the node", mgmtContractAddressFlag: "L1 management contract address", - enclaveIDsFlag: "List of enclave public keys", + enclaveIDsFlag: "List of enclave public keys to grant sequencer role", dockerImageFlag: "Docker image to run", contractsEnvFileFlag: "If set, it will write the contract addresses to the file", + sequencerURLFlag: "Sequencer RPC URL to fetch enclave IDs (required if enclaveIDs are not provided)", } } diff --git a/testnet/launcher/l1grantsequencers/cmd/main.go b/testnet/launcher/l1grantsequencers/cmd/main.go index 6273ecee0..3b43406f6 100644 --- a/testnet/launcher/l1grantsequencers/cmd/main.go +++ b/testnet/launcher/l1grantsequencers/cmd/main.go @@ -17,6 +17,7 @@ func main() { l1gs.WithDockerImage(cliConfig.dockerImage), l1gs.WithMgmtContractAddress(cliConfig.mgmtContractAddress), l1gs.WithEnclaveIDs(cliConfig.enclaveIDs), + l1gs.WithSequencerURL(cliConfig.sequencerURL), ), ) if err != nil { diff --git a/testnet/launcher/l1grantsequencers/config.go b/testnet/launcher/l1grantsequencers/config.go index a230311cd..0345e6b59 100644 --- a/testnet/launcher/l1grantsequencers/config.go +++ b/testnet/launcher/l1grantsequencers/config.go @@ -10,6 +10,8 @@ type Config struct { mgmtContractAddress string enclaveIDs string dockerImage string + sequencerURL string + // debugEnabled bool } @@ -53,6 +55,12 @@ func WithDockerImage(s string) Option { } } +func WithSequencerURL(s string) Option { + return func(c *Config) { + c.sequencerURL = s + } +} + //func WithDebugEnabled(b bool) Option { // return func(c *Config) { // c.debugEnabled = b diff --git a/testnet/launcher/l1grantsequencers/docker.go b/testnet/launcher/l1grantsequencers/docker.go index 41eb56cf5..aa57022d0 100644 --- a/testnet/launcher/l1grantsequencers/docker.go +++ b/testnet/launcher/l1grantsequencers/docker.go @@ -2,8 +2,11 @@ package l1grantsequencers import ( "fmt" + "strings" "github.com/ten-protocol/go-ten/go/common/docker" + "github.com/ten-protocol/go-ten/go/obsclient" + "github.com/ten-protocol/go-ten/go/rpc" ) type GrantSequencers struct { @@ -18,6 +21,18 @@ func NewGrantSequencers(cfg *Config) (*GrantSequencers, error) { } func (s *GrantSequencers) Start() error { + var enclaveIDs string + var err error + if s.cfg.enclaveIDs != "" { + enclaveIDs = s.cfg.enclaveIDs + } else if s.cfg.sequencerURL != "" { + enclaveIDs, err = fetchEnclaveIDs(s.cfg.sequencerURL) + if err != nil { + return err + } + } else { + return fmt.Errorf("enclaveIDs or sequencerURL must be provided") + } cmds := []string{ "npx", "run", @@ -25,7 +40,7 @@ func (s *GrantSequencers) Start() error { "layer1", "scripts/sequencer/001_grant_sequencers.ts", s.cfg.mgmtContractAddress, - s.cfg.enclaveIDs, + enclaveIDs, } envs := map[string]string{ @@ -55,3 +70,28 @@ func (s *GrantSequencers) Start() error { s.containerID = containerID return nil } + +func fetchEnclaveIDs(url string) (string, error) { + // fetch enclaveIDs + client, err := rpc.NewNetworkClient(url) + if err != nil { + return "", fmt.Errorf("failed to create network client (%s): %w", url, err) + } + defer client.Stop() + + obsClient := obsclient.NewObsClient(client) + health, err := obsClient.Health() + if err != nil { + return "", fmt.Errorf("failed to get health status: %w", err) + } + + if len(health.Enclaves) == 0 { + return "", fmt.Errorf("could not retrieve enclave IDs from health endpoint - no enclaves found") + } + + var enclaveIDs []string + for _, status := range health.Enclaves { + enclaveIDs = append(enclaveIDs, status.EnclaveID.String()) + } + return strings.Join(enclaveIDs, ","), nil +}