2024-02-02 06:49:03 +00:00
|
|
|
package util
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2024-02-02 12:26:57 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
|
2024-02-02 06:49:03 +00:00
|
|
|
"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)
|
|
|
|
}
|
2024-02-02 12:26:57 +00:00
|
|
|
fidHash, err := NNSResolveHash(roInvoker, cs.Hash, DomainOf(constants.FrostfsIDContract))
|
2024-02-02 06:49:03 +00:00
|
|
|
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 {
|
2024-02-02 12:26:57 +00:00
|
|
|
case constants.FrostfsContract:
|
2024-02-02 06:49:03 +00:00
|
|
|
items = append(items,
|
2024-02-02 12:26:57 +00:00
|
|
|
c.Contracts[constants.ProcessingContract].Hash,
|
2024-02-02 06:49:03 +00:00
|
|
|
keysParam,
|
|
|
|
smartcontract.Parameter{})
|
2024-02-02 12:26:57 +00:00
|
|
|
case constants.ProcessingContract:
|
|
|
|
items = append(items, c.Contracts[constants.FrostfsContract].Hash)
|
2024-02-02 06:49:03 +00:00
|
|
|
return items[1:], nil // no notary info
|
2024-02-02 12:26:57 +00:00
|
|
|
case constants.BalanceContract:
|
2024-02-02 06:49:03 +00:00
|
|
|
items = append(items,
|
2024-02-02 12:26:57 +00:00
|
|
|
c.Contracts[constants.NetmapContract].Hash,
|
|
|
|
c.Contracts[constants.ContainerContract].Hash)
|
|
|
|
case constants.ContainerContract:
|
2024-02-02 06:49:03 +00:00
|
|
|
// 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,
|
2024-02-02 12:26:57 +00:00
|
|
|
c.Contracts[constants.NetmapContract].Hash,
|
|
|
|
c.Contracts[constants.BalanceContract].Hash,
|
|
|
|
c.Contracts[constants.FrostfsIDContract].Hash,
|
2024-02-02 06:49:03 +00:00
|
|
|
nnsCs.Hash,
|
|
|
|
"container")
|
2024-02-02 12:26:57 +00:00
|
|
|
case constants.FrostfsIDContract:
|
2024-02-02 06:49:03 +00:00
|
|
|
var (
|
|
|
|
h util.Uint160
|
|
|
|
found bool
|
|
|
|
err error
|
|
|
|
)
|
2024-02-02 12:26:57 +00:00
|
|
|
if method == constants.UpdateMethodName {
|
2024-02-02 06:49:03 +00:00
|
|
|
h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker)
|
|
|
|
}
|
2024-02-02 12:26:57 +00:00
|
|
|
if method != constants.UpdateMethodName || err == nil && !found {
|
2024-02-02 06:49:03 +00:00
|
|
|
h, found, err = GetFrostfsIDAdmin(viper.GetViper())
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if found {
|
|
|
|
items = append(items, h)
|
|
|
|
} else {
|
2024-02-02 12:26:57 +00:00
|
|
|
items = append(items, c.Contracts[constants.ProxyContract].Hash)
|
2024-02-02 06:49:03 +00:00
|
|
|
}
|
2024-02-02 12:26:57 +00:00
|
|
|
case constants.NetmapContract:
|
2024-02-02 06:49:03 +00:00
|
|
|
md := GetDefaultNetmapContractConfigMap()
|
2024-02-02 12:26:57 +00:00
|
|
|
if method == constants.UpdateMethodName {
|
2024-02-02 06:49:03 +00:00
|
|
|
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,
|
2024-02-02 12:26:57 +00:00
|
|
|
c.Contracts[constants.BalanceContract].Hash,
|
|
|
|
c.Contracts[constants.ContainerContract].Hash,
|
2024-02-02 06:49:03 +00:00
|
|
|
keysParam,
|
|
|
|
configParam)
|
2024-02-02 12:26:57 +00:00
|
|
|
case constants.ProxyContract:
|
2024-02-02 06:49:03 +00:00
|
|
|
items = nil
|
2024-02-02 12:26:57 +00:00
|
|
|
case constants.PolicyContract:
|
|
|
|
items = append(items, c.Contracts[constants.ProxyContract].Hash)
|
2024-02-02 06:49:03 +00:00
|
|
|
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 {
|
2024-02-02 12:26:57 +00:00
|
|
|
cs := c.GetContract(constants.NNSContract)
|
2024-02-02 06:49:03 +00:00
|
|
|
h := cs.Hash
|
|
|
|
|
|
|
|
nnsCs, err := c.NNSContractState()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if nnsCs != nil {
|
|
|
|
if nnsCs.NEF.Checksum == cs.NEF.Checksum {
|
2024-02-02 12:26:57 +00:00
|
|
|
if method == constants.DeployMethodName {
|
2024-02-02 06:49:03 +00:00
|
|
|
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
|
2024-02-02 12:26:57 +00:00
|
|
|
if method == constants.UpdateMethodName {
|
2024-02-02 06:49:03 +00:00
|
|
|
invokeHash = nnsCs.Hash
|
|
|
|
}
|
|
|
|
|
|
|
|
tx, err := c.CommitteeAct.MakeCall(invokeHash, method, params...)
|
|
|
|
if err != nil {
|
2024-02-02 12:26:57 +00:00
|
|
|
return fmt.Errorf("failed to create deploy tx for %s: %w", constants.NNSContract, err)
|
2024-02-02 06:49:03 +00:00
|
|
|
}
|
|
|
|
|
2024-02-02 12:26:57 +00:00
|
|
|
if err := c.MultiSignAndSend(tx, constants.CommitteeAccountName); err != nil {
|
2024-02-02 06:49:03 +00:00
|
|
|
return fmt.Errorf("can't send deploy transaction: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.AwaitTx()
|
|
|
|
}
|