package util import ( "fmt" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/spf13/viper" ) func getFrostfsIDAdminFromContract(roInvoker *invoker.Invoker) (util.Uint160, bool, error) { r := management.NewReader(roInvoker) cs, err := r.GetContractByID(1) if err != nil { return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err) } fidHash, err := NNSResolveHash(roInvoker, cs.Hash, DomainOf(FrostfsIDContract)) if err != nil { return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err) } item, err := unwrap.Item(roInvoker.Call(fidHash, "getAdmin")) if err != nil { return util.Uint160{}, false, fmt.Errorf("getAdmin: %w", err) } if _, ok := item.(stackitem.Null); ok { return util.Uint160{}, false, nil } bs, err := item.TryBytes() if err != nil { return util.Uint160{}, true, fmt.Errorf("getAdmin: decode result: %w", err) } h, err := util.Uint160DecodeBytesBE(bs) if err != nil { return util.Uint160{}, true, fmt.Errorf("getAdmin: decode result: %w", err) } return h, true, nil } func GetContractDeployData(c *InitializeContext, ctrName string, keysParam []any, method string) ([]any, error) { items := make([]any, 0, 6) switch ctrName { case FrostfsContract: items = append(items, c.Contracts[ProcessingContract].Hash, keysParam, smartcontract.Parameter{}) case ProcessingContract: items = append(items, c.Contracts[FrostfsContract].Hash) return items[1:], nil // no notary info case BalanceContract: items = append(items, c.Contracts[NetmapContract].Hash, c.Contracts[ContainerContract].Hash) case ContainerContract: // In case if NNS is updated multiple times, we can't calculate // it's actual hash based on local data, thus query chain. r := management.NewReader(c.ReadOnlyInvoker) nnsCs, err := r.GetContractByID(1) if err != nil { return nil, fmt.Errorf("get nns contract: %w", err) } items = append(items, c.Contracts[NetmapContract].Hash, c.Contracts[BalanceContract].Hash, c.Contracts[FrostfsIDContract].Hash, nnsCs.Hash, "container") case FrostfsIDContract: var ( h util.Uint160 found bool err error ) if method == UpdateMethodName { h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker) } if method != UpdateMethodName || err == nil && !found { h, found, err = GetFrostfsIDAdmin(viper.GetViper()) } if err != nil { return nil, err } if found { items = append(items, h) } else { items = append(items, c.Contracts[ProxyContract].Hash) } case NetmapContract: md := GetDefaultNetmapContractConfigMap() if method == UpdateMethodName { if err := MergeNetmapConfig(c.ReadOnlyInvoker, md); err != nil { return nil, err } } var configParam []any for k, v := range md { configParam = append(configParam, k, v) } items = append(items, c.Contracts[BalanceContract].Hash, c.Contracts[ContainerContract].Hash, keysParam, configParam) case ProxyContract: items = nil case PolicyContract: items = append(items, c.Contracts[ProxyContract].Hash) default: panic(fmt.Sprintf("invalid contract name: %s", ctrName)) } return items, nil } func GetContractDeployParameters(cs *ContractState, deployData []any) []any { return []any{cs.RawNEF, cs.RawManifest, deployData} } func DeployNNS(c *InitializeContext, method string) error { cs := c.GetContract(NNSContract) h := cs.Hash nnsCs, err := c.NNSContractState() if err != nil { return err } if nnsCs != nil { if nnsCs.NEF.Checksum == cs.NEF.Checksum { if method == DeployMethodName { c.Command.Println("NNS contract is already deployed.") } else { c.Command.Println("NNS contract is already updated.") } return nil } h = nnsCs.Hash } err = AddManifestGroup(c.ContractWallet, h, cs) if err != nil { return fmt.Errorf("can't sign manifest group: %v", err) } params := GetContractDeployParameters(cs, nil) invokeHash := management.Hash if method == UpdateMethodName { invokeHash = nnsCs.Hash } tx, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) if err != nil { return fmt.Errorf("failed to create deploy tx for %s: %w", NNSContract, err) } if err := c.MultiSignAndSend(tx, CommitteeAccountName); err != nil { return fmt.Errorf("can't send deploy transaction: %w", err) } return c.AwaitTx() }