Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion consensus/spos/bls/v2/subroundBlock.go
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,7 @@ func (sr *subroundBlock) processBlock(
return false
}

if !sr.GetHeader().IsHeaderV3() {
if !check.IfNil(sr.GetHeader()) && !sr.GetHeader().IsHeaderV3() {
sr.ConsensusCoreHandler.ScheduledProcessor().StartScheduledProcessing(sr.GetHeader(), sr.GetBody(), sr.GetRoundTimeStamp())
}

Expand Down
4 changes: 4 additions & 0 deletions epochStart/bootstrap/disabled/disabledAccountsAdapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ func (a *accountsAdapter) RecreateTrieIfNeeded(_ common.RootHashHolder) error {
func (a *accountsAdapter) CancelPrune(_ []byte, _ state.TriePruningIdentifier) {
}

// ResetPruning -
func (a *accountsAdapter) ResetPruning() {
}

// SnapshotState -
func (a *accountsAdapter) SnapshotState(_ []byte, _ uint32) {
}
Expand Down
8 changes: 8 additions & 0 deletions integrationTests/mock/blockProcessorMock.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type BlockProcessorMock struct {
) error
OnExecutedBlockCalled func(header data.HeaderHandler, rootHash []byte) error
ProposedDirectSentTransactionsToBroadcastCalled func(proposedBody data.BodyHandler) map[string][][]byte
PruneTrieAsyncHeaderCalled func()
}

// ProcessBlock mocks processing a block
Expand Down Expand Up @@ -231,6 +232,13 @@ func (bpm *BlockProcessorMock) RemoveHeaderFromPool(headerHash []byte) {
}
}

// PruneTrieAsyncHeader -
func (bpm *BlockProcessorMock) PruneTrieAsyncHeader() {
if bpm.PruneTrieAsyncHeaderCalled != nil {
bpm.PruneTrieAsyncHeaderCalled()
}
}

// VerifyBlockProposal -
func (bpm *BlockProcessorMock) VerifyBlockProposal(
headerHandler data.HeaderHandler,
Expand Down
2 changes: 2 additions & 0 deletions process/asyncExecution/headersExecutor.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ func (he *headersExecutor) process(pair cache.HeaderBodyPair) error {
return nil
}

he.blockProcessor.PruneTrieAsyncHeader()

he.blockChain.SetFinalBlockInfo(
executionResult.GetHeaderNonce(),
executionResult.GetHeaderHash(),
Expand Down
1 change: 1 addition & 0 deletions process/asyncExecution/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ type BlockProcessor interface {
ProcessBlockProposal(header data.HeaderHandler, headerHash []byte, body data.BodyHandler) (data.BaseExecutionResultHandler, error)
CommitBlockProposalState(headerHandler data.HeaderHandler) error
RevertBlockProposalState()
PruneTrieAsyncHeader()
IsInterfaceNil() bool
}
81 changes: 81 additions & 0 deletions process/block/baseProcess.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ type baseProcessor struct {
aotSelector process.AOTTransactionSelector
maxProposalNonceGap uint64
closingNodeStarted *atomic.Bool

lastPrunedHeaderHash []byte
lastPrunedHeaderNonce uint64
mutLastPrunedHeader sync.RWMutex
}

type bootStorerDataArgs struct {
Expand Down Expand Up @@ -4032,3 +4036,80 @@ func (bp *baseProcessor) saveEpochStartEconomicsMetrics(epochStartMetaBlock data
bp.appStatusHandler.SetStringValue(common.MetricTotalFees, epochStartMetaBlock.GetAccumulatedFeesInEpoch().String())
bp.appStatusHandler.SetStringValue(common.MetricDevRewardsInEpoch, epochStartMetaBlock.GetDevFeesInEpoch().String())
}

// PruneTrieAsyncHeader will trigger trie pruning for header from async execution flow
func (bp *baseProcessor) PruneTrieAsyncHeader() {
bp.mutLastPrunedHeader.Lock()
defer bp.mutLastPrunedHeader.Unlock()

header := bp.blockChain.GetCurrentBlockHeader()
headerHash := bp.blockChain.GetCurrentBlockHeaderHash()

if len(bp.lastPrunedHeaderHash) == 0 {
// last pruned header hash not set, trigger prune trie for the provided header
bp.blockProcessor.pruneTrieHeaderV3(header)
bp.lastPrunedHeaderHash = headerHash
bp.lastPrunedHeaderNonce = header.GetNonce()
return
}

// extra check by nonce
if header.GetNonce() <= bp.lastPrunedHeaderNonce {
return
}

err := bp.pruneTrieForHeadersUnprotected(headerHash, header)
if err != nil {
// there was an error while fetching intermediate headers
// reset pruning context
bp.blockProcessor.resetPruning()
}

bp.lastPrunedHeaderHash = headerHash
bp.lastPrunedHeaderNonce = header.GetNonce()
}

func (bp *baseProcessor) pruneTrieForHeadersUnprotected(
headerHash []byte,
header data.HeaderHandler,
) error {
if bytes.Equal(headerHash, bp.lastPrunedHeaderHash) {
return nil
}

headersToPrune := make([]data.HeaderHandler, 0)
headersToPrune = append(headersToPrune, header)

lastPrunedHeaderHash := bp.lastPrunedHeaderHash
walkerHash := header.GetPrevHash()

for !bytes.Equal(walkerHash, lastPrunedHeaderHash) {
// headers pool is cleaned on consensus flow based on last execution result
// included on the committed header (plus some delta), so intermediate headers
// should be available in pool, since trie pruning is triggered from
// execution flow; if there are no included blocks from execution flow
// (and not pruning triggered) headers will not be removed from pool
header, err := process.GetHeader(
walkerHash,
bp.dataPool.Headers(),
bp.store,
bp.marshalizer,
header.GetShardID(),
)
if err != nil {
log.Warn("failed to get intermediate header for pruning", "error", err)
return err
}

headersToPrune = append(headersToPrune, header)

walkerHash = header.GetPrevHash()
}

for i := len(headersToPrune) - 1; i >= 0; i-- {
header := headersToPrune[i]
bp.blockProcessor.pruneTrieHeaderV3(header)
}

return nil
}
Loading
Loading