forked from TrueCloudLab/frostfs-node
[#352] Add explicit max number of alphabet nodes
Signed-off-by: Alejandro Lopez <a.lopez@yadro.com>
This commit is contained in:
parent
13a7a90101
commit
df9e099fa7
4 changed files with 41 additions and 10 deletions
|
@ -18,6 +18,7 @@ To start a network, you need a set of consensus nodes, the same number of
|
||||||
Alphabet nodes and any number of Storage nodes. While the number of Storage
|
Alphabet nodes and any number of Storage nodes. While the number of Storage
|
||||||
nodes can be scaled almost infinitely, the number of consensus and Alphabet
|
nodes can be scaled almost infinitely, the number of consensus and Alphabet
|
||||||
nodes can't be changed so easily right now. Consider this before going any further.
|
nodes can't be changed so easily right now. Consider this before going any further.
|
||||||
|
Note also that there is an upper limit on the number of alphabet nodes (currently 22).
|
||||||
|
|
||||||
It is easier to use`frostfs-adm` with a predefined configuration. First, create
|
It is easier to use`frostfs-adm` with a predefined configuration. First, create
|
||||||
a network configuration file. In this example, there is going to be only one
|
a network configuration file. In this example, there is going to be only one
|
||||||
|
|
|
@ -39,6 +39,9 @@ func generateAlphabetCreds(cmd *cobra.Command, _ []string) error {
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return errors.New("size must be > 0")
|
return errors.New("size must be > 0")
|
||||||
}
|
}
|
||||||
|
if size > maxAlphabetNodes {
|
||||||
|
return ErrTooManyAlphabetNodes
|
||||||
|
}
|
||||||
|
|
||||||
v := viper.GetViper()
|
v := viper.GetViper()
|
||||||
walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag))
|
walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag))
|
||||||
|
|
|
@ -23,6 +23,13 @@ import (
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// maxAlphabetNodes is the maximum number of candidates allowed, which is currently limited by the size
|
||||||
|
// of the invocation script.
|
||||||
|
// See: https://github.com/nspcc-dev/neo-go/blob/740488f7f35e367eaa99a71c0a609c315fe2b0fc/pkg/core/transaction/witness.go#L10
|
||||||
|
maxAlphabetNodes = 22
|
||||||
|
)
|
||||||
|
|
||||||
type cache struct {
|
type cache struct {
|
||||||
nnsCs *state.Contract
|
nnsCs *state.Contract
|
||||||
groupKey *keys.PublicKey
|
groupKey *keys.PublicKey
|
||||||
|
@ -45,6 +52,8 @@ type initializeContext struct {
|
||||||
ContractPath string
|
ContractPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ErrTooManyAlphabetNodes = fmt.Errorf("too many alphabet nodes (maximum allowed is %d)", maxAlphabetNodes)
|
||||||
|
|
||||||
func initializeSideChainCmd(cmd *cobra.Command, _ []string) error {
|
func initializeSideChainCmd(cmd *cobra.Command, _ []string) error {
|
||||||
initCtx, err := newInitializeContext(cmd, viper.GetViper())
|
initCtx, err := newInitializeContext(cmd, viper.GetViper())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -111,6 +120,10 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(wallets) > maxAlphabetNodes {
|
||||||
|
return nil, ErrTooManyAlphabetNodes
|
||||||
|
}
|
||||||
|
|
||||||
needContracts := cmd.Name() == "update-contracts" || cmd.Name() == "init"
|
needContracts := cmd.Name() == "update-contracts" || cmd.Name() == "init"
|
||||||
|
|
||||||
var w *wallet.Wallet
|
var w *wallet.Wallet
|
||||||
|
|
|
@ -2,6 +2,7 @@ package morph
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -40,8 +41,11 @@ func TestInitialize(t *testing.T) {
|
||||||
t.Run("16 nodes", func(t *testing.T) {
|
t.Run("16 nodes", func(t *testing.T) {
|
||||||
testInitialize(t, 16)
|
testInitialize(t, 16)
|
||||||
})
|
})
|
||||||
t.Run("22 nodes", func(t *testing.T) {
|
t.Run("max nodes", func(t *testing.T) {
|
||||||
testInitialize(t, 22)
|
testInitialize(t, maxAlphabetNodes)
|
||||||
|
})
|
||||||
|
t.Run("too many nodes", func(t *testing.T) {
|
||||||
|
require.ErrorIs(t, generateTestData(t, t.TempDir(), maxAlphabetNodes+1), ErrTooManyAlphabetNodes)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +53,7 @@ func testInitialize(t *testing.T, committeeSize int) {
|
||||||
testdataDir := t.TempDir()
|
testdataDir := t.TempDir()
|
||||||
v := viper.GetViper()
|
v := viper.GetViper()
|
||||||
|
|
||||||
generateTestData(t, testdataDir, committeeSize)
|
require.NoError(t, generateTestData(t, testdataDir, committeeSize))
|
||||||
v.Set(protoConfigPath, filepath.Join(testdataDir, protoFileName))
|
v.Set(protoConfigPath, filepath.Join(testdataDir, protoFileName))
|
||||||
|
|
||||||
// Set to the path or remove the next statement to download from the network.
|
// Set to the path or remove the next statement to download from the network.
|
||||||
|
@ -80,25 +84,33 @@ func testInitialize(t *testing.T, committeeSize int) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateTestData(t *testing.T, dir string, size int) {
|
func generateTestData(t *testing.T, dir string, size int) error {
|
||||||
v := viper.GetViper()
|
v := viper.GetViper()
|
||||||
v.Set(alphabetWalletsFlag, dir)
|
v.Set(alphabetWalletsFlag, dir)
|
||||||
|
|
||||||
sizeStr := strconv.FormatUint(uint64(size), 10)
|
sizeStr := strconv.FormatUint(uint64(size), 10)
|
||||||
require.NoError(t, generateAlphabetCmd.Flags().Set(alphabetSizeFlag, sizeStr))
|
if err := generateAlphabetCmd.Flags().Set(alphabetSizeFlag, sizeStr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
setTestCredentials(v, size)
|
setTestCredentials(v, size)
|
||||||
require.NoError(t, generateAlphabetCreds(generateAlphabetCmd, nil))
|
if err := generateAlphabetCreds(generateAlphabetCmd, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var pubs []string
|
var pubs []string
|
||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
p := filepath.Join(dir, innerring.GlagoliticLetter(i).String()+".json")
|
p := filepath.Join(dir, innerring.GlagoliticLetter(i).String()+".json")
|
||||||
w, err := wallet.NewWalletFromFile(p)
|
w, err := wallet.NewWalletFromFile(p)
|
||||||
require.NoError(t, err, "wallet doesn't exist")
|
if err != nil {
|
||||||
|
return fmt.Errorf("wallet doesn't exist: %w", err)
|
||||||
|
}
|
||||||
for _, acc := range w.Accounts {
|
for _, acc := range w.Accounts {
|
||||||
if acc.Label == singleAccountName {
|
if acc.Label == singleAccountName {
|
||||||
pub, ok := vm.ParseSignatureContract(acc.Contract.Script)
|
pub, ok := vm.ParseSignatureContract(acc.Contract.Script)
|
||||||
require.True(t, ok)
|
if !ok {
|
||||||
|
return fmt.Errorf("could not parse signature script for %s", acc.Address)
|
||||||
|
}
|
||||||
pubs = append(pubs, hex.EncodeToString(pub))
|
pubs = append(pubs, hex.EncodeToString(pub))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -113,10 +125,12 @@ func generateTestData(t *testing.T, dir string, size int) {
|
||||||
cfg.ProtocolConfiguration.P2PSigExtensions = true
|
cfg.ProtocolConfiguration.P2PSigExtensions = true
|
||||||
cfg.ProtocolConfiguration.VerifyTransactions = true
|
cfg.ProtocolConfiguration.VerifyTransactions = true
|
||||||
data, err := yaml.Marshal(cfg)
|
data, err := yaml.Marshal(cfg)
|
||||||
require.NoError(t, err)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
protoPath := filepath.Join(dir, protoFileName)
|
protoPath := filepath.Join(dir, protoFileName)
|
||||||
require.NoError(t, os.WriteFile(protoPath, data, os.ModePerm))
|
return os.WriteFile(protoPath, data, os.ModePerm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setTestCredentials(v *viper.Viper, size int) {
|
func setTestCredentials(v *viper.Viper, size int) {
|
||||||
|
|
Loading…
Reference in a new issue