[#932] adm: Prepare to move `InitializeContext` to `util` package

Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
pull/950/head
Anton Nikiforov 2024-02-01 14:30:59 +03:00
parent bee3741f4e
commit b68f7be0b6
20 changed files with 277 additions and 270 deletions

View File

@ -85,7 +85,7 @@ func setConfigCmd(cmd *cobra.Command, args []string) error {
return errors.New("empty config pairs")
}
wCtx, err := newInitializeContext(cmd, viper.GetViper())
wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil {
return fmt.Errorf("can't initialize context: %w", err)
}
@ -119,12 +119,12 @@ func setConfigCmd(cmd *cobra.Command, args []string) error {
}
}
err = wCtx.sendConsensusTx(bw.Bytes())
err = wCtx.SendConsensusTx(bw.Bytes())
if err != nil {
return err
}
return wCtx.awaitTx()
return wCtx.AwaitTx()
}
func parseConfigPair(kvStr string, force bool) (key string, val any, err error) {

View File

@ -193,11 +193,11 @@ func restoreContainers(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("invalid filename: %w", err)
}
wCtx, err := newInitializeContext(cmd, viper.GetViper())
wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil {
return err
}
defer wCtx.close()
defer wCtx.Close()
containers, err := parseContainers(filename)
if err != nil {
@ -219,10 +219,10 @@ func restoreContainers(cmd *cobra.Command, _ []string) error {
return err
}
return wCtx.awaitTx()
return wCtx.AwaitTx()
}
func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd *cobra.Command, wCtx *initializeContext, ch util.Uint160) error {
func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd *cobra.Command, wCtx *InitializeContext, ch util.Uint160) error {
bw := io.NewBufBinWriter()
for _, cnt := range containers {
hv := hash.Sha256(cnt.Value)
@ -246,7 +246,7 @@ func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd
panic(bw.Err)
}
if err := wCtx.sendConsensusTx(bw.Bytes()); err != nil {
if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil {
return err
}
}
@ -262,7 +262,7 @@ func putContainer(bw *io.BufBinWriter, ch util.Uint160, cnt Container) {
}
}
func isContainerRestored(cmd *cobra.Command, wCtx *initializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) {
func isContainerRestored(cmd *cobra.Command, wCtx *InitializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) {
emit.AppCall(bw.BinWriter, containerHash, "get", callflag.All, hashValue.BytesBE())
res, err := wCtx.Client.InvokeScript(bw.Bytes(), nil)
if err != nil {
@ -300,7 +300,7 @@ func parseContainers(filename string) ([]Container, error) {
return containers, nil
}
func fetchContainerContractHash(wCtx *initializeContext) (util.Uint160, error) {
func fetchContainerContractHash(wCtx *InitializeContext) (util.Uint160, error) {
r := management.NewReader(wCtx.ReadOnlyInvoker)
nnsCs, err := r.GetContractByID(1)
if err != nil {

View File

@ -60,11 +60,11 @@ func init() {
func deployContractCmd(cmd *cobra.Command, args []string) error {
v := viper.GetViper()
c, err := newInitializeContext(cmd, v)
c, err := NewInitializeContext(cmd, v)
if err != nil {
return fmt.Errorf("initialization error: %w", err)
}
defer c.close()
defer c.Close()
ctrPath, _ := cmd.Flags().GetString(contractPathFlag)
ctrName, err := probeContractName(ctrPath)
@ -123,13 +123,13 @@ func deployContractCmd(cmd *cobra.Command, args []string) error {
panic(fmt.Errorf("BUG: can't create deployment script: %w", writer.Err))
}
if err := c.sendCommitteeTx(writer.Bytes(), false); err != nil {
if err := c.SendCommitteeTx(writer.Bytes(), false); err != nil {
return err
}
return c.awaitTx()
return c.AwaitTx()
}
func registerNNS(nnsCs *state.Contract, c *initializeContext, zone string, domain string, cs *contractState, writer *io.BufBinWriter) error {
func registerNNS(nnsCs *state.Contract, c *InitializeContext, zone string, domain string, cs *util.ContractState, writer *io.BufBinWriter) error {
bw := io.NewBufBinWriter()
emit.Instruction(bw.BinWriter, opcode.INITSSLOT, []byte{1})
emit.AppCall(bw.BinWriter, nnsCs.Hash, "getPrice", callflag.All)
@ -139,7 +139,7 @@ func registerNNS(nnsCs *state.Contract, c *initializeContext, zone string, domai
start := bw.Len()
needRecord := false
ok, err := c.nnsRootRegistered(nnsCs.Hash, zone)
ok, err := c.NNSRootRegistered(nnsCs.Hash, zone)
if err != nil {
return err
} else if !ok {
@ -155,7 +155,7 @@ func registerNNS(nnsCs *state.Contract, c *initializeContext, zone string, domai
frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600))
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
} else {
s, ok, err := c.nnsRegisterDomainScript(nnsCs.Hash, cs.Hash, domain)
s, ok, err := c.NNSRegisterDomainScript(nnsCs.Hash, cs.Hash, domain)
if err != nil {
return err
}

View File

@ -54,7 +54,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error {
irSize := 0
for ; irSize < lastGlagoliticLetter; irSize++ {
ok, err := nnsIsAvailable(c, cs.Hash, getAlphabetNNSDomain(irSize))
ok, err := morphUtil.NNSIsAvailable(c, cs.Hash, getAlphabetNNSDomain(irSize))
if err != nil {
return err
} else if ok {

View File

@ -17,7 +17,7 @@ import (
)
func forceNewEpochCmd(cmd *cobra.Command, _ []string) error {
wCtx, err := newInitializeContext(cmd, viper.GetViper())
wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil {
return fmt.Errorf("can't to initialize context: %w", err)
}
@ -38,8 +38,8 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error {
return err
}
if err = wCtx.sendConsensusTx(bw.Bytes()); err == nil {
err = wCtx.awaitTx()
if err = wCtx.SendConsensusTx(bw.Bytes()); err == nil {
err = wCtx.AwaitTx()
}
if err != nil && strings.Contains(err.Error(), "invalid epoch") {
cmd.Println("Epoch has already ticked.")
@ -48,7 +48,7 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error {
return err
}
func emitNewEpochCall(bw *io.BufBinWriter, wCtx *initializeContext, nmHash util.Uint160) error {
func emitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util.Uint160) error {
curr, err := unwrap.Int64(wCtx.ReadOnlyInvoker.Call(nmHash, "epoch"))
if err != nil {
return errors.New("can't fetch current epoch from the netmap contract")

View File

@ -416,11 +416,11 @@ type frostfsidClient struct {
bw *io.BufBinWriter
contractHash util.Uint160
roCli *frostfsidclient.Client // client can be used only for waiting tx, parsing and forming method params
wCtx *initializeContext
wCtx *InitializeContext
}
func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) {
wCtx, err := newInitializeContext(cmd, viper.GetViper())
wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil {
return nil, fmt.Errorf("can't to initialize context: %w", err)
}
@ -449,16 +449,16 @@ func (f *frostfsidClient) addCall(method string, args []any) {
}
func (f *frostfsidClient) sendWait() error {
if err := f.wCtx.sendConsensusTx(f.bw.Bytes()); err != nil {
if err := f.wCtx.SendConsensusTx(f.bw.Bytes()); err != nil {
return err
}
f.bw.Reset()
return f.wCtx.awaitTx()
return f.wCtx.AwaitTx()
}
func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) {
if err := f.wCtx.sendConsensusTx(f.bw.Bytes()); err != nil {
if err := f.wCtx.SendConsensusTx(f.bw.Bytes()); err != nil {
return nil, err
}
f.bw.Reset()

View File

@ -195,7 +195,7 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error
return err
}
wCtx, err := newInitializeContext(cmd, viper.GetViper())
wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil {
return err
}
@ -208,11 +208,11 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error
return fmt.Errorf("BUG: invalid transfer arguments: %w", bw.Err)
}
if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil {
if err := wCtx.SendCommitteeTx(bw.Bytes(), false); err != nil {
return err
}
return wCtx.awaitTx()
return wCtx.AwaitTx()
}
func parseGASAmount(s string) (fixedn.Fixed8, error) {

View File

@ -7,6 +7,7 @@ import (
"path/filepath"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config"
util2 "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/util"
@ -75,8 +76,8 @@ func openContractWallet(v *viper.Viper, cmd *cobra.Command, walletDir string) (*
return w, nil
}
func (c *initializeContext) addManifestGroup(h util.Uint160, cs *contractState) error {
priv := c.ContractWallet.Accounts[0].PrivateKey()
func addManifestGroup(cw *wallet.Wallet, h util.Uint160, cs *util2.ContractState) error {
priv := cw.Accounts[0].PrivateKey()
pub := priv.PublicKey()
sig := priv.Sign(h.BytesBE())

View File

@ -20,14 +20,14 @@ import (
"github.com/spf13/viper"
)
type cache struct {
nnsCs *state.Contract
groupKey *keys.PublicKey
type Cache struct {
NNSCs *state.Contract
GroupKey *keys.PublicKey
}
type initializeContext struct {
type InitializeContext struct {
morphUtil.ClientContext
cache
Cache
// CommitteeAcc is used for retrieving the committee address and the verification script.
CommitteeAcc *wallet.Account
// ConsensusAcc is used for retrieving the committee address and the verification script.
@ -37,62 +37,62 @@ type initializeContext struct {
ContractWallet *wallet.Wallet
// Accounts contains simple signature accounts in the same order as in Wallets.
Accounts []*wallet.Account
Contracts map[string]*contractState
Contracts map[string]*morphUtil.ContractState
Command *cobra.Command
ContractPath string
ContractURL string
}
func initializeSideChainCmd(cmd *cobra.Command, _ []string) error {
initCtx, err := newInitializeContext(cmd, viper.GetViper())
initCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil {
return fmt.Errorf("initialization error: %w", err)
}
defer initCtx.close()
defer initCtx.Close()
// 1. Transfer funds to committee accounts.
cmd.Println("Stage 1: transfer GAS to alphabet nodes.")
if err := initCtx.transferFunds(); err != nil {
if err := transferFunds(initCtx); err != nil {
return err
}
cmd.Println("Stage 2: set notary and alphabet nodes in designate contract.")
if err := initCtx.setNotaryAndAlphabetNodes(); err != nil {
if err := setNotaryAndAlphabetNodes(initCtx); err != nil {
return err
}
// 3. Deploy NNS contract.
cmd.Println("Stage 3: deploy NNS contract.")
if err := initCtx.deployNNS(deployMethodName); err != nil {
if err := deployNNS(initCtx, deployMethodName); err != nil {
return err
}
// 4. Deploy NeoFS contracts.
cmd.Println("Stage 4: deploy NeoFS contracts.")
if err := initCtx.deployContracts(); err != nil {
if err := deployContracts(initCtx); err != nil {
return err
}
cmd.Println("Stage 4.1: Transfer GAS to proxy contract.")
if err := initCtx.transferGASToProxy(); err != nil {
if err := transferGASToProxy(initCtx); err != nil {
return err
}
cmd.Println("Stage 5: register candidates.")
if err := initCtx.registerCandidates(); err != nil {
if err := registerCandidates(initCtx); err != nil {
return err
}
cmd.Println("Stage 6: transfer NEO to alphabet contracts.")
if err := initCtx.transferNEOToAlphabetContracts(); err != nil {
if err := transferNEOToAlphabetContracts(initCtx); err != nil {
return err
}
cmd.Println("Stage 7: set addresses in NNS.")
return initCtx.setNNS()
return setNNS(initCtx)
}
func (c *initializeContext) close() {
func (c *InitializeContext) Close() {
if local, ok := c.Client.(*morphUtil.LocalClient); ok {
err := local.Dump()
if err != nil {
@ -102,7 +102,7 @@ func (c *initializeContext) close() {
}
}
func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContext, error) {
func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContext, error) {
walletDir := config.ResolveHomePath(viper.GetString(morphUtil.AlphabetWalletsFlag))
wallets, err := morphUtil.GetAlphabetWallets(v, walletDir)
if err != nil {
@ -160,7 +160,7 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
return nil, fmt.Errorf("client context: %w", err)
}
initCtx := &initializeContext{
initCtx := &InitializeContext{
ClientContext: *cliCtx,
ConsensusAcc: consensusAcc,
CommitteeAcc: committeeAcc,
@ -168,7 +168,7 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
Wallets: wallets,
Accounts: accounts,
Command: cmd,
Contracts: make(map[string]*contractState),
Contracts: make(map[string]*morphUtil.ContractState),
ContractPath: ctrPath,
ContractURL: ctrURL,
}
@ -246,13 +246,13 @@ func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) {
return accounts, nil
}
func (c *initializeContext) awaitTx() error {
func (c *InitializeContext) AwaitTx() error {
return c.ClientContext.AwaitTx(c.Command)
}
func (c *initializeContext) nnsContractState() (*state.Contract, error) {
if c.nnsCs != nil {
return c.nnsCs, nil
func (c *InitializeContext) NNSContractState() (*state.Contract, error) {
if c.NNSCs != nil {
return c.NNSCs, nil
}
r := management.NewReader(c.ReadOnlyInvoker)
@ -261,16 +261,16 @@ func (c *initializeContext) nnsContractState() (*state.Contract, error) {
return nil, err
}
c.nnsCs = cs
c.NNSCs = cs
return cs, nil
}
func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transaction.Signer {
if tryGroup && c.groupKey != nil {
func (c *InitializeContext) GetSigner(tryGroup bool, acc *wallet.Account) transaction.Signer {
if tryGroup && c.GroupKey != nil {
return transaction.Signer{
Account: acc.Contract.ScriptHash(),
Scopes: transaction.CustomGroups,
AllowedGroups: keys.PublicKeys{c.groupKey},
AllowedGroups: keys.PublicKeys{c.GroupKey},
}
}
@ -283,14 +283,14 @@ func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transa
return signer
}
nnsCs, err := c.nnsContractState()
nnsCs, err := c.NNSContractState()
if err != nil {
return signer
}
groupKey, err := nnsResolveKey(c.ReadOnlyInvoker, nnsCs.Hash, morphClient.NNSGroupKeyName)
groupKey, err := morphUtil.NNSResolveKey(c.ReadOnlyInvoker, nnsCs.Hash, morphClient.NNSGroupKeyName)
if err == nil {
c.groupKey = groupKey
c.GroupKey = groupKey
signer.Scopes = transaction.CustomGroups
signer.AllowedGroups = keys.PublicKeys{groupKey}
@ -298,21 +298,21 @@ func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transa
return signer
}
// sendCommitteeTx creates transaction from script, signs it by committee nodes and sends it to RPC.
// SendCommitteeTx creates transaction from script, signs it by committee nodes and sends it to RPC.
// If tryGroup is false, global scope is used for the signer (useful when
// working with native contracts).
func (c *initializeContext) sendCommitteeTx(script []byte, tryGroup bool) error {
func (c *InitializeContext) SendCommitteeTx(script []byte, tryGroup bool) error {
return c.sendMultiTx(script, tryGroup, false)
}
// sendConsensusTx creates transaction from script, signs it by alphabet nodes and sends it to RPC.
// SendConsensusTx creates transaction from script, signs it by alphabet nodes and sends it to RPC.
// Not that because this is used only after the contracts were initialized and deployed,
// we always try to have a group scope.
func (c *initializeContext) sendConsensusTx(script []byte) error {
func (c *InitializeContext) SendConsensusTx(script []byte) error {
return c.sendMultiTx(script, true, true)
}
func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsensus bool) error {
func (c *InitializeContext) sendMultiTx(script []byte, tryGroup bool, withConsensus bool) error {
var act *actor.Actor
var err error
@ -321,12 +321,12 @@ func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsen
// Even for consensus signatures we need the committee to pay.
signers := make([]actor.SignerAccount, 1, 2)
signers[0] = actor.SignerAccount{
Signer: c.getSigner(tryGroup, c.CommitteeAcc),
Signer: c.GetSigner(tryGroup, c.CommitteeAcc),
Account: c.CommitteeAcc,
}
if withConsensus {
signers = append(signers, actor.SignerAccount{
Signer: c.getSigner(tryGroup, c.ConsensusAcc),
Signer: c.GetSigner(tryGroup, c.ConsensusAcc),
Account: c.ConsensusAcc,
})
}
@ -346,11 +346,11 @@ func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsen
return fmt.Errorf("could not perform test invocation: %w", err)
}
if err := c.multiSign(tx, morphUtil.CommitteeAccountName); err != nil {
if err := c.MultiSign(tx, morphUtil.CommitteeAccountName); err != nil {
return err
}
if withConsensus {
if err := c.multiSign(tx, morphUtil.ConsensusAccountName); err != nil {
if err := c.MultiSign(tx, morphUtil.ConsensusAccountName); err != nil {
return err
}
}

View File

@ -4,7 +4,6 @@ import (
"archive/tar"
"compress/gzip"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
@ -22,12 +21,11 @@ import (
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
io2 "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
"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/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
@ -66,24 +64,16 @@ var (
}
)
type contractState struct {
NEF *nef.File
RawNEF []byte
Manifest *manifest.Manifest
RawManifest []byte
Hash util.Uint160
}
const (
updateMethodName = "update"
deployMethodName = "deploy"
)
func (c *initializeContext) deployNNS(method string) error {
cs := c.getContract(morphUtil.NNSContract)
func deployNNS(c *InitializeContext, method string) error {
cs := c.GetContract(morphUtil.NNSContract)
h := cs.Hash
nnsCs, err := c.nnsContractState()
nnsCs, err := c.NNSContractState()
if err != nil {
return err
}
@ -99,7 +89,7 @@ func (c *initializeContext) deployNNS(method string) error {
h = nnsCs.Hash
}
err = c.addManifestGroup(h, cs)
err = addManifestGroup(c.ContractWallet, h, cs)
if err != nil {
return fmt.Errorf("can't sign manifest group: %v", err)
}
@ -116,17 +106,17 @@ func (c *initializeContext) deployNNS(method string) error {
return fmt.Errorf("failed to create deploy tx for %s: %w", morphUtil.NNSContract, err)
}
if err := c.multiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil {
if err := c.MultiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil {
return fmt.Errorf("can't send deploy transaction: %w", err)
}
return c.awaitTx()
return c.AwaitTx()
}
func (c *initializeContext) updateContracts() error {
alphaCs := c.getContract(morphUtil.AlphabetContract)
func updateContractsInternal(c *InitializeContext) error {
alphaCs := c.GetContract(morphUtil.AlphabetContract)
nnsCs, err := c.nnsContractState()
nnsCs, err := c.NNSContractState()
if err != nil {
return err
}
@ -147,19 +137,19 @@ func (c *initializeContext) updateContracts() error {
emit.Bytes(w.BinWriter, alphaCs.RawNEF)
emit.Opcodes(w.BinWriter, opcode.STSFLD0)
keysParam, err := c.deployAlphabetAccounts(nnsHash, w, alphaCs)
keysParam, err := deployAlphabetAccounts(c, nnsHash, w, alphaCs)
if err != nil {
return err
}
w.Reset()
if err = c.deployOrUpdateContracts(w, nnsHash, keysParam); err != nil {
if err = deployOrUpdateContracts(c, w, nnsHash, keysParam); err != nil {
return err
}
groupKey := c.ContractWallet.Accounts[0].PrivateKey().PublicKey()
_, _, err = c.emitUpdateNNSGroupScript(w, nnsHash, groupKey)
_, _, err = c.EmitUpdateNNSGroupScript(w, nnsHash, groupKey)
if err != nil {
return err
}
@ -170,20 +160,20 @@ func (c *initializeContext) updateContracts() error {
emit.Opcodes(w.BinWriter, opcode.PACK)
emit.AppCallNoArgs(w.BinWriter, nnsHash, "setPrice", callflag.All)
if err := c.sendCommitteeTx(w.Bytes(), false); err != nil {
if err := c.SendCommitteeTx(w.Bytes(), false); err != nil {
return err
}
return c.awaitTx()
return c.AwaitTx()
}
func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash util.Uint160, keysParam []any) error {
func deployOrUpdateContracts(c *InitializeContext, w *io2.BufBinWriter, nnsHash util.Uint160, keysParam []any) error {
emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1})
emit.AppCall(w.BinWriter, nnsHash, "getPrice", callflag.All)
emit.Opcodes(w.BinWriter, opcode.STSFLD0)
emit.AppCall(w.BinWriter, nnsHash, "setPrice", callflag.All, 1)
for _, ctrName := range contractList {
cs := c.getContract(ctrName)
cs := c.GetContract(ctrName)
method := updateMethodName
ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.DomainOf(ctrName))
@ -196,7 +186,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash
}
}
err = c.addManifestGroup(ctrHash, cs)
err = addManifestGroup(c.ContractWallet, ctrHash, cs)
if err != nil {
return fmt.Errorf("can't sign manifest group: %v", err)
}
@ -206,7 +196,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash
invokeHash = ctrHash
}
args, err := c.getContractDeployData(ctrName, keysParam, updateMethodName)
args, err := getContractDeployData(c, ctrName, keysParam, updateMethodName)
if err != nil {
return fmt.Errorf("%s: getting update params: %v", ctrName, err)
}
@ -223,9 +213,9 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash
w.WriteBytes(res.Script)
if method == deployMethodName {
// same actions are done in initializeContext.setNNS, can be unified
// same actions are done in InitializeContext.setNNS, can be unified
domain := ctrName + ".frostfs"
script, ok, err := c.nnsRegisterDomainScript(nnsHash, cs.Hash, domain)
script, ok, err := c.NNSRegisterDomainScript(nnsHash, cs.Hash, domain)
if err != nil {
return err
}
@ -243,7 +233,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash
return nil
}
func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2.BufBinWriter, alphaCs *contractState) ([]any, error) {
func deployAlphabetAccounts(c *InitializeContext, nnsHash util.Uint160, w *io2.BufBinWriter, alphaCs *morphUtil.ContractState) ([]any, error) {
var keysParam []any
baseGroups := alphaCs.Manifest.Groups
@ -257,11 +247,11 @@ func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2.
keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes())
params := c.getAlphabetDeployItems(i, len(c.Wallets))
params := c.GetAlphabetDeployItems(i, len(c.Wallets))
emit.Array(w.BinWriter, params...)
alphaCs.Manifest.Groups = baseGroups
err = c.addManifestGroup(ctrHash, alphaCs)
err = addManifestGroup(c.ContractWallet, ctrHash, alphaCs)
if err != nil {
return nil, fmt.Errorf("can't sign manifest group: %v", err)
}
@ -272,7 +262,7 @@ func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2.
emit.Opcodes(w.BinWriter, opcode.PACK)
emit.AppCallNoArgs(w.BinWriter, ctrHash, updateMethodName, callflag.All)
}
if err := c.sendCommitteeTx(w.Bytes(), false); err != nil {
if err := c.SendCommitteeTx(w.Bytes(), false); err != nil {
if !strings.Contains(err.Error(), common.ErrAlreadyUpdated) {
return nil, err
}
@ -282,8 +272,8 @@ func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2.
return keysParam, nil
}
func (c *initializeContext) deployContracts() error {
alphaCs := c.getContract(morphUtil.AlphabetContract)
func deployContracts(c *InitializeContext) error {
alphaCs := c.GetContract(morphUtil.AlphabetContract)
var keysParam []any
@ -292,19 +282,19 @@ func (c *initializeContext) deployContracts() error {
// alphabet contracts should be deployed by individual nodes to get different hashes.
for i, acc := range c.Accounts {
ctrHash := state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name)
if c.isUpdated(ctrHash, alphaCs) {
if c.IsUpdated(ctrHash, alphaCs) {
c.Command.Printf("Alphabet contract #%d is already deployed.\n", i)
continue
}
alphaCs.Manifest.Groups = baseGroups
err := c.addManifestGroup(ctrHash, alphaCs)
err := addManifestGroup(c.ContractWallet, ctrHash, alphaCs)
if err != nil {
return fmt.Errorf("can't sign manifest group: %v", err)
}
keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes())
params := getContractDeployParameters(alphaCs, c.getAlphabetDeployItems(i, len(c.Wallets)))
params := getContractDeployParameters(alphaCs, c.GetAlphabetDeployItems(i, len(c.Wallets)))
act, err := actor.NewSimple(c.Client, acc)
if err != nil {
@ -320,20 +310,20 @@ func (c *initializeContext) deployContracts() error {
}
for _, ctrName := range contractList {
cs := c.getContract(ctrName)
cs := c.GetContract(ctrName)
ctrHash := cs.Hash
if c.isUpdated(ctrHash, cs) {
if c.IsUpdated(ctrHash, cs) {
c.Command.Printf("%s contract is already deployed.\n", ctrName)
continue
}
err := c.addManifestGroup(ctrHash, cs)
err := addManifestGroup(c.ContractWallet, ctrHash, cs)
if err != nil {
return fmt.Errorf("can't sign manifest group: %v", err)
}
args, err := c.getContractDeployData(ctrName, keysParam, deployMethodName)
args, err := getContractDeployData(c, ctrName, keysParam, deployMethodName)
if err != nil {
return fmt.Errorf("%s: getting deploy params: %v", ctrName, err)
}
@ -343,25 +333,25 @@ func (c *initializeContext) deployContracts() error {
return fmt.Errorf("can't deploy %s contract: %w", ctrName, err)
}
if err := c.sendCommitteeTx(res.Script, false); err != nil {
if err := c.SendCommitteeTx(res.Script, false); err != nil {
return err
}
}
return c.awaitTx()
return c.AwaitTx()
}
func (c *initializeContext) isUpdated(ctrHash util.Uint160, cs *contractState) bool {
func (c *InitializeContext) IsUpdated(ctrHash util.Uint160, cs *morphUtil.ContractState) bool {
r := management.NewReader(c.ReadOnlyInvoker)
realCs, err := r.GetContract(ctrHash)
return err == nil && realCs != nil && realCs.NEF.Checksum == cs.NEF.Checksum
}
func (c *initializeContext) getContract(ctrName string) *contractState {
func (c *InitializeContext) GetContract(ctrName string) *morphUtil.ContractState {
return c.Contracts[ctrName]
}
func (c *initializeContext) readContracts(names []string) error {
func (c *InitializeContext) readContracts(names []string) error {
var (
fi os.FileInfo
err error
@ -401,7 +391,7 @@ func (c *initializeContext) readContracts(names []string) error {
return err
}
for _, name := range names {
if err := m[name].parse(); err != nil {
if err := m[name].Parse(); err != nil {
return err
}
c.Contracts[name] = m[name]
@ -418,7 +408,7 @@ func (c *initializeContext) readContracts(names []string) error {
return nil
}
func readContract(ctrPath, ctrName string) (*contractState, error) {
func readContract(ctrPath, ctrName string) (*morphUtil.ContractState, error) {
rawNef, err := os.ReadFile(filepath.Join(ctrPath, ctrName+"_contract.nef"))
if err != nil {
return nil, fmt.Errorf("can't read NEF file for %s contract: %w", ctrName, err)
@ -428,34 +418,18 @@ func readContract(ctrPath, ctrName string) (*contractState, error) {
return nil, fmt.Errorf("can't read manifest file for %s contract: %w", ctrName, err)
}
cs := &contractState{
cs := &morphUtil.ContractState{
RawNEF: rawNef,
RawManifest: rawManif,
}
return cs, cs.parse()
return cs, cs.Parse()
}
func (cs *contractState) parse() error {
nf, err := nef.FileFromBytes(cs.RawNEF)
if err != nil {
return fmt.Errorf("can't parse NEF file: %w", err)
}
m := new(manifest.Manifest)
if err := json.Unmarshal(cs.RawManifest, m); err != nil {
return fmt.Errorf("can't parse manifest file: %w", err)
}
cs.NEF = &nf
cs.Manifest = m
return nil
}
func readContractsFromArchive(file io.Reader, names []string) (map[string]*contractState, error) {
m := make(map[string]*contractState, len(names))
func readContractsFromArchive(file io.Reader, names []string) (map[string]*morphUtil.ContractState, error) {
m := make(map[string]*morphUtil.ContractState, len(names))
for i := range names {
m[names[i]] = new(contractState)
m[names[i]] = new(morphUtil.ContractState)
}
gr, err := gzip.NewReader(file)
@ -503,11 +477,11 @@ func readContractsFromArchive(file io.Reader, names []string) (map[string]*contr
return m, nil
}
func getContractDeployParameters(cs *contractState, deployData []any) []any {
func getContractDeployParameters(cs *morphUtil.ContractState, deployData []any) []any {
return []any{cs.RawNEF, cs.RawManifest, deployData}
}
func (c *initializeContext) getContractDeployData(ctrName string, keysParam []any, method string) ([]any, error) {
func getContractDeployData(c *InitializeContext, ctrName string, keysParam []any, method string) ([]any, error) {
items := make([]any, 0, 6)
switch ctrName {
@ -544,7 +518,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an
err error
)
if method == updateMethodName {
h, found, err = c.getFrostfsIDAdminFromContract()
h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker)
}
if method != updateMethodName || err == nil && !found {
h, found, err = getFrostfsIDAdmin(viper.GetViper())
@ -561,7 +535,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an
case morphUtil.NetmapContract:
md := getDefaultNetmapContractConfigMap()
if method == updateMethodName {
if err := c.mergeNetmapConfig(md); err != nil {
if err := mergeNetmapConfig(c.ReadOnlyInvoker, md); err != nil {
return nil, err
}
}
@ -586,17 +560,17 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an
return items, nil
}
func (c *initializeContext) getFrostfsIDAdminFromContract() (util.Uint160, bool, error) {
r := management.NewReader(c.ReadOnlyInvoker)
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 := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.FrostfsIDContract))
fidHash, err := morphUtil.NNSResolveHash(roInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.FrostfsIDContract))
if err != nil {
return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err)
}
item, err := unwrap.Item(c.ReadOnlyInvoker.Call(fidHash, "getAdmin"))
item, err := unwrap.Item(roInvoker.Call(fidHash, "getAdmin"))
if err != nil {
return util.Uint160{}, false, fmt.Errorf("getAdmin: %w", err)
}
@ -615,25 +589,25 @@ func (c *initializeContext) getFrostfsIDAdminFromContract() (util.Uint160, bool,
return h, true, nil
}
func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, error) {
r := management.NewReader(c.ReadOnlyInvoker)
func getNetConfigFromNetmapContract(roInvoker *invoker.Invoker) ([]stackitem.Item, error) {
r := management.NewReader(roInvoker)
cs, err := r.GetContractByID(1)
if err != nil {
return nil, fmt.Errorf("get nns contract: %w", err)
}
nmHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.NetmapContract))
nmHash, err := morphUtil.NNSResolveHash(roInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.NetmapContract))
if err != nil {
return nil, fmt.Errorf("can't get netmap contract hash: %w", err)
}
arr, err := unwrap.Array(c.ReadOnlyInvoker.Call(nmHash, "listConfig"))
arr, err := unwrap.Array(roInvoker.Call(nmHash, "listConfig"))
if err != nil {
return nil, fmt.Errorf("can't fetch list of network config keys from the netmap contract")
}
return arr, err
}
func (c *initializeContext) mergeNetmapConfig(md map[string]any) error {
arr, err := c.getNetConfigFromNetmapContract()
func mergeNetmapConfig(roInvoker *invoker.Invoker, md map[string]any) error {
arr, err := getNetConfigFromNetmapContract(roInvoker)
if err != nil {
return err
}
@ -652,7 +626,7 @@ func (c *initializeContext) mergeNetmapConfig(md map[string]any) error {
return nil
}
func (c *initializeContext) getAlphabetDeployItems(i, n int) []any {
func (c *InitializeContext) GetAlphabetDeployItems(i, n int) []any {
items := make([]any, 5)
items[0] = c.Contracts[morphUtil.NetmapContract].Hash
items[1] = c.Contracts[morphUtil.ProxyContract].Hash

View File

@ -14,16 +14,11 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
nnsClient "github.com/nspcc-dev/neo-go/pkg/rpcclient/nns"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
)
@ -31,14 +26,14 @@ const defaultExpirationTime = 10 * 365 * 24 * time.Hour / time.Second
const frostfsOpsEmail = "ops@frostfs.info"
func (c *initializeContext) setNNS() error {
func setNNS(c *InitializeContext) error {
r := management.NewReader(c.ReadOnlyInvoker)
nnsCs, err := r.GetContractByID(1)
if err != nil {
return err
}
ok, err := c.nnsRootRegistered(nnsCs.Hash, "frostfs")
ok, err := c.NNSRootRegistered(nnsCs.Hash, "frostfs")
if err != nil {
return err
} else if !ok {
@ -47,48 +42,48 @@ func (c *initializeContext) setNNS() error {
"frostfs", c.CommitteeAcc.Contract.ScriptHash(),
frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600))
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
if err := c.sendCommitteeTx(bw.Bytes(), true); err != nil {
if err := c.SendCommitteeTx(bw.Bytes(), true); err != nil {
return fmt.Errorf("can't add domain root to NNS: %w", err)
}
if err := c.awaitTx(); err != nil {
if err := c.AwaitTx(); err != nil {
return err
}
}
alphaCs := c.getContract(morphUtil.AlphabetContract)
alphaCs := c.GetContract(morphUtil.AlphabetContract)
for i, acc := range c.Accounts {
alphaCs.Hash = state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name)
domain := getAlphabetNNSDomain(i)
if err := c.nnsRegisterDomain(nnsCs.Hash, alphaCs.Hash, domain); err != nil {
if err := nnsRegisterDomain(c, nnsCs.Hash, alphaCs.Hash, domain); err != nil {
return err
}
c.Command.Printf("NNS: Set %s -> %s\n", domain, alphaCs.Hash.StringLE())
}
for _, ctrName := range contractList {
cs := c.getContract(ctrName)
cs := c.GetContract(ctrName)
domain := ctrName + ".frostfs"
if err := c.nnsRegisterDomain(nnsCs.Hash, cs.Hash, domain); err != nil {
if err := nnsRegisterDomain(c, nnsCs.Hash, cs.Hash, domain); err != nil {
return err
}
c.Command.Printf("NNS: Set %s -> %s\n", domain, cs.Hash.StringLE())
}
groupKey := c.ContractWallet.Accounts[0].PrivateKey().PublicKey()
err = c.updateNNSGroup(nnsCs.Hash, groupKey)
err = updateNNSGroup(c, nnsCs.Hash, groupKey)
if err != nil {
return err
}
c.Command.Printf("NNS: Set %s -> %s\n", morphClient.NNSGroupKeyName, hex.EncodeToString(groupKey.Bytes()))
return c.awaitTx()
return c.AwaitTx()
}
func (c *initializeContext) updateNNSGroup(nnsHash util.Uint160, pub *keys.PublicKey) error {
func updateNNSGroup(c *InitializeContext, nnsHash util.Uint160, pub *keys.PublicKey) error {
bw := io.NewBufBinWriter()
keyAlreadyAdded, domainRegCodeEmitted, err := c.emitUpdateNNSGroupScript(bw, nnsHash, pub)
keyAlreadyAdded, domainRegCodeEmitted, err := c.EmitUpdateNNSGroupScript(bw, nnsHash, pub)
if keyAlreadyAdded || err != nil {
return err
}
@ -101,20 +96,20 @@ func (c *initializeContext) updateNNSGroup(nnsHash util.Uint160, pub *keys.Publi
script = w.Bytes()
}
return c.sendCommitteeTx(script, true)
return c.SendCommitteeTx(script, true)
}
// emitUpdateNNSGroupScript emits script for updating group key stored in NNS.
// EmitUpdateNNSGroupScript emits script for updating group key stored in NNS.
// First return value is true iff the key is already there and nothing should be done.
// Second return value is true iff a domain registration code was emitted.
func (c *initializeContext) emitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHash util.Uint160, pub *keys.PublicKey) (bool, bool, error) {
isAvail, err := nnsIsAvailable(c.Client, nnsHash, morphClient.NNSGroupKeyName)
func (c *InitializeContext) EmitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHash util.Uint160, pub *keys.PublicKey) (bool, bool, error) {
isAvail, err := morphUtil.NNSIsAvailable(c.Client, nnsHash, morphClient.NNSGroupKeyName)
if err != nil {
return false, false, err
}
if !isAvail {
currentPub, err := nnsResolveKey(c.ReadOnlyInvoker, nnsHash, morphClient.NNSGroupKeyName)
currentPub, err := morphUtil.NNSResolveKey(c.ReadOnlyInvoker, nnsHash, morphClient.NNSGroupKeyName)
if err != nil {
return false, false, err
}
@ -165,8 +160,8 @@ func wrapRegisterScriptWithPrice(w *io.BufBinWriter, nnsHash util.Uint160, s []b
}
}
func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.Uint160, domain string) ([]byte, bool, error) {
ok, err := nnsIsAvailable(c.Client, nnsHash, domain)
func (c *InitializeContext) NNSRegisterDomainScript(nnsHash, expectedHash util.Uint160, domain string) ([]byte, bool, error) {
ok, err := morphUtil.NNSIsAvailable(c.Client, nnsHash, domain)
if err != nil {
return nil, false, err
}
@ -191,8 +186,8 @@ func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.U
return nil, s == expectedHash, nil
}
func (c *initializeContext) nnsRegisterDomain(nnsHash, expectedHash util.Uint160, domain string) error {
script, ok, err := c.nnsRegisterDomainScript(nnsHash, expectedHash, domain)
func nnsRegisterDomain(c *InitializeContext, nnsHash, expectedHash util.Uint160, domain string) error {
script, ok, err := c.NNSRegisterDomainScript(nnsHash, expectedHash, domain)
if ok || err != nil {
return err
}
@ -206,10 +201,10 @@ func (c *initializeContext) nnsRegisterDomain(nnsHash, expectedHash util.Uint160
domain, int64(nns.TXT), expectedHash.StringLE())
emit.AppCall(w.BinWriter, nnsHash, "addRecord", callflag.All,
domain, int64(nns.TXT), address.Uint160ToString(expectedHash))
return c.sendCommitteeTx(w.Bytes(), true)
return c.SendCommitteeTx(w.Bytes(), true)
}
func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160, zone string) (bool, error) {
func (c *InitializeContext) NNSRootRegistered(nnsHash util.Uint160, zone string) (bool, error) {
res, err := c.CommitteeAct.Call(nnsHash, "isAvailable", "name."+zone)
if err != nil {
return false, err
@ -219,43 +214,3 @@ func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160, zone string)
}
var errMissingNNSRecord = errors.New("missing NNS record")
func nnsResolveKey(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (*keys.PublicKey, error) {
res, err := morphUtil.NNSResolve(inv, nnsHash, domain)
if err != nil {
return nil, err
}
if _, ok := res.Value().(stackitem.Null); ok {
return nil, errors.New("NNS record is missing")
}
arr, ok := res.Value().([]stackitem.Item)
if !ok {
return nil, errors.New("API of the NNS contract method `resolve` has changed")
}
for i := range arr {
var bs []byte
bs, err = arr[i].TryBytes()
if err != nil {
continue
}
return keys.NewPublicKeyFromString(string(bs))
}
return nil, errors.New("no valid keys are found")
}
func nnsIsAvailable(c morphUtil.Client, nnsHash util.Uint160, name string) (bool, error) {
switch c.(type) {
case *rpcclient.Client:
inv := invoker.New(c, nil)
reader := nnsClient.NewReader(inv, nnsHash)
return reader.IsAvailable(name)
default:
b, err := unwrap.Bool(morphUtil.InvokeFunction(c, nnsHash, "isAvailable", []any{name}, nil))
if err != nil {
return false, fmt.Errorf("`isAvailable`: invalid response: %w", err)
}
return b, nil
}
}

View File

@ -28,8 +28,8 @@ const (
registerBatchSize = transaction.MaxAttributes - 1
)
func (c *initializeContext) registerCandidateRange(start, end int) error {
regPrice, err := c.getCandidateRegisterPrice()
func registerCandidateRange(c *InitializeContext, start, end int) error {
regPrice, err := getCandidateRegisterPrice(c)
if err != nil {
return fmt.Errorf("can't fetch registration price: %w", err)
}
@ -46,7 +46,7 @@ func (c *initializeContext) registerCandidateRange(start, end int) error {
}
signers := []actor.SignerAccount{{
Signer: c.getSigner(false, c.CommitteeAcc),
Signer: c.GetSigner(false, c.CommitteeAcc),
Account: c.CommitteeAcc,
}}
for _, acc := range c.Accounts[start:end] {
@ -68,7 +68,7 @@ func (c *initializeContext) registerCandidateRange(start, end int) error {
if err != nil {
return fmt.Errorf("can't create tx: %w", err)
}
if err := c.multiSign(tx, morphUtil.CommitteeAccountName); err != nil {
if err := c.MultiSign(tx, morphUtil.CommitteeAccountName); err != nil {
return fmt.Errorf("can't sign a transaction: %w", err)
}
@ -82,7 +82,7 @@ func (c *initializeContext) registerCandidateRange(start, end int) error {
return c.SendTx(tx, c.Command, true)
}
func (c *initializeContext) registerCandidates() error {
func registerCandidates(c *InitializeContext) error {
cc, err := unwrap.Array(c.ReadOnlyInvoker.Call(neo.Hash, "getCandidates"))
if err != nil {
return fmt.Errorf("`getCandidates`: %w", err)
@ -107,7 +107,7 @@ func (c *initializeContext) registerCandidates() error {
if have >= end {
continue
}
if err := c.registerCandidateRange(start, end); err != nil {
if err := registerCandidateRange(c, start, end); err != nil {
return fmt.Errorf("registering candidates %d..%d: %q", start, end-1, err)
}
}
@ -115,15 +115,15 @@ func (c *initializeContext) registerCandidates() error {
return nil
}
func (c *initializeContext) transferNEOToAlphabetContracts() error {
func transferNEOToAlphabetContracts(c *InitializeContext) error {
neoHash := neo.Hash
ok, err := c.transferNEOFinished(neoHash)
ok, err := transferNEOFinished(c, neoHash)
if ok || err != nil {
return err
}
cs := c.getContract(morphUtil.AlphabetContract)
cs := c.GetContract(morphUtil.AlphabetContract)
amount := initialAlphabetNEOAmount / len(c.Wallets)
bw := io.NewBufBinWriter()
@ -134,14 +134,14 @@ func (c *initializeContext) transferNEOToAlphabetContracts() error {
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
}
if err := c.sendCommitteeTx(bw.Bytes(), false); err != nil {
if err := c.SendCommitteeTx(bw.Bytes(), false); err != nil {
return err
}
return c.awaitTx()
return c.AwaitTx()
}
func (c *initializeContext) transferNEOFinished(neoHash util.Uint160) (bool, error) {
func transferNEOFinished(c *InitializeContext, neoHash util.Uint160) (bool, error) {
r := nep17.NewReader(c.ReadOnlyInvoker, neoHash)
bal, err := r.BalanceOf(c.CommitteeAcc.Contract.ScriptHash())
return bal.Cmp(big.NewInt(native.NEOTotalSupply)) == -1, err
@ -149,7 +149,7 @@ func (c *initializeContext) transferNEOFinished(neoHash util.Uint160) (bool, err
var errGetPriceInvalid = errors.New("`getRegisterPrice`: invalid response")
func (c *initializeContext) getCandidateRegisterPrice() (int64, error) {
func getCandidateRegisterPrice(c *InitializeContext) (int64, error) {
switch c.Client.(type) {
case *rpcclient.Client:
inv := invoker.New(c.Client, nil)

View File

@ -9,8 +9,8 @@ import (
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
)
func (c *initializeContext) setNotaryAndAlphabetNodes() error {
if ok, err := c.setRolesFinished(); ok || err != nil {
func setNotaryAndAlphabetNodes(c *InitializeContext) error {
if ok, err := setRolesFinished(c); ok || err != nil {
if err == nil {
c.Command.Println("Stage 2: already performed.")
}
@ -28,14 +28,14 @@ func (c *initializeContext) setNotaryAndAlphabetNodes() error {
emit.AppCall(w.BinWriter, rolemgmt.Hash, "designateAsRole",
callflag.States|callflag.AllowNotify, int64(noderoles.NeoFSAlphabet), pubs)
if err := c.sendCommitteeTx(w.Bytes(), false); err != nil {
if err := c.SendCommitteeTx(w.Bytes(), false); err != nil {
return err
}
return c.awaitTx()
return c.AwaitTx()
}
func (c *initializeContext) setRolesFinished() (bool, error) {
func setRolesFinished(c *InitializeContext) (bool, error) {
height, err := c.Client.GetBlockCount()
if err != nil {
return false, err

View File

@ -28,8 +28,8 @@ const (
initialProxyGASAmount = 50_000 * native.GASFactor
)
func (c *initializeContext) transferFunds() error {
ok, err := c.transferFundsFinished()
func transferFunds(c *InitializeContext) error {
ok, err := transferFundsFinished(c)
if ok || err != nil {
if err == nil {
c.Command.Println("Stage 1: already performed.")
@ -68,14 +68,14 @@ func (c *initializeContext) transferFunds() error {
return fmt.Errorf("can't create transfer transaction: %w", err)
}
if err := c.multiSignAndSend(tx, morphUtil.ConsensusAccountName); err != nil {
if err := c.MultiSignAndSend(tx, morphUtil.ConsensusAccountName); err != nil {
return fmt.Errorf("can't send transfer transaction: %w", err)
}
return c.awaitTx()
return c.AwaitTx()
}
func (c *initializeContext) transferFundsFinished() (bool, error) {
func transferFundsFinished(c *InitializeContext) (bool, error) {
acc := c.Accounts[0]
r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash)
@ -83,15 +83,15 @@ func (c *initializeContext) transferFundsFinished() (bool, error) {
return res.Cmp(big.NewInt(initialAlphabetGASAmount/2)) == 1, err
}
func (c *initializeContext) multiSignAndSend(tx *transaction.Transaction, accType string) error {
if err := c.multiSign(tx, accType); err != nil {
func (c *InitializeContext) MultiSignAndSend(tx *transaction.Transaction, accType string) error {
if err := c.MultiSign(tx, accType); err != nil {
return err
}
return c.SendTx(tx, c.Command, false)
}
func (c *initializeContext) multiSign(tx *transaction.Transaction, accType string) error {
func (c *InitializeContext) MultiSign(tx *transaction.Transaction, accType string) error {
version, err := c.Client.GetVersion()
if err != nil {
// error appears only if client
@ -143,8 +143,8 @@ func (c *initializeContext) multiSign(tx *transaction.Transaction, accType strin
return fmt.Errorf("%s account was not found among transaction signers", accType)
}
func (c *initializeContext) transferGASToProxy() error {
proxyCs := c.getContract(morphUtil.ProxyContract)
func transferGASToProxy(c *InitializeContext) error {
proxyCs := c.GetContract(morphUtil.ProxyContract)
r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash)
bal, err := r.BalanceOf(proxyCs.Hash)
@ -161,11 +161,11 @@ func (c *initializeContext) transferGASToProxy() error {
return err
}
if err := c.multiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil {
if err := c.MultiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil {
return err
}
return c.awaitTx()
return c.AwaitTx()
}
type transferTarget struct {

View File

@ -25,7 +25,7 @@ const (
)
func setPolicyCmd(cmd *cobra.Command, args []string) error {
wCtx, err := newInitializeContext(cmd, viper.GetViper())
wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil {
return fmt.Errorf("can't to initialize context: %w", err)
}
@ -51,11 +51,11 @@ func setPolicyCmd(cmd *cobra.Command, args []string) error {
emit.AppCall(bw.BinWriter, policy.Hash, "set"+k, callflag.All, int64(value))
}
if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil {
if err := wCtx.SendCommitteeTx(bw.Bytes(), false); err != nil {
return err
}
return wCtx.awaitTx()
return wCtx.AwaitTx()
}
func dumpPolicyCmd(cmd *cobra.Command, _ []string) error {

View File

@ -36,7 +36,7 @@ func removeProxyAccount(cmd *cobra.Command, _ []string) {
}
func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error {
wCtx, err := newInitializeContext(cmd, viper.GetViper())
wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil {
return fmt.Errorf("can't to initialize context: %w", err)
}
@ -55,11 +55,11 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error
bw := io.NewBufBinWriter()
emit.AppCall(bw.BinWriter, proxyHash, method, callflag.All, addr)
if err := wCtx.sendConsensusTx(bw.Bytes()); err != nil {
if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil {
return err
}
if err = wCtx.awaitTx(); err != nil {
if err = wCtx.AwaitTx(); err != nil {
return err
}

View File

@ -29,11 +29,11 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error {
}
}
wCtx, err := newInitializeContext(cmd, viper.GetViper())
wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil {
return fmt.Errorf("can't initialize context: %w", err)
}
defer wCtx.close()
defer wCtx.Close()
r := management.NewReader(wCtx.ReadOnlyInvoker)
cs, err := r.GetContractByID(1)
@ -56,9 +56,9 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error {
return err
}
if err := wCtx.sendConsensusTx(bw.Bytes()); err != nil {
if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil {
return err
}
return wCtx.awaitTx()
return wCtx.AwaitTx()
}

View File

@ -8,14 +8,14 @@ import (
)
func updateContracts(cmd *cobra.Command, _ []string) error {
wCtx, err := newInitializeContext(cmd, viper.GetViper())
wCtx, err := NewInitializeContext(cmd, viper.GetViper())
if err != nil {
return fmt.Errorf("initialization error: %w", err)
}
if err := wCtx.deployNNS(updateMethodName); err != nil {
if err := deployNNS(wCtx, updateMethodName); err != nil {
return err
}
return wCtx.updateContracts()
return updateContractsInternal(wCtx)
}

View File

@ -7,8 +7,11 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
nns2 "github.com/nspcc-dev/neo-go/pkg/rpcclient/nns"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util"
@ -144,3 +147,43 @@ func NNSResolveHash(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (
func DomainOf(contract string) string {
return contract + ".frostfs"
}
func NNSResolveKey(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (*keys.PublicKey, error) {
res, err := NNSResolve(inv, nnsHash, domain)
if err != nil {
return nil, err
}
if _, ok := res.Value().(stackitem.Null); ok {
return nil, errors.New("NNS record is missing")
}
arr, ok := res.Value().([]stackitem.Item)
if !ok {
return nil, errors.New("API of the NNS contract method `resolve` has changed")
}
for i := range arr {
var bs []byte
bs, err = arr[i].TryBytes()
if err != nil {
continue
}
return keys.NewPublicKeyFromString(string(bs))
}
return nil, errors.New("no valid keys are found")
}
func NNSIsAvailable(c Client, nnsHash util.Uint160, name string) (bool, error) {
switch c.(type) {
case *rpcclient.Client:
inv := invoker.New(c, nil)
reader := nns2.NewReader(inv, nnsHash)
return reader.IsAvailable(name)
default:
b, err := unwrap.Bool(InvokeFunction(c, nnsHash, "isAvailable", []any{name}, nil))
if err != nil {
return false, fmt.Errorf("`isAvailable`: invalid response: %w", err)
}
return b, nil
}
}

View File

@ -0,0 +1,34 @@
package util
import (
"encoding/json"
"fmt"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
"github.com/nspcc-dev/neo-go/pkg/util"
)
func (cs *ContractState) Parse() error {
nf, err := nef.FileFromBytes(cs.RawNEF)
if err != nil {
return fmt.Errorf("can't parse NEF file: %w", err)
}
m := new(manifest.Manifest)
if err := json.Unmarshal(cs.RawManifest, m); err != nil {
return fmt.Errorf("can't parse manifest file: %w", err)
}
cs.NEF = &nf
cs.Manifest = m
return nil
}
type ContractState struct {
NEF *nef.File
RawNEF []byte
Manifest *manifest.Manifest
RawManifest []byte
Hash util.Uint160
}