github.com/theQRL/go-zond@v0.2.1/consensus/beacon/consensus.go (about) 1 // Copyright 2021 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 beacon 18 19 import ( 20 "errors" 21 "fmt" 22 "math/big" 23 "time" 24 25 "github.com/theQRL/go-zond/common" 26 "github.com/theQRL/go-zond/consensus" 27 "github.com/theQRL/go-zond/consensus/misc/eip1559" 28 "github.com/theQRL/go-zond/core/state" 29 "github.com/theQRL/go-zond/core/types" 30 "github.com/theQRL/go-zond/params" 31 "github.com/theQRL/go-zond/rpc" 32 "github.com/theQRL/go-zond/trie" 33 ) 34 35 // Various error messages to mark blocks invalid. These should be private to 36 // prevent engine specific errors from being referenced in the remainder of the 37 // codebase, inherently breaking if the engine is swapped out. Please put common 38 // error types into the consensus package. 39 var ( 40 errInvalidTimestamp = errors.New("invalid timestamp") 41 ) 42 43 // Beacon is a consensus engine that uses the proof-of-stake algorithm. 44 type Beacon struct { 45 fakeFail *uint64 // Block number which fails PoW check even in fake mode 46 fakeDelay *time.Duration // Time delay to sleep for before returning from verify 47 fakeFull bool // Accepts everything as valid 48 } 49 50 // New creates a consensus engine. 51 func New() *Beacon { 52 return &Beacon{} 53 } 54 55 func NewFaker() *Beacon { 56 return new(Beacon) 57 } 58 59 func NewFakeFailer(fail uint64) *Beacon { 60 return &Beacon{ 61 fakeFail: &fail, 62 } 63 } 64 65 func NewFakeDelayer(delay time.Duration) *Beacon { 66 return &Beacon{ 67 fakeDelay: &delay, 68 } 69 } 70 71 func NewFullFaker() *Beacon { 72 return &Beacon{ 73 fakeFull: true, 74 } 75 } 76 77 // Author implements consensus.Engine, returning the verified author of the block. 78 func (beacon *Beacon) Author(header *types.Header) (common.Address, error) { 79 return header.Coinbase, nil 80 } 81 82 // VerifyHeader checks whether a header conforms to the consensus rules of the 83 // stock Zond consensus engine. 84 func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error { 85 // Short circuit if the parent is not known 86 parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) 87 if parent == nil { 88 return consensus.ErrUnknownAncestor 89 } 90 91 // Sanity checks passed, do a proper verification 92 return beacon.verifyHeader(chain, header, parent) 93 } 94 95 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers 96 // concurrently. The method returns a quit channel to abort the operations and 97 // a results channel to retrieve the async verifications. 98 // VerifyHeaders expect the headers to be ordered and continuous. 99 func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) { 100 return beacon.verifyHeaders(chain, headers, nil) 101 } 102 103 // verifyHeader checks whether a header conforms to the consensus rules of the 104 // stock Zond consensus engine. The difference between the beacon and classic is 105 // (a) The following fields are expected to be constants: 106 // 107 // to be the desired constants 108 // 109 // (b) we don't verify if a block is in the future anymore 110 // (c) the extradata is limited to 32 bytes 111 func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header) error { 112 // Ensure that the header's extra-data section is of a reasonable size 113 if len(header.Extra) > 32 { 114 return fmt.Errorf("extra-data longer than 32 bytes (%d)", len(header.Extra)) 115 } 116 // Verify the timestamp 117 if header.Time <= parent.Time { 118 return errInvalidTimestamp 119 } 120 // Verify that the gas limit is <= 2^63-1 121 if header.GasLimit > params.MaxGasLimit { 122 return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) 123 } 124 // Verify that the gasUsed is <= gasLimit 125 if header.GasUsed > header.GasLimit { 126 return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) 127 } 128 // Verify that the block number is parent's +1 129 if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(common.Big1) != 0 { 130 return consensus.ErrInvalidNumber 131 } 132 // Verify the header's EIP-1559 attributes. 133 if err := eip1559.VerifyEIP1559Header(chain.Config(), parent, header); err != nil { 134 return err 135 } 136 // Verify existence / non-existence of withdrawalsHash. 137 if header.WithdrawalsHash == nil { 138 return errors.New("missing withdrawalsHash") 139 } 140 141 if beacon.fakeDelay != nil { 142 time.Sleep(*beacon.fakeDelay) 143 } 144 if beacon.fakeFail != nil && *beacon.fakeFail == header.Number.Uint64() { 145 return errors.New("invalid tester pos") 146 } 147 148 return nil 149 } 150 151 // verifyHeaders is similar to verifyHeader, but verifies a batch of headers 152 // concurrently. The method returns a quit channel to abort the operations and 153 // a results channel to retrieve the async verifications. An additional parent 154 // header will be passed if the relevant header is not in the database yet. 155 func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, ancestor *types.Header) (chan<- struct{}, <-chan error) { 156 var ( 157 abort = make(chan struct{}) 158 results = make(chan error, len(headers)) 159 ) 160 if beacon.fakeFull || len(headers) == 0 { 161 for i := 0; i < len(headers); i++ { 162 results <- nil 163 } 164 return abort, results 165 } 166 go func() { 167 for i, header := range headers { 168 var parent *types.Header 169 if i == 0 { 170 if ancestor != nil { 171 parent = ancestor 172 } else { 173 parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) 174 } 175 } else if headers[i-1].Hash() == headers[i].ParentHash { 176 parent = headers[i-1] 177 } 178 if parent == nil { 179 select { 180 case <-abort: 181 return 182 case results <- consensus.ErrUnknownAncestor: 183 } 184 continue 185 } 186 err := beacon.verifyHeader(chain, header, parent) 187 select { 188 case <-abort: 189 return 190 case results <- err: 191 } 192 } 193 }() 194 return abort, results 195 } 196 197 // Finalize implements consensus.Engine and processes withdrawals on top. 198 func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { 199 // Withdrawals processing. 200 for _, w := range body.Withdrawals { 201 // Convert amount from gwei to wei. 202 amount := new(big.Int).SetUint64(w.Amount) 203 amount = amount.Mul(amount, big.NewInt(params.GWei)) 204 state.AddBalance(w.Address, amount) 205 } 206 // No block reward which is issued by consensus layer instead. 207 } 208 209 // FinalizeAndAssemble implements consensus.Engine, setting the final state and 210 // assembling the block. 211 func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) { 212 // All blocks after Shanghai must include a withdrawals root. 213 if body.Withdrawals == nil { 214 body.Withdrawals = make([]*types.Withdrawal, 0) 215 } 216 // Finalize and assemble the block. 217 beacon.Finalize(chain, header, state, body) 218 219 // Assign the final state root to header. 220 header.Root = state.IntermediateRoot(true) 221 222 // Assemble and return the final block. 223 return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)), nil 224 } 225 226 // APIs implements consensus.Engine, returning the user facing RPC APIs. 227 func (beacon *Beacon) APIs(chain consensus.ChainHeaderReader) []rpc.API { 228 return []rpc.API{} 229 } 230 231 // Close shutdowns the consensus engine 232 func (beacon *Beacon) Close() error { 233 return nil 234 }