From 2f2ca2e0bde325c24f5525f4dad66ac78ed9073c Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Mon, 29 Nov 2021 13:15:03 +0300 Subject: [PATCH] [#979] adm: Deploy missing contracts during updating Make `nnsResolveHash` function to return declared error on `token not found` fault exception. Catch this error in `deployContracts` method, and switch to deployment if updating contract is missing. Signed-off-by: Leonard Lyubich --- .../internal/modules/morph/initialize.go | 4 ++-- .../modules/morph/initialize_deploy.go | 20 +++++++++++++++---- .../internal/modules/morph/initialize_nns.go | 7 +++++++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/cmd/neofs-adm/internal/modules/morph/initialize.go b/cmd/neofs-adm/internal/modules/morph/initialize.go index dc8933b1c..faa3df537 100644 --- a/cmd/neofs-adm/internal/modules/morph/initialize.go +++ b/cmd/neofs-adm/internal/modules/morph/initialize.go @@ -57,13 +57,13 @@ func initializeSideChainCmd(cmd *cobra.Command, args []string) error { // 3. Deploy NNS contract. cmd.Println("Stage 3: deploy NNS contract.") - if err := initCtx.deployNNS("deploy"); err != nil { + if err := initCtx.deployNNS(deployMethodName); err != nil { return err } // 4. Deploy NeoFS contracts. cmd.Println("Stage 4: deploy NeoFS contracts.") - if err := initCtx.deployContracts("deploy"); err != nil { + if err := initCtx.deployContracts(deployMethodName); err != nil { return err } diff --git a/cmd/neofs-adm/internal/modules/morph/initialize_deploy.go b/cmd/neofs-adm/internal/modules/morph/initialize_deploy.go index aeeae5d3a..0c9db3d32 100644 --- a/cmd/neofs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/neofs-adm/internal/modules/morph/initialize_deploy.go @@ -4,6 +4,7 @@ import ( "archive/tar" "compress/gzip" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -83,7 +84,10 @@ type contractState struct { Hash util.Uint160 } -const updateMethodName = "update" +const ( + updateMethodName = "update" + deployMethodName = "deploy" +) func (c *initializeContext) deployNNS(method string) error { cs := c.getContract(nnsContract) @@ -214,10 +218,18 @@ func (c *initializeContext) deployContracts(method string) error { cs := c.Contracts[ctrName] ctrHash := cs.Hash + + methodCur := method // prevent overriding in if-block + if method == updateMethodName { ctrHash, err = nnsResolveHash(c.Client, nnsHash, ctrName+".neofs") if err != nil { - return fmt.Errorf("can't resolve hash for contract update: %w", err) + if errors.Is(err, errMissingNNSRecord) { + // if contract not found we deploy it instead of update + methodCur = deployMethodName + } else { + return fmt.Errorf("can't resolve hash for contract update: %w", err) + } } } if c.isUpdated(ctrHash, cs) { @@ -226,7 +238,7 @@ func (c *initializeContext) deployContracts(method string) error { } invokeHash := mgmtHash - if method == updateMethodName { + if methodCur == updateMethodName { invokeHash = ctrHash } @@ -237,7 +249,7 @@ func (c *initializeContext) deployContracts(method string) error { Scopes: transaction.Global, } - res, err := c.Client.InvokeFunction(invokeHash, method, params, []transaction.Signer{signer}) + res, err := c.Client.InvokeFunction(invokeHash, methodCur, params, []transaction.Signer{signer}) if err != nil { return fmt.Errorf("can't deploy %s contract: %w", ctrName, err) } diff --git a/cmd/neofs-adm/internal/modules/morph/initialize_nns.go b/cmd/neofs-adm/internal/modules/morph/initialize_nns.go index ecfb16add..9558299f9 100644 --- a/cmd/neofs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/neofs-adm/internal/modules/morph/initialize_nns.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "strconv" + "strings" nns "github.com/nspcc-dev/neo-go/examples/nft-nd-nns" "github.com/nspcc-dev/neo-go/pkg/core/native" @@ -116,6 +117,9 @@ func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160) (bool, error return res.State == vm.HaltState.String(), nil } +var errMissingNNSRecord = errors.New("missing NNS record") + +// Returns errMissingNNSRecord if invocation fault exception contains "token not found". func nnsResolveHash(c *client.Client, nnsHash util.Uint160, domain string) (util.Uint160, error) { result, err := c.InvokeFunction(nnsHash, "resolve", []smartcontract.Parameter{ { @@ -131,6 +135,9 @@ func nnsResolveHash(c *client.Client, nnsHash util.Uint160, domain string) (util return util.Uint160{}, fmt.Errorf("`resolve`: %w", err) } if result.State != vm.HaltState.String() { + if strings.Contains(result.FaultException, "token not found") { + return util.Uint160{}, errMissingNNSRecord + } return util.Uint160{}, fmt.Errorf("invocation failed: %s", result.FaultException) } if len(result.Stack) == 0 {