From 8d9114d84151a5393ec77ba2c9c42090ff12a341 Mon Sep 17 00:00:00 2001 From: Laurentiu Ciobanu Date: Mon, 29 Jul 2024 14:03:53 +0000 Subject: [PATCH] deep copy header when returning from trigger --- .../disabled/disabledEpochStartTrigger.go | 6 ++-- epochStart/interface.go | 2 +- epochStart/metachain/trigger.go | 22 +++++++++++--- epochStart/shardchain/trigger.go | 19 +++++++++--- factory/mock/epochStartTriggerStub.go | 8 ++--- factory/processing/blockProcessorCreator.go | 2 +- .../mock/endOfEpochTriggerStub.go | 8 ++--- node/mock/endOfEpochTriggerStub.go | 8 ++--- process/interface.go | 2 +- process/mock/endOfEpochTriggerStub.go | 8 ++--- process/smartContract/hooks/blockChainHook.go | 30 ++++++++++++++----- process/smartContract/hooks/errors.go | 3 ++ process/smartContract/hooks/interface.go | 2 +- testscommon/epochStartTriggerStub.go | 8 ++--- 14 files changed, 86 insertions(+), 42 deletions(-) diff --git a/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go b/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go index 4042e35ed36..9eb293e910f 100644 --- a/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go +++ b/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go @@ -54,9 +54,9 @@ func (e *epochStartTrigger) EpochStartMetaHdrHash() []byte { return nil } -// EpochStartHdr - -func (e *epochStartTrigger) EpochStartHdr() data.HeaderHandler { - return nil +// LastCommitedEpochStartHdr - +func (e *epochStartTrigger) LastCommitedEpochStartHdr() (data.HeaderHandler, error) { + return nil, nil } // GetSavedStateKey - diff --git a/epochStart/interface.go b/epochStart/interface.go index 274fe0ca336..c08a8ab06e6 100644 --- a/epochStart/interface.go +++ b/epochStart/interface.go @@ -22,7 +22,7 @@ type TriggerHandler interface { Update(round uint64, nonce uint64) EpochStartRound() uint64 EpochStartMetaHdrHash() []byte - EpochStartHdr() data.HeaderHandler + LastCommitedEpochStartHdr() (data.HeaderHandler, error) GetSavedStateKey() []byte LoadState(key []byte) error SetProcessed(header data.HeaderHandler, body data.BodyHandler) diff --git a/epochStart/metachain/trigger.go b/epochStart/metachain/trigger.go index 95e96fd78ec..a39f4f94e24 100644 --- a/epochStart/metachain/trigger.go +++ b/epochStart/metachain/trigger.go @@ -21,7 +21,7 @@ import ( "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/storage" - "github.com/multiversx/mx-chain-logger-go" + logger "github.com/multiversx/mx-chain-logger-go" ) var log = logger.GetOrCreate("epochStart/metachain") @@ -403,9 +403,23 @@ func (t *trigger) EpochStartMetaHdrHash() []byte { return t.epochStartMetaHash } -// EpochStartHdr returns the header of the epoch start block -func (t *trigger) EpochStartHdr() data.HeaderHandler { - return t.epochStartMeta +// LastCommitedEpochStartHdr returns the header of the epoch start block +func (t *trigger) LastCommitedEpochStartHdr() (data.HeaderHandler, error) { + t.mutTrigger.RLock() + defer t.mutTrigger.RUnlock() + + // marshal + unmarshal deep copy + headerBytes, err := t.marshaller.Marshal(t.epochStartMeta) + if err != nil { + return nil, err + } + + header, err := process.UnmarshalMetaHeader(t.marshaller, headerBytes) + if err != nil { + return nil, err + } + + return header, nil } // GetSavedStateKey returns the last saved trigger state key diff --git a/epochStart/shardchain/trigger.go b/epochStart/shardchain/trigger.go index cc098eced85..5f494b4444f 100644 --- a/epochStart/shardchain/trigger.go +++ b/epochStart/shardchain/trigger.go @@ -24,7 +24,7 @@ import ( "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/storage" - "github.com/multiversx/mx-chain-logger-go" + logger "github.com/multiversx/mx-chain-logger-go" ) var log = logger.GetOrCreate("epochStart/shardchain") @@ -1102,12 +1102,23 @@ func (t *trigger) EpochStartMetaHdrHash() []byte { return t.epochMetaBlockHash } -// EpochStartHdr returns the epoch start header -func (t *trigger) EpochStartHdr() data.HeaderHandler { +// LastCommitedEpochStartHdr returns the epoch start header +func (t *trigger) LastCommitedEpochStartHdr() (data.HeaderHandler, error) { t.mutTrigger.RLock() defer t.mutTrigger.RUnlock() - return t.epochStartShardHeader + // marshal + unmarshal deep copy + headerBytes, err := t.marshaller.Marshal(t.epochStartShardHeader) + if err != nil { + return nil, err + } + + header, err := process.UnmarshalShardHeader(t.marshaller, headerBytes) + if err != nil { + return nil, err + } + + return header, nil } // GetSavedStateKey returns the last saved trigger state key diff --git a/factory/mock/epochStartTriggerStub.go b/factory/mock/epochStartTriggerStub.go index e121fa4d11d..a151e0a17ea 100644 --- a/factory/mock/epochStartTriggerStub.go +++ b/factory/mock/epochStartTriggerStub.go @@ -50,13 +50,13 @@ func (e *EpochStartTriggerStub) EpochStartMetaHdrHash() []byte { return nil } -// EpochStartHdr - -func (e *EpochStartTriggerStub) EpochStartHdr() data.HeaderHandler { +// LastCommitedEpochStartHdr - +func (e *EpochStartTriggerStub) LastCommitedEpochStartHdr() (data.HeaderHandler, error) { if e.EpochStartHdrCalled != nil { - return e.EpochStartHdrCalled() + return e.EpochStartHdrCalled(), nil } - return nil + return nil, nil } // GetSavedStateKey - diff --git a/factory/processing/blockProcessorCreator.go b/factory/processing/blockProcessorCreator.go index d6f4f109e1b..cc8c6973781 100644 --- a/factory/processing/blockProcessorCreator.go +++ b/factory/processing/blockProcessorCreator.go @@ -1150,7 +1150,7 @@ func (pcf *processComponentsFactory) createVMFactoryMeta( Counter: counters.NewDisabledCounter(), MissingTrieNodesNotifier: syncer.NewMissingTrieNodesNotifier(), EpochStartTrigger: epochStartTriggerHandler, - RoundHandler: pcf.coreData.RoundHandler(), + RoundHandler: pcf.coreData.RoundHandler(), // TODO: @laurci - this needs to be replaced when changing the round duration } blockChainHookImpl, err := hooks.NewBlockChainHookImpl(argsHook) diff --git a/integrationTests/mock/endOfEpochTriggerStub.go b/integrationTests/mock/endOfEpochTriggerStub.go index 61d3bf8a37c..e2490e20ef9 100644 --- a/integrationTests/mock/endOfEpochTriggerStub.go +++ b/integrationTests/mock/endOfEpochTriggerStub.go @@ -50,12 +50,12 @@ func (e *EpochStartTriggerStub) EpochStartMetaHdrHash() []byte { return nil } -// EpochStartHdr - -func (e *EpochStartTriggerStub) EpochStartHdr() data.HeaderHandler { +// LastCommitedEpochStartHdr - +func (e *EpochStartTriggerStub) LastCommitedEpochStartHdr() (data.HeaderHandler, error) { if e.EpochStartHdrCalled != nil { - return e.EpochStartHdrCalled() + return e.EpochStartHdrCalled(), nil } - return nil + return nil, nil } // GetSavedStateKey - diff --git a/node/mock/endOfEpochTriggerStub.go b/node/mock/endOfEpochTriggerStub.go index 5ca23408b3c..3f9c198576b 100644 --- a/node/mock/endOfEpochTriggerStub.go +++ b/node/mock/endOfEpochTriggerStub.go @@ -59,13 +59,13 @@ func (e *EpochStartTriggerStub) EpochStartMetaHdrHash() []byte { return nil } -// EpochStartHdr - -func (e *EpochStartTriggerStub) EpochStartHdr() data.HeaderHandler { +// LastCommitedEpochStartHdr - +func (e *EpochStartTriggerStub) LastCommitedEpochStartHdr() (data.HeaderHandler, error) { if e.EpochStartHdrCalled != nil { - return e.EpochStartHdrCalled() + return e.EpochStartHdrCalled(), nil } - return nil + return nil, nil } // Revert - diff --git a/process/interface.go b/process/interface.go index d8d2dd1f63d..df38dbd7269 100644 --- a/process/interface.go +++ b/process/interface.go @@ -469,7 +469,7 @@ type EpochStartTriggerHandler interface { Epoch() uint32 MetaEpoch() uint32 EpochStartRound() uint64 - EpochStartHdr() data.HeaderHandler + LastCommitedEpochStartHdr() (data.HeaderHandler, error) SetProcessed(header data.HeaderHandler, body data.BodyHandler) RevertStateToBlock(header data.HeaderHandler) error EpochStartMetaHdrHash() []byte diff --git a/process/mock/endOfEpochTriggerStub.go b/process/mock/endOfEpochTriggerStub.go index 2f3866c7d00..df03c7f1268 100644 --- a/process/mock/endOfEpochTriggerStub.go +++ b/process/mock/endOfEpochTriggerStub.go @@ -84,12 +84,12 @@ func (e *EpochStartTriggerStub) EpochStartRound() uint64 { return 0 } -// ReceivedHeader - -func (e *EpochStartTriggerStub) EpochStartHdr() data.HeaderHandler { +// LastCommitedEpochStartHdr - +func (e *EpochStartTriggerStub) LastCommitedEpochStartHdr() (data.HeaderHandler, error) { if e.EpochStartHdrCalled != nil { - return e.EpochStartHdrCalled() + return e.EpochStartHdrCalled(), nil } - return nil + return nil, nil } // Update - diff --git a/process/smartContract/hooks/blockChainHook.go b/process/smartContract/hooks/blockChainHook.go index 15a2dfaefa7..a8db0c2cc49 100644 --- a/process/smartContract/hooks/blockChainHook.go +++ b/process/smartContract/hooks/blockChainHook.go @@ -65,7 +65,7 @@ type ArgBlockChainHook struct { Counter BlockChainHookCounter MissingTrieNodesNotifier common.MissingTrieNodesNotifier EpochStartTrigger EpochStartTriggerHandler - RoundHandler RoundHandler + RoundHandler RoundHandler // TODO: @laurci - this needs to be replaced when changing the round duration } // BlockChainHookImpl is a wrapper over AccountsAdapter that satisfy vmcommon.BlockchainHook interface @@ -84,7 +84,7 @@ type BlockChainHookImpl struct { enableEpochsHandler common.EnableEpochsHandler counter BlockChainHookCounter epochStartTrigger EpochStartTriggerHandler - roundHandler RoundHandler + roundHandler RoundHandler // TODO: @laurci - this needs to be replaced when changing the round duration mutCurrentHdr sync.RWMutex currentHdr data.HeaderHandler @@ -411,6 +411,7 @@ func (bh *BlockChainHookImpl) LastEpoch() uint32 { // RoundTime returns the duration of a round func (bh *BlockChainHookImpl) RoundTime() uint64 { + // TODO: @laurci - this needs to be replaced when changing the round duration roundDuration := bh.roundHandler.TimeDuration() return uint64(roundDuration.Milliseconds()) @@ -801,24 +802,39 @@ func (bh *BlockChainHookImpl) SetCurrentHeader(hdr data.HeaderHandler) { bh.mutCurrentHdr.Lock() bh.currentHdr = hdr - bh.updateEpochStartHeader(hdr) + err := bh.updateEpochStartHeader(hdr) + if err != nil { + log.Debug("BlockChainHookImpl.SetCurrentHeader: updateEpochStartHeader", "error", err) + } + bh.mutCurrentHdr.Unlock() } -func (bh *BlockChainHookImpl) updateEpochStartHeader(hdr data.HeaderHandler) { +func (bh *BlockChainHookImpl) updateEpochStartHeader(hdr data.HeaderHandler) error { bh.mutEpochStartHdr.Lock() defer bh.mutEpochStartHdr.Unlock() if hdr.IsStartOfEpochBlock() { bh.epochStartHdr = hdr - return + return nil } if bh.epochStartHdr.GetEpoch() == hdr.GetEpoch() { - return + return nil } - bh.epochStartHdr = bh.epochStartTrigger.EpochStartHdr() + epochStartHdr, err := bh.epochStartTrigger.LastCommitedEpochStartHdr() + if err != nil { + return err + } + + if epochStartHdr.GetEpoch() != hdr.GetEpoch() { + return ErrLastCommitedEpochStartHdrMismatch + } + + bh.epochStartHdr = epochStartHdr + + return nil } // SaveCompiledCode saves the compiled code to cache and storage diff --git a/process/smartContract/hooks/errors.go b/process/smartContract/hooks/errors.go index bc20d58ea3f..73c8a2072da 100644 --- a/process/smartContract/hooks/errors.go +++ b/process/smartContract/hooks/errors.go @@ -25,3 +25,6 @@ var ErrNilEpochStartTriggerHandler = errors.New("nil epoch start trigger handler // ErrNilRoundHandler signals that a nil round handler was provided var ErrNilRoundHandler = errors.New("nil round handler") + +// ErrLastCommitedEpochStartHdrMismatch signals that the current header epoch and last commited epoch start header epoch do not match +var ErrLastCommitedEpochStartHdrMismatch = errors.New("current header epoch and last commited epoch start header epoch do not match") diff --git a/process/smartContract/hooks/interface.go b/process/smartContract/hooks/interface.go index 090b132af69..53038df7997 100644 --- a/process/smartContract/hooks/interface.go +++ b/process/smartContract/hooks/interface.go @@ -19,7 +19,7 @@ type BlockChainHookCounter interface { // EpochStartTriggerHandler defines the operations of an epoch start trigger handler needed by the blockchain hook type EpochStartTriggerHandler interface { - EpochStartHdr() data.HeaderHandler + LastCommitedEpochStartHdr() (data.HeaderHandler, error) IsInterfaceNil() bool } diff --git a/testscommon/epochStartTriggerStub.go b/testscommon/epochStartTriggerStub.go index ec64e5377fb..87493a51b3b 100644 --- a/testscommon/epochStartTriggerStub.go +++ b/testscommon/epochStartTriggerStub.go @@ -57,12 +57,12 @@ func (e *EpochStartTriggerStub) EpochStartMetaHdrHash() []byte { return nil } -// EpochStartHdr - -func (e *EpochStartTriggerStub) EpochStartHdr() data.HeaderHandler { +// LastCommitedEpochStartHdr - +func (e *EpochStartTriggerStub) LastCommitedEpochStartHdr() (data.HeaderHandler, error) { if e.EpochStartHdrCalled != nil { - return e.EpochStartHdrCalled() + return e.EpochStartHdrCalled(), nil } - return nil + return nil, nil } // GetSavedStateKey -