frostfs-node/cmd/frostfs-adm/internal/modules/morph/util/contract.go
Anton Nikiforov 76343f19e5 [#932] adm: Move update-contracts to package contract
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2024-02-13 09:59:27 +03:00

169 lines
4.5 KiB
Go

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()
}