github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/eth/catalyst/queue.go (about)

     1  // Copyright 2022 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package catalyst
    18  
    19  import (
    20  	"sync"
    21  
    22  	"github.com/ethereum/go-ethereum/common"
    23  	"github.com/ethereum/go-ethereum/core/beacon"
    24  	"github.com/ethereum/go-ethereum/core/types"
    25  )
    26  
    27  // maxTrackedPayloads is the maximum number of prepared payloads the execution
    28  // engine tracks before evicting old ones. Ideally we should only ever track the
    29  // latest one; but have a slight wiggle room for non-ideal conditions.
    30  const maxTrackedPayloads = 10
    31  
    32  // maxTrackedHeaders is the maximum number of executed payloads the execution
    33  // engine tracks before evicting old ones. Ideally we should only ever track the
    34  // latest one; but have a slight wiggle room for non-ideal conditions.
    35  const maxTrackedHeaders = 10
    36  
    37  // payloadQueueItem represents an id->payload tuple to store until it's retrieved
    38  // or evicted.
    39  type payloadQueueItem struct {
    40  	id      beacon.PayloadID
    41  	payload *beacon.ExecutableDataV1
    42  }
    43  
    44  // payloadQueue tracks the latest handful of constructed payloads to be retrieved
    45  // by the beacon chain if block production is requested.
    46  type payloadQueue struct {
    47  	payloads []*payloadQueueItem
    48  	lock     sync.RWMutex
    49  }
    50  
    51  // newPayloadQueue creates a pre-initialized queue with a fixed number of slots
    52  // all containing empty items.
    53  func newPayloadQueue() *payloadQueue {
    54  	return &payloadQueue{
    55  		payloads: make([]*payloadQueueItem, maxTrackedPayloads),
    56  	}
    57  }
    58  
    59  // put inserts a new payload into the queue at the given id.
    60  func (q *payloadQueue) put(id beacon.PayloadID, data *beacon.ExecutableDataV1) {
    61  	q.lock.Lock()
    62  	defer q.lock.Unlock()
    63  
    64  	copy(q.payloads[1:], q.payloads)
    65  	q.payloads[0] = &payloadQueueItem{
    66  		id:      id,
    67  		payload: data,
    68  	}
    69  }
    70  
    71  // get retrieves a previously stored payload item or nil if it does not exist.
    72  func (q *payloadQueue) get(id beacon.PayloadID) *beacon.ExecutableDataV1 {
    73  	q.lock.RLock()
    74  	defer q.lock.RUnlock()
    75  
    76  	for _, item := range q.payloads {
    77  		if item == nil {
    78  			return nil // no more items
    79  		}
    80  		if item.id == id {
    81  			return item.payload
    82  		}
    83  	}
    84  	return nil
    85  }
    86  
    87  // headerQueueItem represents an hash->header tuple to store until it's retrieved
    88  // or evicted.
    89  type headerQueueItem struct {
    90  	hash   common.Hash
    91  	header *types.Header
    92  }
    93  
    94  // headerQueue tracks the latest handful of constructed headers to be retrieved
    95  // by the beacon chain if block production is requested.
    96  type headerQueue struct {
    97  	headers []*headerQueueItem
    98  	lock    sync.RWMutex
    99  }
   100  
   101  // newHeaderQueue creates a pre-initialized queue with a fixed number of slots
   102  // all containing empty items.
   103  func newHeaderQueue() *headerQueue {
   104  	return &headerQueue{
   105  		headers: make([]*headerQueueItem, maxTrackedHeaders),
   106  	}
   107  }
   108  
   109  // put inserts a new header into the queue at the given hash.
   110  func (q *headerQueue) put(hash common.Hash, data *types.Header) {
   111  	q.lock.Lock()
   112  	defer q.lock.Unlock()
   113  
   114  	copy(q.headers[1:], q.headers)
   115  	q.headers[0] = &headerQueueItem{
   116  		hash:   hash,
   117  		header: data,
   118  	}
   119  }
   120  
   121  // get retrieves a previously stored header item or nil if it does not exist.
   122  func (q *headerQueue) get(hash common.Hash) *types.Header {
   123  	q.lock.RLock()
   124  	defer q.lock.RUnlock()
   125  
   126  	for _, item := range q.headers {
   127  		if item == nil {
   128  			return nil // no more items
   129  		}
   130  		if item.hash == hash {
   131  			return item.header
   132  		}
   133  	}
   134  	return nil
   135  }