Merge pull request #2028 from nspcc-dev/core/fix-add-headers
core: allow to add several headers with StateRootInHeader on
This commit is contained in:
commit
c203995a9b
3 changed files with 41 additions and 3 deletions
|
@ -782,6 +782,15 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error
|
||||||
// because changes applied are the ones from HALTed transactions.
|
// because changes applied are the ones from HALTed transactions.
|
||||||
return fmt.Errorf("error while trying to apply MPT changes: %w", err)
|
return fmt.Errorf("error while trying to apply MPT changes: %w", err)
|
||||||
}
|
}
|
||||||
|
if bc.config.StateRootInHeader && bc.HeaderHeight() > sr.Index {
|
||||||
|
h, err := bc.GetHeader(bc.GetHeaderHash(int(sr.Index) + 1))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get next header: %w", err)
|
||||||
|
}
|
||||||
|
if h.PrevStateRoot != sr.Root {
|
||||||
|
return fmt.Errorf("local stateroot and next header's PrevStateRoot mismatch: %s vs %s", sr.Root.StringBE(), h.PrevStateRoot.StringBE())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if bc.config.SaveStorageBatch {
|
if bc.config.SaveStorageBatch {
|
||||||
bc.lastBatch = cache.DAO.GetBatch()
|
bc.lastBatch = cache.DAO.GetBatch()
|
||||||
|
@ -1430,11 +1439,13 @@ var (
|
||||||
|
|
||||||
func (bc *Blockchain) verifyHeader(currHeader, prevHeader *block.Header) error {
|
func (bc *Blockchain) verifyHeader(currHeader, prevHeader *block.Header) error {
|
||||||
if bc.config.StateRootInHeader {
|
if bc.config.StateRootInHeader {
|
||||||
|
if bc.stateRoot.CurrentLocalHeight() == prevHeader.Index {
|
||||||
if sr := bc.stateRoot.CurrentLocalStateRoot(); currHeader.PrevStateRoot != sr {
|
if sr := bc.stateRoot.CurrentLocalStateRoot(); currHeader.PrevStateRoot != sr {
|
||||||
return fmt.Errorf("%w: %s != %s",
|
return fmt.Errorf("%w: %s != %s",
|
||||||
ErrHdrInvalidStateRoot, currHeader.PrevStateRoot.StringLE(), sr.StringLE())
|
ErrHdrInvalidStateRoot, currHeader.PrevStateRoot.StringLE(), sr.StringLE())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if prevHeader.Hash() != currHeader.PrevHash {
|
if prevHeader.Hash() != currHeader.PrevHash {
|
||||||
return ErrHdrHashMismatch
|
return ErrHdrHashMismatch
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,28 @@ func TestAddBlockStateRoot(t *testing.T) {
|
||||||
require.NoError(t, bc.AddBlock(b))
|
require.NoError(t, bc.AddBlock(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAddHeadersStateRoot(t *testing.T) {
|
||||||
|
bc := newTestChainWithCustomCfg(t, func(c *config.Config) {
|
||||||
|
c.ProtocolConfiguration.StateRootInHeader = true
|
||||||
|
})
|
||||||
|
|
||||||
|
r := bc.stateRoot.CurrentLocalStateRoot()
|
||||||
|
h1 := bc.newBlock().Header
|
||||||
|
|
||||||
|
// invalid stateroot
|
||||||
|
h1.PrevStateRoot[0] ^= 0xFF
|
||||||
|
require.True(t, errors.Is(bc.AddHeaders(&h1), ErrHdrInvalidStateRoot))
|
||||||
|
|
||||||
|
// valid stateroot
|
||||||
|
h1.PrevStateRoot = r
|
||||||
|
require.NoError(t, bc.AddHeaders(&h1))
|
||||||
|
|
||||||
|
// unable to verify stateroot (stateroot is computed for block #0 only => can
|
||||||
|
// verify stateroot of header #1 only) => just store the header
|
||||||
|
h2 := newBlockWithState(bc.config, 2, h1.Hash(), nil).Header
|
||||||
|
require.NoError(t, bc.AddHeaders(&h2))
|
||||||
|
}
|
||||||
|
|
||||||
func TestAddBadBlock(t *testing.T) {
|
func TestAddBadBlock(t *testing.T) {
|
||||||
bc := newTestChain(t)
|
bc := newTestChain(t)
|
||||||
// It has ValidUntilBlock == 0, which is wrong
|
// It has ValidUntilBlock == 0, which is wrong
|
||||||
|
|
|
@ -70,6 +70,11 @@ func (s *Module) CurrentLocalStateRoot() util.Uint256 {
|
||||||
return s.currentLocal.Load().(util.Uint256)
|
return s.currentLocal.Load().(util.Uint256)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CurrentLocalHeight returns height of the local state root.
|
||||||
|
func (s *Module) CurrentLocalHeight() uint32 {
|
||||||
|
return s.localHeight.Load()
|
||||||
|
}
|
||||||
|
|
||||||
// CurrentValidatedHeight returns current state root validated height.
|
// CurrentValidatedHeight returns current state root validated height.
|
||||||
func (s *Module) CurrentValidatedHeight() uint32 {
|
func (s *Module) CurrentValidatedHeight() uint32 {
|
||||||
return s.validatedHeight.Load()
|
return s.validatedHeight.Load()
|
||||||
|
|
Loading…
Reference in a new issue