github.com/tirogen/go-ethereum@v1.10.12-0.20221226051715-250cfede41b6/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/tirogen/go-ethereum/common"
    23  	"github.com/tirogen/go-ethereum/core/beacon"
    24  	"github.com/tirogen/go-ethereum/core/types"
    25  	"github.com/tirogen/go-ethereum/miner"
    26  )
    27  
    28  // maxTrackedPayloads is the maximum number of prepared payloads the execution
    29  // engine tracks before evicting old ones. Ideally we should only ever track the
    30  // latest one; but have a slight wiggle room for non-ideal conditions.
    31  const maxTrackedPayloads = 10
    32  
    33  // maxTrackedHeaders is the maximum number of executed payloads the execution
    34  // engine tracks before evicting old ones. Ideally we should only ever track the
    35  // latest one; but have a slight wiggle room for non-ideal conditions.
    36  const maxTrackedHeaders = 10
    37  
    38  // payloadQueueItem represents an id->payload tuple to store until it's retrieved
    39  // or evicted.
    40  type payloadQueueItem struct {
    41  	id      beacon.PayloadID
    42  	payload *miner.Payload
    43  }
    44  
    45  // payloadQueue tracks the latest handful of constructed payloads to be retrieved
    46  // by the beacon chain if block production is requested.
    47  type payloadQueue struct {
    48  	payloads []*payloadQueueItem
    49  	lock     sync.RWMutex
    50  }
    51  
    52  // newPayloadQueue creates a pre-initialized queue with a fixed number of slots
    53  // all containing empty items.
    54  func newPayloadQueue() *payloadQueue {
    55  	return &payloadQueue{
    56  		payloads: make([]*payloadQueueItem, maxTrackedPayloads),
    57  	}
    58  }
    59  
    60  // put inserts a new payload into the queue at the given id.
    61  func (q *payloadQueue) put(id beacon.PayloadID, payload *miner.Payload) {
    62  	q.lock.Lock()
    63  	defer q.lock.Unlock()
    64  
    65  	copy(q.payloads[1:], q.payloads)
    66  	q.payloads[0] = &payloadQueueItem{
    67  		id:      id,
    68  		payload: payload,
    69  	}
    70  }
    71  
    72  // get retrieves a previously stored payload item or nil if it does not exist.
    73  func (q *payloadQueue) get(id beacon.PayloadID) *beacon.ExecutableDataV1 {
    74  	q.lock.RLock()
    75  	defer q.lock.RUnlock()
    76  
    77  	for _, item := range q.payloads {
    78  		if item == nil {
    79  			return nil // no more items
    80  		}
    81  		if item.id == id {
    82  			return item.payload.Resolve()
    83  		}
    84  	}
    85  	return nil
    86  }
    87  
    88  // has checks if a particular payload is already tracked.
    89  func (q *payloadQueue) has(id beacon.PayloadID) bool {
    90  	q.lock.RLock()
    91  	defer q.lock.RUnlock()
    92  
    93  	for _, item := range q.payloads {
    94  		if item == nil {
    95  			return false
    96  		}
    97  		if item.id == id {
    98  			return true
    99  		}
   100  	}
   101  	return false
   102  }
   103  
   104  // headerQueueItem represents an hash->header tuple to store until it's retrieved
   105  // or evicted.
   106  type headerQueueItem struct {
   107  	hash   common.Hash
   108  	header *types.Header
   109  }
   110  
   111  // headerQueue tracks the latest handful of constructed headers to be retrieved
   112  // by the beacon chain if block production is requested.
   113  type headerQueue struct {
   114  	headers []*headerQueueItem
   115  	lock    sync.RWMutex
   116  }
   117  
   118  // newHeaderQueue creates a pre-initialized queue with a fixed number of slots
   119  // all containing empty items.
   120  func newHeaderQueue() *headerQueue {
   121  	return &headerQueue{
   122  		headers: make([]*headerQueueItem, maxTrackedHeaders),
   123  	}
   124  }
   125  
   126  // put inserts a new header into the queue at the given hash.
   127  func (q *headerQueue) put(hash common.Hash, data *types.Header) {
   128  	q.lock.Lock()
   129  	defer q.lock.Unlock()
   130  
   131  	copy(q.headers[1:], q.headers)
   132  	q.headers[0] = &headerQueueItem{
   133  		hash:   hash,
   134  		header: data,
   135  	}
   136  }
   137  
   138  // get retrieves a previously stored header item or nil if it does not exist.
   139  func (q *headerQueue) get(hash common.Hash) *types.Header {
   140  	q.lock.RLock()
   141  	defer q.lock.RUnlock()
   142  
   143  	for _, item := range q.headers {
   144  		if item == nil {
   145  			return nil // no more items
   146  		}
   147  		if item.hash == hash {
   148  			return item.header
   149  		}
   150  	}
   151  	return nil
   152  }