Skip to content

Commit

Permalink
sidechain/deploy: Do not register/use a committee contract group
Browse files Browse the repository at this point in the history
Starting from c08e2b5 (#2625), there is
no need to maintain committee group and its private key because
CustomGroups witness scope is no longer used.

Completely purge committee group from NeoFS Sidechain auto-deployment
procedure. As a result, contract manifests are no longer modified.

Closes #2642.

Signed-off-by: Leonard Lyubich <[email protected]>
  • Loading branch information
cthulhu-rider committed Nov 15, 2023
1 parent d98b0ae commit 06dcd7e
Show file tree
Hide file tree
Showing 10 changed files with 21 additions and 749 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Changelog for NeoFS Node
- Transaction witness scope no longer uses CustomGroups relying on more strict Rules now (#2619)
- New optimized SDK version is integrated (#2622)
- IR uses internal LOCODE DB from Go package (#2610)
- Contract group for the committee is no longer registered/used in the Sidechain auto-deployment (#2642)

### Removed
- deprecated `no-precheck` flag of `neofs-cli container set-eacl` (#2496)
Expand Down
77 changes: 0 additions & 77 deletions pkg/innerring/deploy.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package innerring

import (
"encoding/json"
"fmt"
"math"
"sync"

"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap"
"github.com/nspcc-dev/neofs-node/pkg/morph/deploy"
"github.com/nspcc-dev/neofs-node/pkg/util/state"
)

type neoFSSidechain struct {
Expand Down Expand Up @@ -80,76 +76,3 @@ func (x *neoFSSidechain) CurrentState() (deploy.NeoFSState, error) {

return res, nil
}

type sidechainKeyStorage struct {
persistentStorage *state.PersistentStorage
}

func newSidechainKeyStorage(persistentStorage *state.PersistentStorage) *sidechainKeyStorage {
return &sidechainKeyStorage{
persistentStorage: persistentStorage,
}
}

var committeeGroupKey = []byte("committeeGroupKey")

// GetPersistedPrivateKey reads persisted private key from the underlying
// storage. If key is missing, it's randomized and saved first.
func (x *sidechainKeyStorage) GetPersistedPrivateKey() (*keys.PrivateKey, error) {
b, err := x.persistentStorage.Bytes(committeeGroupKey)
if err != nil {
return nil, fmt.Errorf("read persistent storage: %w", err)
}

const password = ""

if b != nil {
var wlt wallet.Wallet

err = json.Unmarshal(b, &wlt)
if err != nil {
return nil, fmt.Errorf("decode persisted NEO wallet from JSON: %w", err)
}

if len(wlt.Accounts) != 1 {
return nil, fmt.Errorf("unexpected number of accounts in the persisted NEO wallet: %d instead of 1", len(wlt.Accounts))
}

err = wlt.Accounts[0].Decrypt(password, keys.NEP2ScryptParams())
if err != nil {
return nil, fmt.Errorf("unlock 1st NEO account of the persisted NEO wallet: %w", err)
}

return wlt.Accounts[0].PrivateKey(), nil
}

acc, err := wallet.NewAccount()
if err != nil {
return nil, fmt.Errorf("generate random NEO account: %w", err)
}

scryptPrm := keys.NEP2ScryptParams()

err = acc.Encrypt(password, scryptPrm)
if err != nil {
return nil, fmt.Errorf("protect NEO account with password: %w", err)
}

wlt := wallet.Wallet{
Version: "1.0", // copy-paste from wallet package
Accounts: []*wallet.Account{acc},
Scrypt: scryptPrm,
}

jWallet, err := json.Marshal(wlt)
if err != nil {
return nil, fmt.Errorf("encode NEO wallet with randomized NEO account into JSON: %w", err)
}

err = x.persistentStorage.SetBytes(committeeGroupKey, jWallet)
if err != nil {
return nil, fmt.Errorf("save generated key in the persistent storage: %w", err)
}

return acc.PrivateKey(), nil
}
66 changes: 0 additions & 66 deletions pkg/innerring/deploy_test.go

This file was deleted.

2 changes: 0 additions & 2 deletions pkg/innerring/innerring.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,14 +460,12 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper, errChan chan<-
log.Info("auto-deployment configured, initializing Sidechain...")

sidechain := newNeoFSSidechain(server.morphClient)
sidechainKeyStorage := newSidechainKeyStorage(server.persistate)

var deployPrm deploy.Prm
deployPrm.Logger = server.log
deployPrm.Blockchain = wsClient
deployPrm.LocalAccount = singleAcc
deployPrm.ValidatorMultiSigAccount = consensusAcc
deployPrm.KeyStorage = sidechainKeyStorage
deployPrm.NeoFS = sidechain

nnsCfg, err := parseNNSConfig(cfg)
Expand Down
8 changes: 2 additions & 6 deletions pkg/morph/deploy/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ import (

// various common methods of the NeoFS contracts.
const (
methodUpdate = "update"
methodVersion = "version"
methodUpdate = "update"
)

// syncNeoFSContractPrm groups parameters of syncNeoFSContract.
Expand All @@ -43,8 +42,7 @@ type syncNeoFSContractPrm struct {
nnsContract util.Uint160
systemEmail string

committee keys.PublicKeys
committeeGroupKey *keys.PrivateKey
committee keys.PublicKeys

// with localAcc signer only
simpleLocalActor *actor.Actor
Expand Down Expand Up @@ -129,8 +127,6 @@ func syncNeoFSContract(ctx context.Context, prm syncNeoFSContractPrm) (util.Uint
ctx, cancel := context.WithCancel(ctx)
defer cancel()

setGroupInManifest(&prm.localManifest, prm.localNEF, prm.committeeGroupKey, prm.localAcc.ScriptHash())

var contractDeployer interface {
Sender() util.Uint160
}
Expand Down
98 changes: 14 additions & 84 deletions pkg/morph/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,6 @@ type Blockchain interface {
Unsubscribe(id string) error
}

// KeyStorage represents storage of the private keys.
type KeyStorage interface {
// GetPersistedPrivateKey returns singleton private key persisted in the
// storage. GetPersistedPrivateKey randomizes the key initially. All subsequent
// successful calls return the same key.
GetPersistedPrivateKey() (*keys.PrivateKey, error)
}

// NeoFSState groups information about NeoFS network state processed by Deploy.
type NeoFSState struct {
// Current NeoFS epoch.
Expand Down Expand Up @@ -157,9 +149,6 @@ type Prm struct {
// participants (must be unlocked).
ValidatorMultiSigAccount *wallet.Account

// Storage for single committee group key.
KeyStorage KeyStorage

// Running NeoFS network for which deployment procedure is performed.
NeoFS NeoFS

Expand Down Expand Up @@ -187,10 +176,9 @@ type Prm struct {
// 1. NNS contract deployment
// 2. launch of a notary service for the committee
// 3. initial GAS distribution between committee members
// 4. committee group initialization
// 5. Alphabet initialization (incl. registration as candidates to validators)
// 6. deployment/update of the NeoFS system contracts
// 7. distribution of all available NEO between the Alphabet contracts
// 4. Alphabet initialization (incl. registration as candidates to validators)
// 5. deployment/update of the NeoFS system contracts
// 6. distribution of all available NEO between the Alphabet contracts
//
// See project documentation for details.
func Deploy(ctx context.Context, prm Prm) error {
Expand Down Expand Up @@ -242,39 +230,20 @@ func Deploy(ctx context.Context, prm Prm) error {
defer monitor.stop()

deployNNSPrm := deployNNSContractPrm{
logger: prm.Logger,
blockchain: prm.Blockchain,
monitor: monitor,
localAcc: prm.LocalAccount,
localNEF: prm.NNS.Common.NEF,
localManifest: prm.NNS.Common.Manifest,
systemEmail: prm.NNS.SystemEmail,
initCommitteeGroupKey: nil, // set below
logger: prm.Logger,
blockchain: prm.Blockchain,
monitor: monitor,
localAcc: prm.LocalAccount,
localNEF: prm.NNS.Common.NEF,
localManifest: prm.NNS.Common.Manifest,
systemEmail: prm.NNS.SystemEmail,
tryDeploy: localAccCommitteeIndex == 0, // see below
}

// if local node is the first committee member (Az) => deploy NNS contract,
// otherwise just wait
if localAccCommitteeIndex == 0 {
// Why such a centralized approach? There is a need to initialize committee
// contract group and share its private key between all committee members (the
// latter is done in the current procedure next). Currently, there is no
// convenient Neo service for this, and we don't want to use anything but
// blockchain, so the key is distributed through domain NNS records. However,
// then the chicken-and-egg problem pops up: committee group must be also set
// for the NNS contract. To set the group, you need to know the contract hash in
// advance, and it is a function from the sender of the deployment transaction.
// Summing up all these statements, we come to the conclusion that the one who
// deploys the contract creates the group key, and he shares it among the other
// members. Technically any committee member could deploy NNS contract, but for
// the sake of simplicity, this is a fixed node. This makes the procedure even
// more centralized, however, in practice, at the start of the network, all
// members are expected to be healthy and active.
//
// Note that manifest can't be changed w/o NEF change, so it's impossible to set
// committee group dynamically right after deployment. See
// https://github.com/nspcc-dev/neofs-contract/issues/340
deployNNSPrm.initCommitteeGroupKey = prm.KeyStorage.GetPersistedPrivateKey
}
// otherwise just wait. This will avoid duplication of contracts. This also
// makes the procedure more centralized, however, in practice, at the start of
// the network, all members are expected to be healthy and active.

prm.Logger.Info("initializing NNS contract on the chain...")

Expand Down Expand Up @@ -333,43 +302,6 @@ func Deploy(ctx context.Context, prm Prm) error {

prm.Logger.Info("initial transfer to the committee successfully done")

prm.Logger.Info("initializing committee group for contract management...")

committeeGroupKey, err := initCommitteeGroup(ctx, initCommitteeGroupPrm{
logger: prm.Logger,
blockchain: prm.Blockchain,
monitor: monitor,
nnsOnChainAddress: nnsOnChainAddress,
systemEmail: prm.NNS.SystemEmail,
committee: committee,
localAcc: prm.LocalAccount,
localAccCommitteeIndex: localAccCommitteeIndex,
keyStorage: prm.KeyStorage,
})
if err != nil {
return fmt.Errorf("init committee group: %w", err)
}

prm.Logger.Info("committee group successfully initialized", zap.Stringer("public key", committeeGroupKey.PublicKey()))

prm.Logger.Info("registering committee group in the NNS...")

err = registerCommitteeGroupInNNS(ctx, registerCommitteeGroupInNNSPrm{
logger: prm.Logger,
blockchain: prm.Blockchain,
monitor: monitor,
nnsContract: nnsOnChainAddress,
systemEmail: prm.NNS.SystemEmail,
localAcc: prm.LocalAccount,
committee: committee,
committeeGroupKey: committeeGroupKey,
})
if err != nil {
return fmt.Errorf("regsiter committee group in the NNS: %w", err)
}

prm.Logger.Info("committee group successfully registered in the NNS")

prm.Logger.Info("initializing NeoFS Alphabet...")

err = initAlphabet(ctx, initAlphabetPrm{
Expand All @@ -394,7 +326,6 @@ func Deploy(ctx context.Context, prm Prm) error {
nnsContract: nnsOnChainAddress,
systemEmail: prm.NNS.SystemEmail,
committee: committee,
committeeGroupKey: committeeGroupKey,
simpleLocalActor: simpleLocalActor,
committeeLocalActor: committeeLocalActor,
}
Expand Down Expand Up @@ -509,7 +440,6 @@ func Deploy(ctx context.Context, prm Prm) error {
localManifest: prm.NNS.Common.Manifest,
systemEmail: prm.NNS.SystemEmail,
committee: committee,
committeeGroupKey: committeeGroupKey,
buildExtraUpdateArgs: noExtraUpdateArgs,
proxyContract: proxyContractAddress,
})
Expand Down
Loading

0 comments on commit 06dcd7e

Please sign in to comment.