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 (
"errors"
"fmt"
"sync"
"sync/atomic"
"time"
@ -9,6 +10,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/config"
"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/native/noderoles"
"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/crypto/keys"
@ -22,6 +24,7 @@ type (
// Ledger is an interface to Blockchain sufficient for Service.
Ledger interface {
GetConfig() config.Blockchain
GetDesignatedByRole(role noderoles.Role) (keys.PublicKeys, uint32, error)
HeaderHeight() uint32
SubscribeForBlocks(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
// not be started again by calling Start (use a new instance if needed).
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 {
@ -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")
}
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)
}
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())
}
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 {
*storage.MemoryStore
}