services: adjust StateRoot service initialisation

Perform initialisation of StateRoot service with designated
StateValidator's node list in the service constructor. There's no need
to wait until the next role update event, and it may lead to inaccuraces
in service work on SIGHUP/server restart.

A part of #3228.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
Anna Shaleva 2023-11-24 15:24:02 +03:00
parent 11ec0db350
commit 15b4e0a8cd
2 changed files with 38 additions and 0 deletions

View file

@ -2,6 +2,7 @@ package stateroot
import ( import (
"errors" "errors"
"fmt"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -9,6 +10,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/stateroot" "github.com/nspcc-dev/neo-go/pkg/core/stateroot"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
@ -22,6 +24,7 @@ type (
// Ledger is an interface to Blockchain sufficient for Service. // Ledger is an interface to Blockchain sufficient for Service.
Ledger interface { Ledger interface {
GetConfig() config.Blockchain GetConfig() config.Blockchain
GetDesignatedByRole(role noderoles.Role) (keys.PublicKeys, uint32, error)
HeaderHeight() uint32 HeaderHeight() uint32
SubscribeForBlocks(ch chan *block.Block) SubscribeForBlocks(ch chan *block.Block)
UnsubscribeFromBlocks(ch chan *block.Block) UnsubscribeFromBlocks(ch chan *block.Block)
@ -40,6 +43,10 @@ type (
// to Shutdown on the same instance are no-op. The instance that was stopped can // to Shutdown on the same instance are no-op. The instance that was stopped can
// not be started again by calling Start (use a new instance if needed). // not be started again by calling Start (use a new instance if needed).
Shutdown() Shutdown()
// IsAuthorized returns whether state root service currently is authorized to sign
// state roots. It returns true iff designated StateValidator node's account
// provided to the state root service in decrypted state.
IsAuthorized() bool
} }
service struct { service struct {
@ -116,6 +123,12 @@ func New(cfg config.StateRoot, sm *stateroot.Module, log *zap.Logger, bc Ledger,
return nil, errors.New("no wallet account could be unlocked") return nil, errors.New("no wallet account could be unlocked")
} }
keys, h, err := bc.GetDesignatedByRole(noderoles.StateValidator)
if err != nil {
return nil, fmt.Errorf("failed to get designated StateValidators: %w", err)
}
s.updateValidators(h, keys)
s.SetUpdateValidatorsCallback(s.updateValidators) s.SetUpdateValidatorsCallback(s.updateValidators)
} }
return s, nil return s, nil
@ -173,3 +186,9 @@ func (s *service) updateValidators(height uint32, pubs keys.PublicKeys) {
} }
} }
} }
// IsAuthorized implements Service interface.
func (s *service) IsAuthorized() bool {
_, acc := s.getAccount()
return acc != nil
}

View file

@ -148,6 +148,25 @@ func TestStateRoot(t *testing.T) {
require.Equal(t, h, r.Witness[0].ScriptHash()) require.Equal(t, h, r.Witness[0].ScriptHash())
} }
func TestStateRoot_GenesisRole(t *testing.T) {
_, _, accs := newMajorityMultisigWithGAS(t, 2)
bc, _, _ := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) {
c.Genesis.Roles = map[noderoles.Role]keys.PublicKeys{
noderoles.StateValidator: {accs[0].PublicKey(), accs[1].PublicKey()},
}
})
tmpDir := t.TempDir()
w := createAndWriteWallet(t, accs[0], filepath.Join(tmpDir, "w"), "pass")
cfg := createStateRootConfig(w.Path(), "pass")
srMod := bc.GetStateModule().(*corestate.Module) // Take full responsibility here.
srv, err := stateroot.New(cfg, srMod, zaptest.NewLogger(t), bc, nil)
require.NoError(t, err)
require.True(t, srv.IsAuthorized())
}
type memoryStore struct { type memoryStore struct {
*storage.MemoryStore *storage.MemoryStore
} }