consensus.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  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. package beacon
  17. import (
  18. "errors"
  19. "fmt"
  20. "math/big"
  21. "github.com/ethereum/go-ethereum/common"
  22. "github.com/ethereum/go-ethereum/consensus"
  23. "github.com/ethereum/go-ethereum/consensus/misc"
  24. "github.com/ethereum/go-ethereum/core/state"
  25. "github.com/ethereum/go-ethereum/core/types"
  26. "github.com/ethereum/go-ethereum/params"
  27. "github.com/ethereum/go-ethereum/rpc"
  28. "github.com/ethereum/go-ethereum/trie"
  29. )
  30. // Proof-of-stake protocol constants.
  31. var (
  32. beaconDifficulty = common.Big0 // The default block difficulty in the beacon consensus
  33. beaconNonce = types.EncodeNonce(0) // The default block nonce in the beacon consensus
  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. errTooManyUncles = errors.New("too many uncles")
  41. errInvalidNonce = errors.New("invalid nonce")
  42. errInvalidUncleHash = errors.New("invalid uncle hash")
  43. errInvalidTimestamp = errors.New("invalid timestamp")
  44. errNotSupportPosHeader = errors.New("not support pos header")
  45. )
  46. // Beacon is a consensus engine that combines the eth1 consensus and proof-of-stake
  47. // algorithm. There is a special flag inside to decide whether to use legacy consensus
  48. // rules or new rules. The transition rule is described in the eth1/2 merge spec.
  49. // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3675.md
  50. //
  51. // The beacon here is a half-functional consensus engine with partial functions which
  52. // is only used for necessary consensus checks. The legacy consensus engine can be any
  53. // engine implements the consensus interface (except the beacon itself).
  54. type Beacon struct {
  55. ethone consensus.Engine // Original consensus engine used in eth1, e.g. ethash or clique
  56. }
  57. // New creates a consensus engine with the given embedded eth1 engine.
  58. func New(ethone consensus.Engine) *Beacon {
  59. if _, ok := ethone.(*Beacon); ok {
  60. panic("nested consensus engine")
  61. }
  62. return &Beacon{ethone: ethone}
  63. }
  64. // Author implements consensus.Engine, returning the verified author of the block.
  65. func (beacon *Beacon) Author(header *types.Header) (common.Address, error) {
  66. if !beacon.IsPoSHeader(header) {
  67. return beacon.ethone.Author(header)
  68. }
  69. return header.Coinbase, nil
  70. }
  71. // VerifyHeader checks whether a header conforms to the consensus rules of the
  72. // stock Ethereum consensus engine.
  73. func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error {
  74. if chain.Config().EthPoWForkSupport {
  75. return beacon.ethone.VerifyHeader(chain, header, seal)
  76. }
  77. reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1)
  78. if err != nil {
  79. return err
  80. }
  81. if !reached {
  82. return beacon.ethone.VerifyHeader(chain, header, seal)
  83. }
  84. // Short circuit if the parent is not known
  85. parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
  86. if parent == nil {
  87. return consensus.ErrUnknownAncestor
  88. }
  89. // Sanity checks passed, do a proper verification
  90. return beacon.verifyHeader(chain, header, parent)
  91. }
  92. // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
  93. // concurrently. The method returns a quit channel to abort the operations and
  94. // a results channel to retrieve the async verifications.
  95. // VerifyHeaders expect the headers to be ordered and continuous.
  96. func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
  97. if !beacon.IsPoSHeader(headers[len(headers)-1]) {
  98. return beacon.ethone.VerifyHeaders(chain, headers, seals)
  99. }
  100. if chain.Config().EthPoWForkSupport {
  101. err := errNotSupportPosHeader
  102. results := make(chan error, len(headers))
  103. for i := 0; i < len(headers); i++ {
  104. results <- err
  105. }
  106. return make(chan struct{}), results
  107. }
  108. var (
  109. preHeaders []*types.Header
  110. postHeaders []*types.Header
  111. preSeals []bool
  112. )
  113. for index, header := range headers {
  114. if beacon.IsPoSHeader(header) {
  115. preHeaders = headers[:index]
  116. postHeaders = headers[index:]
  117. preSeals = seals[:index]
  118. break
  119. }
  120. }
  121. if len(preHeaders) == 0 {
  122. // All the headers are pos headers. Verify that the parent block reached total terminal difficulty.
  123. if reached, err := IsTTDReached(chain, headers[0].ParentHash, headers[0].Number.Uint64()-1); !reached {
  124. // TTD not reached for the first block, mark subsequent with invalid terminal block
  125. if err == nil {
  126. err = consensus.ErrInvalidTerminalBlock
  127. }
  128. results := make(chan error, len(headers))
  129. for i := 0; i < len(headers); i++ {
  130. results <- err
  131. }
  132. return make(chan struct{}), results
  133. }
  134. return beacon.verifyHeaders(chain, headers, nil)
  135. }
  136. // The transition point exists in the middle, separate the headers
  137. // into two batches and apply different verification rules for them.
  138. var (
  139. abort = make(chan struct{})
  140. results = make(chan error, len(headers))
  141. )
  142. go func() {
  143. var (
  144. old, new, out = 0, len(preHeaders), 0
  145. errors = make([]error, len(headers))
  146. done = make([]bool, len(headers))
  147. oldDone, oldResult = beacon.ethone.VerifyHeaders(chain, preHeaders, preSeals)
  148. newDone, newResult = beacon.verifyHeaders(chain, postHeaders, preHeaders[len(preHeaders)-1])
  149. )
  150. // Verify that pre-merge headers don't overflow the TTD
  151. if index, err := verifyTerminalPoWBlock(chain, preHeaders); err != nil {
  152. // Mark all subsequent pow headers with the error.
  153. for i := index; i < len(preHeaders); i++ {
  154. errors[i], done[i] = err, true
  155. }
  156. }
  157. // Collect the results
  158. for {
  159. for ; done[out]; out++ {
  160. results <- errors[out]
  161. if out == len(headers)-1 {
  162. return
  163. }
  164. }
  165. select {
  166. case err := <-oldResult:
  167. if !done[old] { // skip TTD-verified failures
  168. errors[old], done[old] = err, true
  169. }
  170. old++
  171. case err := <-newResult:
  172. errors[new], done[new] = err, true
  173. new++
  174. case <-abort:
  175. close(oldDone)
  176. close(newDone)
  177. return
  178. }
  179. }
  180. }()
  181. return abort, results
  182. }
  183. // verifyTerminalPoWBlock verifies that the preHeaders conform to the specification
  184. // wrt. their total difficulty.
  185. // It expects:
  186. // - preHeaders to be at least 1 element
  187. // - the parent of the header element to be stored in the chain correctly
  188. // - the preHeaders to have a set difficulty
  189. // - the last element to be the terminal block
  190. func verifyTerminalPoWBlock(chain consensus.ChainHeaderReader, preHeaders []*types.Header) (int, error) {
  191. td := chain.GetTd(preHeaders[0].ParentHash, preHeaders[0].Number.Uint64()-1)
  192. if td == nil {
  193. return 0, consensus.ErrUnknownAncestor
  194. }
  195. td = new(big.Int).Set(td)
  196. // Check that all blocks before the last one are below the TTD
  197. for i, head := range preHeaders {
  198. if td.Cmp(chain.Config().TerminalTotalDifficulty) >= 0 {
  199. return i, consensus.ErrInvalidTerminalBlock
  200. }
  201. td.Add(td, head.Difficulty)
  202. }
  203. // Check that the last block is the terminal block
  204. if td.Cmp(chain.Config().TerminalTotalDifficulty) < 0 {
  205. return len(preHeaders) - 1, consensus.ErrInvalidTerminalBlock
  206. }
  207. return 0, nil
  208. }
  209. // VerifyUncles verifies that the given block's uncles conform to the consensus
  210. // rules of the Ethereum consensus engine.
  211. func (beacon *Beacon) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
  212. if !beacon.IsPoSHeader(block.Header()) {
  213. return beacon.ethone.VerifyUncles(chain, block)
  214. }
  215. if chain.Config().EthPoWForkSupport {
  216. return errNotSupportPosHeader
  217. }
  218. // Verify that there is no uncle block. It's explicitly disabled in the beacon
  219. if len(block.Uncles()) > 0 {
  220. return errTooManyUncles
  221. }
  222. return nil
  223. }
  224. // verifyHeader checks whether a header conforms to the consensus rules of the
  225. // stock Ethereum consensus engine. The difference between the beacon and classic is
  226. // (a) The following fields are expected to be constants:
  227. // - difficulty is expected to be 0
  228. // - nonce is expected to be 0
  229. // - unclehash is expected to be Hash(emptyHeader)
  230. // to be the desired constants
  231. //
  232. // (b) we don't verify if a block is in the future anymore
  233. // (c) the extradata is limited to 32 bytes
  234. func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header) error {
  235. // Ensure that the header's extra-data section is of a reasonable size
  236. if len(header.Extra) > 32 {
  237. return fmt.Errorf("extra-data longer than 32 bytes (%d)", len(header.Extra))
  238. }
  239. // Verify the seal parts. Ensure the nonce and uncle hash are the expected value.
  240. if header.Nonce != beaconNonce {
  241. return errInvalidNonce
  242. }
  243. if header.UncleHash != types.EmptyUncleHash {
  244. return errInvalidUncleHash
  245. }
  246. // Verify the timestamp
  247. if header.Time <= parent.Time {
  248. return errInvalidTimestamp
  249. }
  250. // Verify the block's difficulty to ensure it's the default constant
  251. if beaconDifficulty.Cmp(header.Difficulty) != 0 {
  252. return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, beaconDifficulty)
  253. }
  254. // Verify that the gas limit is <= 2^63-1
  255. if header.GasLimit > params.MaxGasLimit {
  256. return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit)
  257. }
  258. // Verify that the gasUsed is <= gasLimit
  259. if header.GasUsed > header.GasLimit {
  260. return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
  261. }
  262. // Verify that the block number is parent's +1
  263. if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(common.Big1) != 0 {
  264. return consensus.ErrInvalidNumber
  265. }
  266. // Verify the header's EIP-1559 attributes.
  267. return misc.VerifyEip1559Header(chain.Config(), parent, header)
  268. }
  269. // verifyHeaders is similar to verifyHeader, but verifies a batch of headers
  270. // concurrently. The method returns a quit channel to abort the operations and
  271. // a results channel to retrieve the async verifications. An additional parent
  272. // header will be passed if the relevant header is not in the database yet.
  273. func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, ancestor *types.Header) (chan<- struct{}, <-chan error) {
  274. var (
  275. abort = make(chan struct{})
  276. results = make(chan error, len(headers))
  277. )
  278. go func() {
  279. for i, header := range headers {
  280. var parent *types.Header
  281. if i == 0 {
  282. if ancestor != nil {
  283. parent = ancestor
  284. } else {
  285. parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1)
  286. }
  287. } else if headers[i-1].Hash() == headers[i].ParentHash {
  288. parent = headers[i-1]
  289. }
  290. if parent == nil {
  291. select {
  292. case <-abort:
  293. return
  294. case results <- consensus.ErrUnknownAncestor:
  295. }
  296. continue
  297. }
  298. err := beacon.verifyHeader(chain, header, parent)
  299. select {
  300. case <-abort:
  301. return
  302. case results <- err:
  303. }
  304. }
  305. }()
  306. return abort, results
  307. }
  308. // Prepare implements consensus.Engine, initializing the difficulty field of a
  309. // header to conform to the beacon protocol. The changes are done inline.
  310. func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
  311. if chain.Config().EthPoWForkSupport {
  312. return beacon.ethone.Prepare(chain, header)
  313. }
  314. // Transition isn't triggered yet, use the legacy rules for preparation.
  315. reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1)
  316. if err != nil {
  317. return err
  318. }
  319. if !reached {
  320. return beacon.ethone.Prepare(chain, header)
  321. }
  322. header.Difficulty = beaconDifficulty
  323. return nil
  324. }
  325. // Finalize implements consensus.Engine, setting the final state on the header
  326. func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) {
  327. // Finalize is different with Prepare, it can be used in both block generation
  328. // and verification. So determine the consensus rules by header type.
  329. if !beacon.IsPoSHeader(header) {
  330. beacon.ethone.Finalize(chain, header, state, txs, uncles)
  331. return
  332. }
  333. if chain.Config().EthPoWForkSupport {
  334. return
  335. }
  336. // The block reward is no longer handled here. It's done by the
  337. // external consensus engine.
  338. header.Root = state.IntermediateRoot(true)
  339. }
  340. // FinalizeAndAssemble implements consensus.Engine, setting the final state and
  341. // assembling the block.
  342. func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
  343. // FinalizeAndAssemble is different with Prepare, it can be used in both block
  344. // generation and verification. So determine the consensus rules by header type.
  345. if !beacon.IsPoSHeader(header) {
  346. return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts)
  347. }
  348. if chain.Config().EthPoWForkSupport {
  349. return nil, errNotSupportPosHeader
  350. }
  351. // Finalize and assemble the block
  352. beacon.Finalize(chain, header, state, txs, uncles)
  353. return types.NewBlock(header, txs, uncles, receipts, trie.NewStackTrie(nil)), nil
  354. }
  355. // Seal generates a new sealing request for the given input block and pushes
  356. // the result into the given channel.
  357. //
  358. // Note, the method returns immediately and will send the result async. More
  359. // than one result may also be returned depending on the consensus algorithm.
  360. func (beacon *Beacon) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
  361. if !beacon.IsPoSHeader(block.Header()) {
  362. return beacon.ethone.Seal(chain, block, results, stop)
  363. }
  364. // The seal verification is done by the external consensus engine,
  365. // return directly without pushing any block back. In another word
  366. // beacon won't return any result by `results` channel which may
  367. // blocks the receiver logic forever.
  368. return nil
  369. }
  370. // SealHash returns the hash of a block prior to it being sealed.
  371. func (beacon *Beacon) SealHash(header *types.Header) common.Hash {
  372. return beacon.ethone.SealHash(header)
  373. }
  374. // CalcDifficulty is the difficulty adjustment algorithm. It returns
  375. // the difficulty that a new block should have when created at time
  376. // given the parent block's time and difficulty.
  377. func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
  378. // Transition isn't triggered yet, use the legacy rules for calculation
  379. if chain.Config().EthPoWForkSupport {
  380. return beacon.ethone.CalcDifficulty(chain, time, parent)
  381. }
  382. if reached, _ := IsTTDReached(chain, parent.Hash(), parent.Number.Uint64()); !reached {
  383. return beacon.ethone.CalcDifficulty(chain, time, parent)
  384. }
  385. return beaconDifficulty
  386. }
  387. // APIs implements consensus.Engine, returning the user facing RPC APIs.
  388. func (beacon *Beacon) APIs(chain consensus.ChainHeaderReader) []rpc.API {
  389. return beacon.ethone.APIs(chain)
  390. }
  391. // Close shutdowns the consensus engine
  392. func (beacon *Beacon) Close() error {
  393. return beacon.ethone.Close()
  394. }
  395. // IsPoSHeader reports the header belongs to the PoS-stage with some special fields.
  396. // This function is not suitable for a part of APIs like Prepare or CalcDifficulty
  397. // because the header difficulty is not set yet.
  398. func (beacon *Beacon) IsPoSHeader(header *types.Header) bool {
  399. if header.Difficulty == nil {
  400. panic("IsPoSHeader called with invalid difficulty")
  401. }
  402. return header.Difficulty.Cmp(beaconDifficulty) == 0
  403. }
  404. // InnerEngine returns the embedded eth1 consensus engine.
  405. func (beacon *Beacon) InnerEngine() consensus.Engine {
  406. return beacon.ethone
  407. }
  408. // SetThreads updates the mining threads. Delegate the call
  409. // to the eth1 engine if it's threaded.
  410. func (beacon *Beacon) SetThreads(threads int) {
  411. type threaded interface {
  412. SetThreads(threads int)
  413. }
  414. if th, ok := beacon.ethone.(threaded); ok {
  415. th.SetThreads(threads)
  416. }
  417. }
  418. // IsTTDReached checks if the TotalTerminalDifficulty has been surpassed on the `parentHash` block.
  419. // It depends on the parentHash already being stored in the database.
  420. // If the parentHash is not stored in the database a UnknownAncestor error is returned.
  421. func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, number uint64) (bool, error) {
  422. if chain.Config().EthPoWForkSupport {
  423. return false, nil
  424. }
  425. if chain.Config().TerminalTotalDifficulty == nil {
  426. return false, nil
  427. }
  428. td := chain.GetTd(parentHash, number)
  429. if td == nil {
  430. return false, consensus.ErrUnknownAncestor
  431. }
  432. return td.Cmp(chain.Config().TerminalTotalDifficulty) >= 0, nil
  433. }