core: shrink blockchainer.StateRoot further, leave simple RO methods

This commit is contained in:
Roman Khimov 2022-01-14 02:09:16 +03:00
parent 077d5ccb03
commit ddb23ccf78
4 changed files with 27 additions and 32 deletions

View file

@ -14,6 +14,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core" "github.com/nspcc-dev/neo-go/pkg/core"
"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/chaindump" "github.com/nspcc-dev/neo-go/pkg/core/chaindump"
corestate "github.com/nspcc-dev/neo-go/pkg/core/stateroot"
"github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
@ -413,7 +414,8 @@ func startServer(ctx *cli.Context) error {
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("failed to create network server: %w", err), 1) return cli.NewExitError(fmt.Errorf("failed to create network server: %w", err), 1)
} }
sr, err := stateroot.New(serverConfig.StateRootCfg, log, chain, serv.BroadcastExtensible) srMod := chain.GetStateModule().(*corestate.Module) // Take full responsibility here.
sr, err := stateroot.New(serverConfig.StateRootCfg, srMod, log, chain, serv.BroadcastExtensible)
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("can't initialize StateRoot service: %w", err), 1) return cli.NewExitError(fmt.Errorf("can't initialize StateRoot service: %w", err), 1)
} }

View file

@ -3,13 +3,11 @@ package blockchainer
import ( import (
"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/storage" "github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
) )
// StateRoot represents local state root module. // StateRoot represents local state root module.
type StateRoot interface { type StateRoot interface {
AddStateRoot(root *state.MPTRoot) error
CurrentLocalHeight() uint32 CurrentLocalHeight() uint32
CurrentLocalStateRoot() util.Uint256 CurrentLocalStateRoot() util.Uint256
CurrentValidatedHeight() uint32 CurrentValidatedHeight() uint32
@ -17,6 +15,4 @@ type StateRoot interface {
GetState(root util.Uint256, key []byte) ([]byte, error) GetState(root util.Uint256, key []byte) ([]byte, error)
GetStateProof(root util.Uint256, key []byte) ([][]byte, error) GetStateProof(root util.Uint256, key []byte) ([][]byte, error)
GetStateRoot(height uint32) (*state.MPTRoot, error) GetStateRoot(height uint32) (*state.MPTRoot, error)
GetStateValidators(height uint32) keys.PublicKeys
SetUpdateValidatorsCallback(func(uint32, keys.PublicKeys))
} }

View file

@ -80,32 +80,32 @@ func TestStateRoot(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
w := createAndWriteWallet(t, accs[0], filepath.Join(tmpDir, "w"), "pass") w := createAndWriteWallet(t, accs[0], filepath.Join(tmpDir, "w"), "pass")
cfg := createStateRootConfig(w.Path(), "pass") cfg := createStateRootConfig(w.Path(), "pass")
srv, err := stateroot.New(cfg, zaptest.NewLogger(t), bc, nil) srv, err := stateroot.New(cfg, bc.stateRoot, zaptest.NewLogger(t), bc, nil)
require.NoError(t, err) require.NoError(t, err)
require.EqualValues(t, 0, srv.CurrentValidatedHeight()) require.EqualValues(t, 0, bc.stateRoot.CurrentValidatedHeight())
r, err := srv.GetStateRoot(bc.BlockHeight()) r, err := bc.stateRoot.GetStateRoot(bc.BlockHeight())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, r.Root, srv.CurrentLocalStateRoot()) require.Equal(t, r.Root, bc.stateRoot.CurrentLocalStateRoot())
t.Run("invalid message", func(t *testing.T) { t.Run("invalid message", func(t *testing.T) {
require.Error(t, srv.OnPayload(&payload.Extensible{Data: []byte{42}})) require.Error(t, srv.OnPayload(&payload.Extensible{Data: []byte{42}}))
require.EqualValues(t, 0, srv.CurrentValidatedHeight()) require.EqualValues(t, 0, bc.stateRoot.CurrentValidatedHeight())
}) })
t.Run("drop zero index", func(t *testing.T) { t.Run("drop zero index", func(t *testing.T) {
r, err := srv.GetStateRoot(0) r, err := bc.stateRoot.GetStateRoot(0)
require.NoError(t, err) require.NoError(t, err)
data, err := testserdes.EncodeBinary(stateroot.NewMessage(stateroot.RootT, r)) data, err := testserdes.EncodeBinary(stateroot.NewMessage(stateroot.RootT, r))
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, srv.OnPayload(&payload.Extensible{Data: data})) require.NoError(t, srv.OnPayload(&payload.Extensible{Data: data}))
require.EqualValues(t, 0, srv.CurrentValidatedHeight()) require.EqualValues(t, 0, bc.stateRoot.CurrentValidatedHeight())
}) })
t.Run("invalid height", func(t *testing.T) { t.Run("invalid height", func(t *testing.T) {
r, err := srv.GetStateRoot(1) r, err := bc.stateRoot.GetStateRoot(1)
require.NoError(t, err) require.NoError(t, err)
r.Index = 10 r.Index = 10
data := testSignStateRoot(t, r, pubs, accs...) data := testSignStateRoot(t, r, pubs, accs...)
require.Error(t, srv.OnPayload(&payload.Extensible{Data: data})) require.Error(t, srv.OnPayload(&payload.Extensible{Data: data}))
require.EqualValues(t, 0, srv.CurrentValidatedHeight()) require.EqualValues(t, 0, bc.stateRoot.CurrentValidatedHeight())
}) })
t.Run("invalid signer", func(t *testing.T) { t.Run("invalid signer", func(t *testing.T) {
accInv, err := wallet.NewAccount() accInv, err := wallet.NewAccount()
@ -113,21 +113,21 @@ func TestStateRoot(t *testing.T) {
pubs := keys.PublicKeys{accInv.PrivateKey().PublicKey()} pubs := keys.PublicKeys{accInv.PrivateKey().PublicKey()}
require.NoError(t, accInv.ConvertMultisig(1, pubs)) require.NoError(t, accInv.ConvertMultisig(1, pubs))
transferTokenFromMultisigAccount(t, bc, accInv.Contract.ScriptHash(), bc.contracts.GAS.Hash, 1_0000_0000) transferTokenFromMultisigAccount(t, bc, accInv.Contract.ScriptHash(), bc.contracts.GAS.Hash, 1_0000_0000)
r, err := srv.GetStateRoot(1) r, err := bc.stateRoot.GetStateRoot(1)
require.NoError(t, err) require.NoError(t, err)
data := testSignStateRoot(t, r, pubs, accInv) data := testSignStateRoot(t, r, pubs, accInv)
err = srv.OnPayload(&payload.Extensible{Data: data}) err = srv.OnPayload(&payload.Extensible{Data: data})
require.True(t, errors.Is(err, ErrWitnessHashMismatch), "got: %v", err) require.True(t, errors.Is(err, ErrWitnessHashMismatch), "got: %v", err)
require.EqualValues(t, 0, srv.CurrentValidatedHeight()) require.EqualValues(t, 0, bc.stateRoot.CurrentValidatedHeight())
}) })
r, err = srv.GetStateRoot(updateIndex + 1) r, err = bc.stateRoot.GetStateRoot(updateIndex + 1)
require.NoError(t, err) require.NoError(t, err)
data := testSignStateRoot(t, r, pubs, accs...) data := testSignStateRoot(t, r, pubs, accs...)
require.NoError(t, srv.OnPayload(&payload.Extensible{Data: data})) require.NoError(t, srv.OnPayload(&payload.Extensible{Data: data}))
require.EqualValues(t, 2, srv.CurrentValidatedHeight()) require.EqualValues(t, 2, bc.stateRoot.CurrentValidatedHeight())
r, err = srv.GetStateRoot(updateIndex + 1) r, err = bc.stateRoot.GetStateRoot(updateIndex + 1)
require.NoError(t, err) require.NoError(t, err)
require.NotEqual(t, 0, len(r.Witness)) require.NotEqual(t, 0, len(r.Witness))
require.Equal(t, h, r.Witness[0].ScriptHash()) require.Equal(t, h, r.Witness[0].ScriptHash())
@ -148,14 +148,14 @@ func TestStateRootInitNonZeroHeight(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
w := createAndWriteWallet(t, accs[0], filepath.Join(tmpDir, "w"), "pass") w := createAndWriteWallet(t, accs[0], filepath.Join(tmpDir, "w"), "pass")
cfg := createStateRootConfig(w.Path(), "pass") cfg := createStateRootConfig(w.Path(), "pass")
srv, err := stateroot.New(cfg, zaptest.NewLogger(t), bc, nil) srv, err := stateroot.New(cfg, bc.stateRoot, zaptest.NewLogger(t), bc, nil)
require.NoError(t, err) require.NoError(t, err)
r, err := srv.GetStateRoot(2) r, err := bc.stateRoot.GetStateRoot(2)
require.NoError(t, err) require.NoError(t, err)
data := testSignStateRoot(t, r, pubs, accs...) data := testSignStateRoot(t, r, pubs, accs...)
require.NoError(t, srv.OnPayload(&payload.Extensible{Data: data})) require.NoError(t, srv.OnPayload(&payload.Extensible{Data: data}))
require.EqualValues(t, 2, srv.CurrentValidatedHeight()) require.EqualValues(t, 2, bc.stateRoot.CurrentValidatedHeight())
root = srv.CurrentLocalStateRoot() root = bc.stateRoot.CurrentLocalStateRoot()
}) })
bc2 := newTestChainWithCustomCfgAndStore(t, st, nil) bc2 := newTestChainWithCustomCfgAndStore(t, st, nil)
@ -194,7 +194,7 @@ func TestStateRootFull(t *testing.T) {
var lastValidated atomic.Value var lastValidated atomic.Value
var lastHeight atomic.Uint32 var lastHeight atomic.Uint32
srv, err := stateroot.New(cfg, zaptest.NewLogger(t), bc, func(ep *payload.Extensible) { srv, err := stateroot.New(cfg, bc.stateRoot, zaptest.NewLogger(t), bc, func(ep *payload.Extensible) {
lastHeight.Store(ep.ValidBlockStart) lastHeight.Store(ep.ValidBlockStart)
lastValidated.Store(ep) lastValidated.Store(ep)
}) })
@ -211,7 +211,7 @@ func TestStateRootFull(t *testing.T) {
require.Eventually(t, func() bool { return lastHeight.Load() == 3 }, time.Second, time.Millisecond) require.Eventually(t, func() bool { return lastHeight.Load() == 3 }, time.Second, time.Millisecond)
checkVoteBroadcasted(t, bc, lastValidated.Load().(*payload.Extensible), 3, 1) checkVoteBroadcasted(t, bc, lastValidated.Load().(*payload.Extensible), 3, 1)
r, err := srv.GetStateRoot(2) r, err := bc.stateRoot.GetStateRoot(2)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, srv.AddSignature(2, 0, accs[0].PrivateKey().SignHashable(uint32(netmode.UnitTestNet), r))) require.NoError(t, srv.AddSignature(2, 0, accs[0].PrivateKey().SignHashable(uint32(netmode.UnitTestNet), r)))
require.NotNil(t, lastValidated.Load().(*payload.Extensible)) require.NotNil(t, lastValidated.Load().(*payload.Extensible))
@ -220,7 +220,7 @@ func TestStateRootFull(t *testing.T) {
require.NoError(t, testserdes.DecodeBinary(lastValidated.Load().(*payload.Extensible).Data, msg)) require.NoError(t, testserdes.DecodeBinary(lastValidated.Load().(*payload.Extensible).Data, msg))
require.NotEqual(t, stateroot.RootT, msg.Type) // not a sender for this root require.NotEqual(t, stateroot.RootT, msg.Type) // not a sender for this root
r, err = srv.GetStateRoot(3) r, err = bc.stateRoot.GetStateRoot(3)
require.NoError(t, err) require.NoError(t, err)
require.Error(t, srv.AddSignature(2, 0, accs[0].PrivateKey().SignHashable(uint32(netmode.UnitTestNet), r))) require.Error(t, srv.AddSignature(2, 0, accs[0].PrivateKey().SignHashable(uint32(netmode.UnitTestNet), r)))
require.NoError(t, srv.AddSignature(3, 0, accs[0].PrivateKey().SignHashable(uint32(netmode.UnitTestNet), r))) require.NoError(t, srv.AddSignature(3, 0, accs[0].PrivateKey().SignHashable(uint32(netmode.UnitTestNet), r)))

View file

@ -8,7 +8,6 @@ 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/blockchainer"
"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,7 +21,6 @@ type (
// Ledger is the interface to Blockchain sufficient for Service. // Ledger is the interface to Blockchain sufficient for Service.
Ledger interface { Ledger interface {
GetConfig() config.ProtocolConfiguration GetConfig() config.ProtocolConfiguration
GetStateModule() blockchainer.StateRoot
HeaderHeight() uint32 HeaderHeight() uint32
SubscribeForBlocks(ch chan<- *block.Block) SubscribeForBlocks(ch chan<- *block.Block)
UnsubscribeFromBlocks(ch chan<- *block.Block) UnsubscribeFromBlocks(ch chan<- *block.Block)
@ -30,7 +28,6 @@ type (
// Service represents state root service. // Service represents state root service.
Service interface { Service interface {
blockchainer.StateRoot
OnPayload(p *payload.Extensible) error OnPayload(p *payload.Extensible) error
AddSignature(height uint32, validatorIndex int32, sig []byte) error AddSignature(height uint32, validatorIndex int32, sig []byte) error
GetConfig() config.StateRoot GetConfig() config.StateRoot
@ -39,7 +36,7 @@ type (
} }
service struct { service struct {
blockchainer.StateRoot *stateroot.Module
chain Ledger chain Ledger
MainCfg config.StateRoot MainCfg config.StateRoot
@ -69,10 +66,10 @@ const (
) )
// New returns new state root service instance using underlying module. // New returns new state root service instance using underlying module.
func New(cfg config.StateRoot, log *zap.Logger, bc Ledger, cb RelayCallback) (Service, error) { func New(cfg config.StateRoot, sm *stateroot.Module, log *zap.Logger, bc Ledger, cb RelayCallback) (Service, error) {
bcConf := bc.GetConfig() bcConf := bc.GetConfig()
s := &service{ s := &service{
StateRoot: bc.GetStateModule(), Module: sm,
Network: bcConf.Magic, Network: bcConf.Magic,
chain: bc, chain: bc,
log: log, log: log,