@@ -209,6 +209,9 @@ type SubtreeProcessor struct {
209209 // currentSubtree represents the subtree currently being built
210210 currentSubtree * subtreepkg.Subtree
211211
212+ // currentSubtreeMu protects currentSubtree pointer from concurrent read/write access
213+ currentSubtreeMu sync.RWMutex
214+
212215 // currentBlockHeader stores the current block header being processed
213216 currentBlockHeader * model.BlockHeader
214217
@@ -567,7 +570,7 @@ func (stp *SubtreeProcessor) Start(ctx context.Context) {
567570 if _ , err = stp .moveForwardBlock (processorCtx , moveForwardReq .block , false , processedConflictingHashesMap , false , true ); err != nil {
568571 // rollback to previous state
569572 stp .chainedSubtrees = originalChainedSubtrees
570- stp .currentSubtree = originalCurrentSubtree
573+ stp .setCurrentSubtree ( originalCurrentSubtree )
571574 stp .currentTxMap = originalCurrentTxMap
572575 stp .currentBlockHeader = currentBlockHeader
573576
@@ -827,7 +830,8 @@ func (stp *SubtreeProcessor) reset(blockHeader *model.BlockHeader, moveBackBlock
827830 stp .chainedSubtrees = make ([]* subtreepkg.Subtree , 0 , ExpectedNumberOfSubtrees )
828831 stp .chainedSubtreeCount .Store (0 )
829832
830- stp .currentSubtree , _ = subtreepkg .NewTreeByLeafCount (stp .currentItemsPerFile )
833+ newSubtree , _ := subtreepkg .NewTreeByLeafCount (stp .currentItemsPerFile )
834+ stp .setCurrentSubtree (newSubtree )
831835 if err := stp .currentSubtree .AddCoinbaseNode (); err != nil {
832836 return errors .NewProcessingError ("[SubtreeProcessor][Reset] error adding coinbase placeholder to new current subtree" , err )
833837 }
@@ -1041,11 +1045,22 @@ func (stp *SubtreeProcessor) SetCurrentBlockHeader(blockHeader *model.BlockHeade
10411045 stp .currentBlockHeader = blockHeader
10421046}
10431047
1048+ // setCurrentSubtree safely updates the currentSubtree pointer with write lock protection.
1049+ // This is used internally to prevent data races when external callers read via GetCurrentSubtree().
1050+ func (stp * SubtreeProcessor ) setCurrentSubtree (st * subtreepkg.Subtree ) {
1051+ stp .currentSubtreeMu .Lock ()
1052+ stp .currentSubtree = st
1053+ stp .currentSubtreeMu .Unlock ()
1054+ }
1055+
10441056// GetCurrentSubtree returns the subtree currently being built.
1057+ // This method is safe for concurrent access from external callers.
10451058//
10461059// Returns:
10471060// - *util.Subtree: Current subtree
10481061func (stp * SubtreeProcessor ) GetCurrentSubtree () * subtreepkg.Subtree {
1062+ stp .currentSubtreeMu .RLock ()
1063+ defer stp .currentSubtreeMu .RUnlock ()
10491064 return stp .currentSubtree
10501065}
10511066
@@ -1349,10 +1364,11 @@ func (stp *SubtreeProcessor) addNode(node subtreepkg.Node, parents *subtreepkg.T
13491364 }
13501365
13511366 if stp .currentSubtree == nil {
1352- stp . currentSubtree , err = subtreepkg .NewTreeByLeafCount (stp .currentItemsPerFile )
1367+ newSubtree , err : = subtreepkg .NewTreeByLeafCount (stp .currentItemsPerFile )
13531368 if err != nil {
13541369 return err
13551370 }
1371+ stp .setCurrentSubtree (newSubtree )
13561372
13571373 // This is the first subtree for this block - we need a coinbase placeholder
13581374 err = stp .currentSubtree .AddCoinbaseNode ()
@@ -1404,10 +1420,11 @@ func (stp *SubtreeProcessor) processCompleteSubtree(skipNotification bool) (err
14041420 oldSubtreeHash := oldSubtree .RootHash ()
14051421
14061422 // create a new subtree with the same height as the previous subtree
1407- stp . currentSubtree , err = subtreepkg .NewTree (stp . currentSubtree .Height )
1423+ newSubtree , err : = subtreepkg .NewTree (oldSubtree .Height )
14081424 if err != nil {
14091425 return errors .NewProcessingError ("[%s] error creating new subtree" , oldSubtreeHash .String (), err )
14101426 }
1427+ stp .setCurrentSubtree (newSubtree )
14111428
14121429 // Send the subtree to the newSubtreeChan, including a reference to the parent transactions map
14131430 errCh := make (chan error )
@@ -1637,10 +1654,11 @@ func (stp *SubtreeProcessor) reChainSubtrees(fromIndex int) error {
16371654
16381655 stp .chainedSubtreeCount .Store (fromIndexInt32 )
16391656
1640- stp . currentSubtree , err = subtreepkg .NewTreeByLeafCount (stp .currentItemsPerFile )
1657+ newSubtree , err : = subtreepkg .NewTreeByLeafCount (stp .currentItemsPerFile )
16411658 if err != nil {
16421659 return errors .NewProcessingError ("error creating new current subtree" , err )
16431660 }
1661+ stp .setCurrentSubtree (newSubtree )
16441662
16451663 if len (originalSubtrees ) == 0 {
16461664 // we must add the coinbase tx if we have no original subtrees
@@ -1888,7 +1906,7 @@ func (stp *SubtreeProcessor) reorgBlocks(ctx context.Context, moveBackBlocks []*
18881906 if err != nil {
18891907 // restore the original state
18901908 stp .chainedSubtrees = originalChainedSubtrees
1891- stp .currentSubtree = originalCurrentSubtree
1909+ stp .setCurrentSubtree ( originalCurrentSubtree )
18921910 stp .currentTxMap = originalCurrentTxMap
18931911 stp .currentBlockHeader = currentBlockHeader
18941912
@@ -2308,10 +2326,11 @@ func (stp *SubtreeProcessor) moveBackBlockCreateNewSubtrees(ctx context.Context,
23082326 // we create as few subtrees as possible when moving back, to avoid fragmentation and lots of small writes to disk
23092327 subtreeSize = 1024 * 1024
23102328 }
2311- stp . currentSubtree , err = subtreepkg .NewTreeByLeafCount (subtreeSize )
2329+ newSubtree , err : = subtreepkg .NewTreeByLeafCount (subtreeSize )
23122330 if err != nil {
23132331 return nil , nil , errors .NewProcessingError ("[moveBackBlock:CreateNewSubtrees][%s] error creating new subtree" , block .String (), err )
23142332 }
2333+ stp .setCurrentSubtree (newSubtree )
23152334
23162335 stp .chainedSubtrees = make ([]* subtreepkg.Subtree , 0 , ExpectedNumberOfSubtrees )
23172336 stp .chainedSubtreeCount .Store (0 )
@@ -2576,10 +2595,11 @@ func (stp *SubtreeProcessor) resetSubtreeState(createProperlySizedSubtrees bool)
25762595 subtreeSize = 1024 * 1024
25772596 }
25782597
2579- stp . currentSubtree , err = subtreepkg .NewTreeByLeafCount (subtreeSize )
2598+ newSubtree , err : = subtreepkg .NewTreeByLeafCount (subtreeSize )
25802599 if err != nil {
25812600 return err
25822601 }
2602+ stp .setCurrentSubtree (newSubtree )
25832603
25842604 stp .chainedSubtrees = make ([]* subtreepkg.Subtree , 0 , ExpectedNumberOfSubtrees )
25852605 stp .chainedSubtreeCount .Store (0 )
0 commit comments