diff --git a/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go b/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go index 14cdef4be32..63465de8491 100644 --- a/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go +++ b/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go @@ -26,6 +26,11 @@ func (e *epochStartTrigger) ShouldProposeEpochChange(_ uint64, _ uint64) bool { func (e *epochStartTrigger) SetEpochChangeProposed(_ bool) { } +// GetEpochChangeProposed - +func (e *epochStartTrigger) GetEpochChangeProposed() bool { + return false +} + // SetEpochChange - func (e *epochStartTrigger) SetEpochChange(_ uint64) {} diff --git a/epochStart/interface.go b/epochStart/interface.go index 400ab104017..cc3d6ac1d40 100644 --- a/epochStart/interface.go +++ b/epochStart/interface.go @@ -7,9 +7,10 @@ import ( "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/state" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" ) // TriggerHandler defines the functionalities for an start of epoch trigger @@ -23,6 +24,7 @@ type TriggerHandler interface { SetEpochChange(round uint64) ShouldProposeEpochChange(round uint64, nonce uint64) bool SetEpochChangeProposed(value bool) + GetEpochChangeProposed() bool EpochStartRound() uint64 EpochStartMetaHdrHash() []byte LastCommitedEpochStartHdr() (data.HeaderHandler, error) diff --git a/epochStart/metachain/trigger.go b/epochStart/metachain/trigger.go index 2382b00e64a..a880d16d8fb 100644 --- a/epochStart/metachain/trigger.go +++ b/epochStart/metachain/trigger.go @@ -243,6 +243,13 @@ func (t *trigger) SetEpochChangeProposed(value bool) { t.epochChangeProposed = value } +// GetEpochChangeProposed returns the epoch change proposed flag +func (t *trigger) GetEpochChangeProposed() bool { + t.mutTrigger.RLock() + defer t.mutTrigger.RUnlock() + return t.epochChangeProposed +} + func (t *trigger) shouldTriggerEpochStart(currentRound uint64, currentNonce uint64) bool { isZeroEpochEdgeCase := currentNonce < minimumNonceToStartEpoch isNormalEpochStart := currentRound > t.currEpochStartRound+t.getRoundsPerEpoch(t.epoch)-t.getOffsetPerEpoch(t.epoch) diff --git a/epochStart/shardchain/trigger.go b/epochStart/shardchain/trigger.go index b9192ad2df9..6212769402e 100644 --- a/epochStart/shardchain/trigger.go +++ b/epochStart/shardchain/trigger.go @@ -1246,6 +1246,11 @@ func (t *trigger) SetEpochChangeProposed(_ bool) { // no implementation needed } +// GetEpochChangeProposed will always return false +func (t *trigger) GetEpochChangeProposed() bool { + return false +} + // SetFinalityAttestingRound sets the round which finalized the start of epoch block func (t *trigger) SetFinalityAttestingRound(_ uint64) { } diff --git a/factory/mock/epochStartTriggerStub.go b/factory/mock/epochStartTriggerStub.go index c3a6c050c70..15e9cd7f002 100644 --- a/factory/mock/epochStartTriggerStub.go +++ b/factory/mock/epochStartTriggerStub.go @@ -23,6 +23,7 @@ type EpochStartTriggerStub struct { ShouldProposeEpochChangeCalled func(round uint64, nonce uint64) bool SetEpochChangeCalled func(round uint64) SetEpochChangeProposedCalled func(value bool) + GetEpochChangeProposedCalled func() bool } // SetEpochChange - @@ -48,6 +49,15 @@ func (e *EpochStartTriggerStub) SetEpochChangeProposed(value bool) { } } +// GetEpochChangeProposed - +func (e *EpochStartTriggerStub) GetEpochChangeProposed() bool { + if e.GetEpochChangeProposedCalled != nil { + return e.GetEpochChangeProposedCalled() + } + + return false +} + // RevertStateToBlock - func (e *EpochStartTriggerStub) RevertStateToBlock(_ data.HeaderHandler) error { return nil diff --git a/integrationTests/mock/endOfEpochTriggerStub.go b/integrationTests/mock/endOfEpochTriggerStub.go index eeb54716e0a..fce663469ea 100644 --- a/integrationTests/mock/endOfEpochTriggerStub.go +++ b/integrationTests/mock/endOfEpochTriggerStub.go @@ -23,6 +23,7 @@ type EpochStartTriggerStub struct { ShouldProposeEpochChangeCalled func(round uint64, nonce uint64) bool SetEpochChangeCalled func(round uint64) SetEpochChangeProposedCalled func(value bool) + GetEpochChangeProposedCalled func() bool } // SetEpochChange - @@ -48,6 +49,15 @@ func (e *EpochStartTriggerStub) SetEpochChangeProposed(value bool) { } } +// GetEpochChangeProposed - +func (e *EpochStartTriggerStub) GetEpochChangeProposed() bool { + if e.GetEpochChangeProposedCalled != nil { + return e.GetEpochChangeProposedCalled() + } + + return false +} + // RevertStateToBlock - func (e *EpochStartTriggerStub) RevertStateToBlock(_ data.HeaderHandler) error { return nil diff --git a/node/mock/endOfEpochTriggerStub.go b/node/mock/endOfEpochTriggerStub.go index 987d74e8c5d..84a32f1f734 100644 --- a/node/mock/endOfEpochTriggerStub.go +++ b/node/mock/endOfEpochTriggerStub.go @@ -21,6 +21,7 @@ type EpochStartTriggerStub struct { ShouldProposeEpochChangeCalled func(round uint64, nonce uint64) bool SetEpochChangeCalled func(round uint64) SetEpochChangeProposedCalled func(value bool) + GetEpochChangeProposedCalled func() bool } // SetEpochChange - @@ -46,6 +47,15 @@ func (e *EpochStartTriggerStub) SetEpochChangeProposed(value bool) { } } +// GetEpochChangeProposed - +func (e *EpochStartTriggerStub) GetEpochChangeProposed() bool { + if e.GetEpochChangeProposedCalled != nil { + return e.GetEpochChangeProposedCalled() + } + + return false +} + // RevertStateToBlock - func (e *EpochStartTriggerStub) RevertStateToBlock(_ data.HeaderHandler) error { return nil diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index cbc667417cc..9b8b549f6c5 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -111,7 +111,7 @@ func (mp *metaProcessor) CreateBlockProposal( metaHdr.SoftwareVersion = []byte(mp.headerIntegrityVerifier.GetVersion(metaHdr.Epoch, metaHdr.Round)) - if metaHdr.IsStartOfEpochBlock() || metaHdr.GetEpochChangeProposed() || mp.epochStartTrigger.IsEpochStart() { + if metaHdr.IsStartOfEpochBlock() || metaHdr.GetEpochChangeProposed() || mp.epochStartTrigger.GetEpochChangeProposed() { // no new transactions in start of epoch block // to simplify bootstrapping return metaHdr, &block.Body{}, nil @@ -978,6 +978,11 @@ func (mp *metaProcessor) checkShardHeadersValidityAndFinalityProposal( return fmt.Errorf("%w : checkShardHeadersValidityAndFinalityProposal -> getShardHeadersFromMetaHeader", err) } + shouldNotHaveShardHeaders := metaHeaderHandler.IsStartOfEpochBlock() || metaHeaderHandler.IsEpochChangeProposed() || mp.epochStartTrigger.GetEpochChangeProposed() + if len(usedShardHeaders.orderedShardHeaders) > 0 && shouldNotHaveShardHeaders { + return fmt.Errorf("%w : between epoch change proposed and epoch start block", process.ErrShardHeadersShouldNotBeNotarized) + } + ok := mp.hasProofsForHeaders(usedShardHeaders.headersPerShard) if !ok { return process.ErrMissingHeaderProof diff --git a/process/block/metablockProposal_test.go b/process/block/metablockProposal_test.go index a5e37fac523..d1b6eb6cc64 100644 --- a/process/block/metablockProposal_test.go +++ b/process/block/metablockProposal_test.go @@ -649,7 +649,7 @@ func TestMetaProcessor_CreateBlockProposal(t *testing.T) { require.NotNil(t, header) require.NotNil(t, body) }) - t.Run("no mini blocks added if isEpochStart", func(t *testing.T) { + t.Run("no mini blocks added if epoch change propose set", func(t *testing.T) { t.Parallel() coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() @@ -661,7 +661,7 @@ func TestMetaProcessor_CreateBlockProposal(t *testing.T) { }, } arguments.EpochStartTrigger = &testscommon.EpochStartTriggerStub{ - IsEpochStartCalled: func() bool { + GetEpochChangeProposedCalled: func() bool { return true }, } @@ -1157,6 +1157,11 @@ func Test_checkShardHeadersValidityAndFinalityProposal(t *testing.T) { return nil, nil, expectedErr }, }, + "epochStartTrigger": &testscommon.EpochStartTriggerStub{ + GetEpochChangeProposedCalled: func() bool { + return false + }, + }, }) require.Nil(t, err) @@ -1189,6 +1194,11 @@ func Test_checkShardHeadersValidityAndFinalityProposal(t *testing.T) { return &testscommon.HeaderHandlerStub{}, nil, nil }, }, + "epochStartTrigger": &testscommon.EpochStartTriggerStub{ + GetEpochChangeProposedCalled: func() bool { + return false + }, + }, "dataPool": dataPoolMock, }) require.Nil(t, err) @@ -1242,6 +1252,11 @@ func Test_checkShardHeadersValidityAndFinalityProposal(t *testing.T) { return &testscommon.HeaderHandlerStub{}, nil, nil }, }, + "epochStartTrigger": &testscommon.EpochStartTriggerStub{ + GetEpochChangeProposedCalled: func() bool { + return false + }, + }, "dataPool": dataPoolMock, "proofsPool": proofsPool, "store": storage, @@ -1296,6 +1311,11 @@ func Test_checkShardHeadersValidityAndFinalityProposal(t *testing.T) { return &testscommon.HeaderHandlerStub{}, nil, nil }, }, + "epochStartTrigger": &testscommon.EpochStartTriggerStub{ + GetEpochChangeProposedCalled: func() bool { + return false + }, + }, "dataPool": dataPoolMock, "marshalizer": marshaller, "blockChain": &testscommon.ChainHandlerStub{ @@ -1336,6 +1356,11 @@ func Test_checkShardHeadersValidityAndFinalityProposal(t *testing.T) { return &testscommon.HeaderHandlerStub{}, nil, nil }, }, + "epochStartTrigger": &testscommon.EpochStartTriggerStub{ + GetEpochChangeProposedCalled: func() bool { + return false + }, + }, "dataPool": dataPoolMock, "marshalizer": &marshal.GogoProtoMarshalizer{}, "proofsPool": &dataRetrieverMock.ProofsPoolMock{ diff --git a/process/errors.go b/process/errors.go index 00fb6a7f60d..3fb2b476a82 100644 --- a/process/errors.go +++ b/process/errors.go @@ -1448,3 +1448,6 @@ var ErrNoReferencedHeader = errors.New("no referenced header") // ErrExecutionResultNotFound signals that the execution result was not found var ErrExecutionResultNotFound = errors.New("execution result not found") + +// ErrShardHeadersShouldNotBeNotarized signals that shard headers should not be notarized +var ErrShardHeadersShouldNotBeNotarized = errors.New("shard headers should not be notarized") diff --git a/process/interface.go b/process/interface.go index 768667fab40..d9309c16b17 100644 --- a/process/interface.go +++ b/process/interface.go @@ -554,6 +554,7 @@ type EpochStartTriggerHandler interface { SetEpochChange(round uint64) ShouldProposeEpochChange(round uint64, nonce uint64) bool SetEpochChangeProposed(value bool) + GetEpochChangeProposed() bool IsEpochStart() bool Epoch() uint32 MetaEpoch() uint32 diff --git a/process/mock/endOfEpochTriggerStub.go b/process/mock/endOfEpochTriggerStub.go index cc9063430f6..8f5810ea711 100644 --- a/process/mock/endOfEpochTriggerStub.go +++ b/process/mock/endOfEpochTriggerStub.go @@ -24,6 +24,7 @@ type EpochStartTriggerStub struct { ShouldProposeEpochChangeCalled func(round uint64, nonce uint64) bool SetEpochChangeCalled func(round uint64) SetEpochChangeProposedCalled func(value bool) + GetEpochChangeProposedCalled func() bool } func (e *EpochStartTriggerStub) SetEpochChangeProposed(value bool) { @@ -32,6 +33,14 @@ func (e *EpochStartTriggerStub) SetEpochChangeProposed(value bool) { } } +// GetEpochChangeProposed - +func (e *EpochStartTriggerStub) GetEpochChangeProposed() bool { + if e.GetEpochChangeProposedCalled != nil { + return e.GetEpochChangeProposedCalled() + } + return false +} + // SetEpochChange - func (e *EpochStartTriggerStub) SetEpochChange(round uint64) { if e.SetEpochChangeCalled != nil { diff --git a/testscommon/epochStartTriggerStub.go b/testscommon/epochStartTriggerStub.go index 23aa32dbf67..66f4d37ddea 100644 --- a/testscommon/epochStartTriggerStub.go +++ b/testscommon/epochStartTriggerStub.go @@ -23,6 +23,7 @@ type EpochStartTriggerStub struct { ShouldProposeEpochChangeCalled func(round uint64, nonce uint64) bool SetEpochChangeCalled func(round uint64) SetEpochChangeProposedCalled func(value bool) + GetEpochChangeProposedCalled func() bool } // SetEpochChange - @@ -119,6 +120,14 @@ func (e *EpochStartTriggerStub) SetEpochChangeProposed(value bool) { } } +// GetEpochChangeProposed - +func (e *EpochStartTriggerStub) GetEpochChangeProposed() bool { + if e.GetEpochChangeProposedCalled != nil { + return e.GetEpochChangeProposedCalled() + } + return false +} + // Update - func (e *EpochStartTriggerStub) Update(round uint64, nonce uint64) { if e.UpdateCalled != nil {