gitlab.com/flarenetwork/coreth@v0.1.1/consensus/dummy/consensus.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package dummy 5 6 import ( 7 "bytes" 8 "errors" 9 "fmt" 10 "math/big" 11 "time" 12 13 "github.com/ethereum/go-ethereum/common" 14 "github.com/ethereum/go-ethereum/trie" 15 "gitlab.com/flarenetwork/coreth/consensus" 16 "gitlab.com/flarenetwork/coreth/core/state" 17 "gitlab.com/flarenetwork/coreth/core/types" 18 "gitlab.com/flarenetwork/coreth/params" 19 "gitlab.com/flarenetwork/coreth/rpc" 20 ) 21 22 type OnFinalizeCallbackType = func(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, receipts []*types.Receipt, uncles []*types.Header) error 23 type OnFinalizeAndAssembleCallbackType = func(header *types.Header, state *state.StateDB, txs []*types.Transaction) ([]byte, error) 24 type OnAPIsCallbackType = func(consensus.ChainHeaderReader) []rpc.API 25 type OnExtraStateChangeType = func(block *types.Block, statedb *state.StateDB) error 26 27 type ConsensusCallbacks struct { 28 OnAPIs OnAPIsCallbackType 29 OnFinalize OnFinalizeCallbackType 30 OnFinalizeAndAssemble OnFinalizeAndAssembleCallbackType 31 OnExtraStateChange OnExtraStateChangeType 32 } 33 34 type DummyEngine struct { 35 cb *ConsensusCallbacks 36 } 37 38 func NewDummyEngine(cb *ConsensusCallbacks) *DummyEngine { 39 return &DummyEngine{ 40 cb: cb, 41 } 42 } 43 44 func NewFaker() *DummyEngine { 45 return NewDummyEngine(new(ConsensusCallbacks)) 46 } 47 48 var ( 49 allowedFutureBlockTime = 10 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks 50 ) 51 52 var ( 53 errInvalidBlockTime = errors.New("timestamp less than parent's") 54 errUnclesUnsupported = errors.New("uncles unsupported") 55 ) 56 57 // modified from consensus.go 58 func (self *DummyEngine) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header, uncle bool) error { 59 // Ensure that we do not verify an uncle 60 if uncle { 61 return errUnclesUnsupported 62 } 63 // Ensure that the header's extra-data section is of a reasonable size 64 if !chain.Config().IsApricotPhase3(new(big.Int).SetUint64(header.Time)) { 65 if uint64(len(header.Extra)) > params.MaximumExtraDataSize { 66 return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) 67 } 68 // Verify BaseFee is not present before EIP-1559 69 // Note: this has been moved up from below in order to only switch on IsApricotPhase3 once. 70 if header.BaseFee != nil { 71 return fmt.Errorf("invalid baseFee before fork: have %d, want <nil>", header.BaseFee) 72 } 73 } else { 74 if len(header.Extra) != params.ApricotPhase3ExtraDataSize { 75 return fmt.Errorf("expected extra-data field to be: %d, but found %d", params.ApricotPhase3ExtraDataSize, len(header.Extra)) 76 } 77 // Verify baseFee and rollupWindow encoding as part of header verification 78 expectedRollupWindowBytes, expectedBaseFee, err := CalcBaseFee(chain.Config(), parent, header.Time) 79 if err != nil { 80 return fmt.Errorf("failed to calculate base fee: %w", err) 81 } 82 if !bytes.Equal(expectedRollupWindowBytes, header.Extra) { 83 return fmt.Errorf("expected rollup window bytes: %x, found %x", expectedRollupWindowBytes, header.Extra) 84 } 85 if header.BaseFee.Cmp(expectedBaseFee) != 0 { 86 return fmt.Errorf("expected base fee (%d), found (%d)", expectedBaseFee, header.BaseFee) 87 } 88 } 89 90 // Verify the header's timestamp 91 if header.Time > uint64(time.Now().Add(allowedFutureBlockTime).Unix()) { 92 return consensus.ErrFutureBlock 93 } 94 //if header.Time <= parent.Time { 95 if header.Time < parent.Time { 96 return errInvalidBlockTime 97 } 98 // Verify that the gas limit is <= 2^63-1 99 cap := uint64(0x7fffffffffffffff) 100 if header.GasLimit > cap { 101 return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap) 102 } 103 // Verify that the gasUsed is <= gasLimit 104 if header.GasUsed > header.GasLimit { 105 return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) 106 } 107 if config := chain.Config(); config.IsApricotPhase1(new(big.Int).SetUint64((header.Time))) { 108 if header.GasLimit != params.ApricotPhase1GasLimit { 109 return fmt.Errorf("expected gas limit to be %d, but found %d", params.ApricotPhase1GasLimit, header.GasLimit) 110 } 111 } else { 112 // Verify that the gas limit remains within allowed bounds 113 diff := int64(parent.GasLimit) - int64(header.GasLimit) 114 if diff < 0 { 115 diff *= -1 116 } 117 limit := parent.GasLimit / params.GasLimitBoundDivisor 118 119 if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit { 120 return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit) 121 } 122 } 123 124 // Verify that the block number is parent's +1 125 if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { 126 return consensus.ErrInvalidNumber 127 } 128 // Verify the engine specific seal securing the block 129 return self.VerifySeal(chain, header) 130 } 131 132 func (self *DummyEngine) Author(header *types.Header) (common.Address, error) { 133 return header.Coinbase, nil 134 } 135 136 func (self *DummyEngine) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error { 137 // Short circuit if the header is known, or it's parent not 138 number := header.Number.Uint64() 139 if chain.GetHeader(header.Hash(), number) != nil { 140 return nil 141 } 142 parent := chain.GetHeader(header.ParentHash, number-1) 143 if parent == nil { 144 return consensus.ErrUnknownAncestor 145 } 146 // Sanity checks passed, do a proper verification 147 return self.verifyHeader(chain, header, parent, false) 148 } 149 150 func (self *DummyEngine) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { 151 if len(block.Uncles()) > 0 { 152 return errUnclesUnsupported 153 } 154 return nil 155 } 156 157 func (self *DummyEngine) VerifySeal(chain consensus.ChainHeaderReader, header *types.Header) error { 158 return nil 159 } 160 161 func (self *DummyEngine) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { 162 header.Difficulty = big.NewInt(1) 163 return nil 164 } 165 166 func (self *DummyEngine) Finalize( 167 chain consensus.ChainHeaderReader, header *types.Header, 168 state *state.StateDB, txs []*types.Transaction, receipts []*types.Receipt, 169 uncles []*types.Header) error { 170 if self.cb.OnFinalize != nil { 171 return self.cb.OnFinalize(chain, header, state, txs, receipts, uncles) 172 } 173 return nil 174 } 175 176 func (self *DummyEngine) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, 177 uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { 178 var extdata []byte 179 if self.cb.OnFinalizeAndAssemble != nil { 180 ret, err := self.cb.OnFinalizeAndAssemble(header, state, txs) 181 extdata = ret 182 if err != nil { 183 return nil, err 184 } 185 } 186 // commit the final state root 187 header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 188 189 // Header seems complete, assemble into a block and return 190 return types.NewBlock( 191 header, txs, uncles, receipts, new(trie.Trie), extdata, 192 chain.Config().IsApricotPhase1(new(big.Int).SetUint64(header.Time)), 193 ), nil 194 } 195 196 func (self *DummyEngine) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { 197 return big.NewInt(1) 198 } 199 200 func (self *DummyEngine) APIs(chain consensus.ChainHeaderReader) (res []rpc.API) { 201 res = nil 202 if self.cb.OnAPIs != nil { 203 res = self.cb.OnAPIs(chain) 204 } 205 return 206 } 207 208 func (self *DummyEngine) Close() error { 209 return nil 210 } 211 212 func (self *DummyEngine) ExtraStateChange(block *types.Block, statedb *state.StateDB) error { 213 if self.cb.OnExtraStateChange != nil { 214 return self.cb.OnExtraStateChange(block, statedb) 215 } 216 return nil 217 }