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 }