github.com/theQRL/go-zond@v0.1.1/zond/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/theQRL/go-zond/beacon/engine" 23 "github.com/theQRL/go-zond/common" 24 "github.com/theQRL/go-zond/core/types" 25 "github.com/theQRL/go-zond/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. These are tracked outside the chain 35 // during initial sync to allow ForkchoiceUpdate to reference past blocks via 36 // hashes only. For the sync target it would be enough to track only the latest 37 // header, but snap sync also needs the latest finalized height for the ancient 38 // limit. 39 const maxTrackedHeaders = 96 40 41 // payloadQueueItem represents an id->payload tuple to store until it's retrieved 42 // or evicted. 43 type payloadQueueItem struct { 44 id engine.PayloadID 45 payload *miner.Payload 46 } 47 48 // payloadQueue tracks the latest handful of constructed payloads to be retrieved 49 // by the beacon chain if block production is requested. 50 type payloadQueue struct { 51 payloads []*payloadQueueItem 52 lock sync.RWMutex 53 } 54 55 // newPayloadQueue creates a pre-initialized queue with a fixed number of slots 56 // all containing empty items. 57 func newPayloadQueue() *payloadQueue { 58 return &payloadQueue{ 59 payloads: make([]*payloadQueueItem, maxTrackedPayloads), 60 } 61 } 62 63 // put inserts a new payload into the queue at the given id. 64 func (q *payloadQueue) put(id engine.PayloadID, payload *miner.Payload) { 65 q.lock.Lock() 66 defer q.lock.Unlock() 67 68 copy(q.payloads[1:], q.payloads) 69 q.payloads[0] = &payloadQueueItem{ 70 id: id, 71 payload: payload, 72 } 73 } 74 75 // get retrieves a previously stored payload item or nil if it does not exist. 76 func (q *payloadQueue) get(id engine.PayloadID, full bool) *engine.ExecutionPayloadEnvelope { 77 q.lock.RLock() 78 defer q.lock.RUnlock() 79 80 for _, item := range q.payloads { 81 if item == nil { 82 return nil // no more items 83 } 84 if item.id == id { 85 if !full { 86 return item.payload.Resolve() 87 } 88 return item.payload.ResolveFull() 89 } 90 } 91 return nil 92 } 93 94 // has checks if a particular payload is already tracked. 95 func (q *payloadQueue) has(id engine.PayloadID) bool { 96 q.lock.RLock() 97 defer q.lock.RUnlock() 98 99 for _, item := range q.payloads { 100 if item == nil { 101 return false 102 } 103 if item.id == id { 104 return true 105 } 106 } 107 return false 108 } 109 110 // headerQueueItem represents an hash->header tuple to store until it's retrieved 111 // or evicted. 112 type headerQueueItem struct { 113 hash common.Hash 114 header *types.Header 115 } 116 117 // headerQueue tracks the latest handful of constructed headers to be retrieved 118 // by the beacon chain if block production is requested. 119 type headerQueue struct { 120 headers []*headerQueueItem 121 lock sync.RWMutex 122 } 123 124 // newHeaderQueue creates a pre-initialized queue with a fixed number of slots 125 // all containing empty items. 126 func newHeaderQueue() *headerQueue { 127 return &headerQueue{ 128 headers: make([]*headerQueueItem, maxTrackedHeaders), 129 } 130 } 131 132 // put inserts a new header into the queue at the given hash. 133 func (q *headerQueue) put(hash common.Hash, data *types.Header) { 134 q.lock.Lock() 135 defer q.lock.Unlock() 136 137 copy(q.headers[1:], q.headers) 138 q.headers[0] = &headerQueueItem{ 139 hash: hash, 140 header: data, 141 } 142 } 143 144 // get retrieves a previously stored header item or nil if it does not exist. 145 func (q *headerQueue) get(hash common.Hash) *types.Header { 146 q.lock.RLock() 147 defer q.lock.RUnlock() 148 149 for _, item := range q.headers { 150 if item == nil { 151 return nil // no more items 152 } 153 if item.hash == hash { 154 return item.header 155 } 156 } 157 return nil 158 }