stateroot: broadcast state on new blocks
This commit is contained in:
parent
3c65ed1507
commit
2f3abf95a2
9 changed files with 75 additions and 36 deletions
|
@ -14,7 +14,6 @@ type StateRoot interface {
|
|||
GetStateProof(root util.Uint256, key []byte) ([][]byte, error)
|
||||
GetStateRoot(height uint32) (*state.MPTRoot, error)
|
||||
GetStateValidators(height uint32) keys.PublicKeys
|
||||
SetSignAndSendCallback(func(*state.MPTRoot) error)
|
||||
SetUpdateValidatorsCallback(func(keys.PublicKeys))
|
||||
SetUpdateValidatorsCallback(func(uint32, keys.PublicKeys))
|
||||
UpdateStateValidators(height uint32, pubs keys.PublicKeys)
|
||||
}
|
||||
|
|
|
@ -1,19 +1,11 @@
|
|||
package stateroot
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
)
|
||||
|
||||
// SetSignAndSendCb sets callback for sending signed root.
|
||||
func (s *Module) SetSignAndSendCallback(f func(*state.MPTRoot) error) {
|
||||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
s.signAndSendCb = f
|
||||
}
|
||||
|
||||
// SetUpdateValidatorsCallback sets callback for sending signed root.
|
||||
func (s *Module) SetUpdateValidatorsCallback(f func(keys.PublicKeys)) {
|
||||
func (s *Module) SetUpdateValidatorsCallback(f func(uint32, keys.PublicKeys)) {
|
||||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
s.updateValidatorsCb = f
|
||||
|
|
|
@ -31,8 +31,7 @@ type (
|
|||
mtx sync.RWMutex
|
||||
keys []keyCache
|
||||
|
||||
updateValidatorsCb func(publicKeys keys.PublicKeys)
|
||||
signAndSendCb func(*state.MPTRoot) error
|
||||
updateValidatorsCb func(height uint32, publicKeys keys.PublicKeys)
|
||||
}
|
||||
|
||||
keyCache struct {
|
||||
|
|
|
@ -31,9 +31,6 @@ func (s *Module) addLocalStateRoot(sr *state.MPTRoot) error {
|
|||
s.validatedHeight.Store(sr.Index)
|
||||
updateStateHeightMetric(sr.Index)
|
||||
}
|
||||
if s.signAndSendCb != nil {
|
||||
return s.signAndSendCb(sr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ func (s *Module) UpdateStateValidators(height uint32, pubs keys.PublicKeys) {
|
|||
|
||||
s.mtx.Lock()
|
||||
if s.updateValidatorsCb != nil {
|
||||
s.updateValidatorsCb(pubs)
|
||||
s.updateValidatorsCb(height, pubs)
|
||||
}
|
||||
kc := s.getKeyCacheForHeight(height)
|
||||
if kc.validatorsHash != h {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"path"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
|
@ -23,6 +24,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/atomic"
|
||||
"go.uber.org/zap/zaptest"
|
||||
)
|
||||
|
||||
|
@ -80,7 +82,7 @@ func TestStateRoot(t *testing.T) {
|
|||
defer os.RemoveAll(tmpDir)
|
||||
w := createAndWriteWallet(t, accs[0], path.Join(tmpDir, "w"), "pass")
|
||||
cfg := createStateRootConfig(w.Path(), "pass")
|
||||
srv, err := stateroot.New(cfg, zaptest.NewLogger(t), bc.GetStateModule())
|
||||
srv, err := stateroot.New(cfg, zaptest.NewLogger(t), bc)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 0, srv.CurrentValidatedHeight())
|
||||
r, err := srv.GetStateRoot(bc.BlockHeight())
|
||||
|
@ -150,7 +152,7 @@ func TestStateRootInitNonZeroHeight(t *testing.T) {
|
|||
defer os.RemoveAll(tmpDir)
|
||||
w := createAndWriteWallet(t, accs[0], path.Join(tmpDir, "w"), "pass")
|
||||
cfg := createStateRootConfig(w.Path(), "pass")
|
||||
srv, err := stateroot.New(cfg, zaptest.NewLogger(t), bc.GetStateModule())
|
||||
srv, err := stateroot.New(cfg, zaptest.NewLogger(t), bc)
|
||||
require.NoError(t, err)
|
||||
r, err := srv.GetStateRoot(2)
|
||||
require.NoError(t, err)
|
||||
|
@ -196,27 +198,33 @@ func TestStateRootFull(t *testing.T) {
|
|||
h, pubs, accs := newMajorityMultisigWithGAS(t, 2)
|
||||
w := createAndWriteWallet(t, accs[1], path.Join(tmpDir, "wallet2"), "two")
|
||||
cfg := createStateRootConfig(w.Path(), "two")
|
||||
srv, err := stateroot.New(cfg, zaptest.NewLogger(t), bc.GetStateModule())
|
||||
srv, err := stateroot.New(cfg, zaptest.NewLogger(t), bc)
|
||||
require.NoError(t, err)
|
||||
srv.Run()
|
||||
t.Cleanup(srv.Shutdown)
|
||||
|
||||
var lastValidated *payload.Extensible
|
||||
var lastValidated atomic.Value
|
||||
var lastHeight atomic.Uint32
|
||||
srv.SetRelayCallback(func(ep *payload.Extensible) {
|
||||
lastValidated = ep
|
||||
lastHeight.Store(ep.ValidBlockStart)
|
||||
lastValidated.Store(ep)
|
||||
})
|
||||
|
||||
bc.setNodesByRole(t, true, native.RoleStateValidator, pubs)
|
||||
transferTokenFromMultisigAccount(t, bc, h, bc.contracts.GAS.Hash, 1_0000_0000)
|
||||
checkVoteBroadcasted(t, bc, lastValidated, 2, 1)
|
||||
require.Eventually(t, func() bool { return lastHeight.Load() == 2 }, time.Second, time.Millisecond)
|
||||
checkVoteBroadcasted(t, bc, lastValidated.Load().(*payload.Extensible), 2, 1)
|
||||
_, err = persistBlock(bc)
|
||||
checkVoteBroadcasted(t, bc, lastValidated, 3, 1)
|
||||
require.Eventually(t, func() bool { return lastHeight.Load() == 3 }, time.Second, time.Millisecond)
|
||||
checkVoteBroadcasted(t, bc, lastValidated.Load().(*payload.Extensible), 3, 1)
|
||||
|
||||
r, err := srv.GetStateRoot(2)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, srv.AddSignature(2, 0, accs[0].PrivateKey().SignHash(r.GetSignedHash())))
|
||||
require.NotNil(t, lastValidated)
|
||||
require.NotNil(t, lastValidated.Load().(*payload.Extensible))
|
||||
|
||||
msg := new(stateroot.Message)
|
||||
require.NoError(t, testserdes.DecodeBinary(lastValidated.Data, msg))
|
||||
require.NoError(t, testserdes.DecodeBinary(lastValidated.Load().(*payload.Extensible).Data, msg))
|
||||
require.Equal(t, stateroot.RootT, msg.Type)
|
||||
|
||||
actual := msg.Payload.(*state.MPTRoot)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue