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 }