diff --git a/cmd/neofs-adm/internal/modules/morph/deploy.go b/cmd/neofs-adm/internal/modules/morph/deploy.go index 8e60c0603..8a3942276 100644 --- a/cmd/neofs-adm/internal/modules/morph/deploy.go +++ b/cmd/neofs-adm/internal/modules/morph/deploy.go @@ -14,6 +14,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" + "github.com/nspcc-dev/neofs-contract/nns" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -109,13 +110,53 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { emit.AppCallNoArgs(w.BinWriter, callHash, method, callflag.All) emit.Opcodes(w.BinWriter, opcode.DROP) // contract state on stack if !isUpdate { - s, err := c.nnsRegisterDomainScript(nnsCs.Hash, cs.Hash, domain) + bw := io.NewBufBinWriter() + emit.Instruction(bw.BinWriter, opcode.INITSSLOT, []byte{1}) + emit.AppCall(bw.BinWriter, nnsCs.Hash, "getPrice", callflag.All) + emit.Opcodes(bw.BinWriter, opcode.STSFLD0) + emit.AppCall(bw.BinWriter, nnsCs.Hash, "setPrice", callflag.All, 1) + + start := bw.Len() + newRecord := false + + ok, err := c.nnsRootRegistered(nnsCs.Hash, zone) if err != nil { return err + } else if !ok { + newRecord = true + + emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, + zone, c.CommitteeAcc.Contract.ScriptHash(), + "ops@nspcc.ru", int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) + emit.Opcodes(bw.BinWriter, opcode.ASSERT) + + emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, + domain, c.CommitteeAcc.Contract.ScriptHash(), + "ops@nspcc.ru", int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) + emit.Opcodes(bw.BinWriter, opcode.ASSERT) + + emit.AppCall(bw.BinWriter, nnsCs.Hash, "addRecord", callflag.All, + domain, int64(nns.TXT), cs.Hash.StringLE()) + } else { + s, err := c.nnsRegisterDomainScript(nnsCs.Hash, cs.Hash, domain, false) + if err != nil { + return err + } + if len(s) != 0 { + newRecord = true + bw.WriteBytes(s) + } } - if len(s) != 0 { - c.Command.Printf("NNS: Set %s -> %s\n", domain, cs.Hash.StringLE()) - w.WriteBytes(s) + if bw.Err != nil { + panic(fmt.Errorf("BUG: can't create deployment script: %w", w.Err)) + } else if bw.Len() != start { + w.WriteBytes(bw.Bytes()) + emit.Opcodes(w.BinWriter, opcode.LDSFLD0, opcode.PUSH1, opcode.PACK) + emit.AppCallNoArgs(w.BinWriter, nnsCs.Hash, "setPrice", callflag.All) + + if newRecord { + c.Command.Printf("NNS: Set %s -> %s\n", domain, cs.Hash.StringLE()) + } } } diff --git a/cmd/neofs-adm/internal/modules/morph/initialize_deploy.go b/cmd/neofs-adm/internal/modules/morph/initialize_deploy.go index 494300e93..df88989d2 100644 --- a/cmd/neofs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/neofs-adm/internal/modules/morph/initialize_deploy.go @@ -263,7 +263,7 @@ func (c *initializeContext) updateContracts() error { if method == deployMethodName { // same actions are done in initializeContext.setNNS, can be unified domain := ctrName + ".neofs" - script, err := c.nnsRegisterDomainScript(nnsHash, cs.Hash, domain) + script, err := c.nnsRegisterDomainScript(nnsHash, cs.Hash, domain, true) if err != nil { return err } diff --git a/cmd/neofs-adm/internal/modules/morph/initialize_nns.go b/cmd/neofs-adm/internal/modules/morph/initialize_nns.go index 69deefe21..8b588ec40 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 ( "encoding/hex" "errors" "fmt" + "math/big" "strconv" "strings" "time" @@ -33,7 +34,7 @@ func (c *initializeContext) setNNS() error { return err } - ok, err := c.nnsRootRegistered(nnsCs.Hash) + ok, err := c.nnsRootRegistered(nnsCs.Hash, "neofs") if err != nil { return err } else if !ok { @@ -125,26 +126,29 @@ func getAlphabetNNSDomain(i int) string { return alphabetContract + strconv.FormatUint(uint64(i), 10) + ".neofs" } -func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.Uint160, domain string) ([]byte, error) { +func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.Uint160, domain string, setPrice bool) ([]byte, error) { ok, err := nnsIsAvailable(c.Client, nnsHash, domain) if err != nil { return nil, err } - res, err := invokeFunction(c.Client, nnsHash, "getPrice", nil, nil) - if err != nil || res.State != vmstate.Halt.String() || len(res.Stack) == 0 { - return nil, errors.New("could not get NNS's price") - } - - price, err := res.Stack[0].TryInteger() - if err != nil { - return nil, fmt.Errorf("unexpected `GetPrice` stack returned: %w", err) - } - bw := io.NewBufBinWriter() if ok { - // set minimal registration price - emit.AppCall(bw.BinWriter, nnsHash, "setPrice", callflag.All, 1) + var price *big.Int + if setPrice { + res, err := invokeFunction(c.Client, nnsHash, "getPrice", nil, nil) + if err != nil || res.State != vmstate.Halt.String() || len(res.Stack) == 0 { + return nil, errors.New("could not get NNS's price") + } + + price, err = res.Stack[0].TryInteger() + if err != nil { + return nil, fmt.Errorf("unexpected `GetPrice` stack returned: %w", err) + } + + // set minimal registration price + emit.AppCall(bw.BinWriter, nnsHash, "setPrice", callflag.All, 1) + } // register domain emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All, @@ -152,8 +156,10 @@ func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.U "ops@nspcc.ru", int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) - // set registration price back - emit.AppCall(bw.BinWriter, nnsHash, "setPrice", callflag.All, price) + if setPrice { + // set registration price back + emit.AppCall(bw.BinWriter, nnsHash, "setPrice", callflag.All, price) + } } else { s, err := nnsResolveHash(c.Client, nnsHash, domain) if err != nil { @@ -174,7 +180,7 @@ func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.U } func (c *initializeContext) nnsRegisterDomain(nnsHash, expectedHash util.Uint160, domain string) error { - script, err := c.nnsRegisterDomainScript(nnsHash, expectedHash, domain) + script, err := c.nnsRegisterDomainScript(nnsHash, expectedHash, domain, true) if script == nil { return err } @@ -182,8 +188,8 @@ func (c *initializeContext) nnsRegisterDomain(nnsHash, expectedHash util.Uint160 return c.sendCommitteeTx(script, sysFee, true) } -func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160) (bool, error) { - params := []interface{}{"name.neofs"} +func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160, zone string) (bool, error) { + params := []interface{}{"name." + zone} res, err := invokeFunction(c.Client, nnsHash, "isAvailable", params, nil) if err != nil { return false, err