[#749] neofs-adm: include neofs contracts in a group

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2021-11-29 15:33:46 +03:00 committed by Alex Vanin
parent e03cb91b64
commit b416285eb0
3 changed files with 112 additions and 12 deletions

View file

@ -0,0 +1,73 @@
package morph
import (
"encoding/json"
"fmt"
"path"
"github.com/nspcc-dev/neo-go/cli/input"
"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"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/spf13/viper"
)
const contractWalletName = "contract.json"
func openContractWallet(walletDir string) (*wallet.Wallet, error) {
p := path.Join(walletDir, contractWalletName)
w, err := wallet.NewWalletFromFile(p)
if err != nil {
return nil, fmt.Errorf("can't open wallet: %w", err)
}
var password string
if key := "credentials.contract"; viper.IsSet(key) {
password = viper.GetString(key)
} else {
prompt := "Password for contract wallet > "
password, err = input.ReadPassword(prompt)
if err != nil {
return nil, fmt.Errorf("can't fetch password: %w", err)
}
}
for i := range w.Accounts {
if err := w.Accounts[i].Decrypt(password, keys.NEP2ScryptParams()); err != nil {
return nil, fmt.Errorf("can't unlock wallet: %w", err)
}
}
return w, nil
}
func (c *initializeContext) addManifestGroup(h util.Uint160, cs *contractState) error {
priv := c.ContractWallet.Accounts[0].PrivateKey()
pub := priv.PublicKey()
sig := priv.Sign(h.BytesBE())
found := false
for i := range cs.Manifest.Groups {
if cs.Manifest.Groups[i].PublicKey.Equal(pub) {
cs.Manifest.Groups[i].Signature = sig
found = true
break
}
}
if !found {
cs.Manifest.Groups = append(cs.Manifest.Groups, manifest.Group{
PublicKey: pub,
Signature: sig,
})
}
data, err := json.Marshal(cs.Manifest)
if err != nil {
return err
}
cs.RawManifest = data
return nil
}

View file

@ -28,6 +28,8 @@ type initializeContext struct {
// ConsensusAcc is used for retrieving committee address and verification script. // ConsensusAcc is used for retrieving committee address and verification script.
ConsensusAcc *wallet.Account ConsensusAcc *wallet.Account
Wallets []*wallet.Wallet Wallets []*wallet.Wallet
// ContractWallet is a wallet for providing contract group signature.
ContractWallet *wallet.Wallet
// Accounts contains simple signature accounts in the same order as in Wallets. // Accounts contains simple signature accounts in the same order as in Wallets.
Accounts []*wallet.Account Accounts []*wallet.Account
Contracts map[string]*contractState Contracts map[string]*contractState
@ -95,6 +97,11 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
return nil, err return nil, err
} }
w, err := openContractWallet(walletDir)
if err != nil {
return nil, err
}
c, err := getN3Client(v) c, err := getN3Client(v)
if err != nil { if err != nil {
return nil, fmt.Errorf("can't create N3 client: %w", err) return nil, fmt.Errorf("can't create N3 client: %w", err)
@ -144,15 +151,16 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
} }
initCtx := &initializeContext{ initCtx := &initializeContext{
clientContext: *defaultClientContext(c), clientContext: *defaultClientContext(c),
ConsensusAcc: consensusAcc, ConsensusAcc: consensusAcc,
CommitteeAcc: committeeAcc, CommitteeAcc: committeeAcc,
Wallets: wallets, ContractWallet: w,
Accounts: accounts, Wallets: wallets,
Command: cmd, Accounts: accounts,
Contracts: make(map[string]*contractState), Command: cmd,
ContractPath: ctrPath, Contracts: make(map[string]*contractState),
Natives: nativeHashes, ContractPath: ctrPath,
Natives: nativeHashes,
} }
if needContracts { if needContracts {

View file

@ -96,11 +96,20 @@ const (
func (c *initializeContext) deployNNS(method string) error { func (c *initializeContext) deployNNS(method string) error {
cs := c.getContract(nnsContract) cs := c.getContract(nnsContract)
h := cs.Hash
realCs, err := c.Client.GetContractStateByID(1) realCs, err := c.Client.GetContractStateByID(1)
if err == nil && realCs.NEF.Checksum == cs.NEF.Checksum { if err == nil {
c.Command.Println("NNS contract is already deployed.") if realCs.NEF.Checksum == cs.NEF.Checksum {
return nil c.Command.Println("NNS contract is already deployed.")
return nil
}
h = realCs.Hash
}
err = c.addManifestGroup(h, cs)
if err != nil {
return fmt.Errorf("can't sign manifest group: %v", err)
} }
params := getContractDeployParameters(cs.RawNEF, cs.RawManifest, nil) params := getContractDeployParameters(cs.RawNEF, cs.RawManifest, nil)
@ -220,6 +229,11 @@ func (c *initializeContext) updateContracts() error {
} }
} }
err = c.addManifestGroup(ctrHash, alphaCs)
if err != nil {
return fmt.Errorf("can't sign manifest group: %v", err)
}
invokeHash := mgmtHash invokeHash := mgmtHash
if method == updateMethodName { if method == updateMethodName {
invokeHash = ctrHash invokeHash = ctrHash
@ -322,6 +336,11 @@ func (c *initializeContext) deployContracts() error {
continue continue
} }
err := c.addManifestGroup(ctrHash, cs)
if err != nil {
return fmt.Errorf("can't sign manifest group: %v", err)
}
invokeHash := mgmtHash invokeHash := mgmtHash
params := getContractDeployParameters(cs.RawNEF, cs.RawManifest, params := getContractDeployParameters(cs.RawNEF, cs.RawManifest,
c.getContractDeployData(ctrName, keysParam)) c.getContractDeployData(ctrName, keysParam))