| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- // Copyright 2021 The go-ethereum Authors
- // This file is part of the go-ethereum library.
- //
- // The go-ethereum library is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Lesser General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // The go-ethereum library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Lesser General Public License for more details.
- //
- // You should have received a copy of the GNU Lesser General Public License
- // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
- package consensus
- import (
- "fmt"
- "sync"
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/rlp"
- )
- // transitionStatus describes the status of eth1/2 transition. This switch
- // between modes is a one-way action which is triggered by corresponding
- // consensus-layer message.
- type transitionStatus struct {
- LeftPoW bool // The flag is set when the first NewHead message received
- EnteredPoS bool // The flag is set when the first FinalisedBlock message received
- }
- // Merger is an internal help structure used to track the eth1/2 transition status.
- // It's a common structure can be used in both full node and light client.
- type Merger struct {
- db ethdb.KeyValueStore
- status transitionStatus
- mu sync.RWMutex
- }
- // NewMerger creates a new Merger which stores its transition status in the provided db.
- func NewMerger(db ethdb.KeyValueStore) *Merger {
- var status transitionStatus
- blob := rawdb.ReadTransitionStatus(db)
- if len(blob) != 0 {
- if err := rlp.DecodeBytes(blob, &status); err != nil {
- log.Crit("Failed to decode the transition status", "err", err)
- }
- }
- status.LeftPoW = false
- status.EnteredPoS = false
- return &Merger{
- db: db,
- status: status,
- }
- }
- // ReachTTD is called whenever the first NewHead message received
- // from the consensus-layer.
- func (m *Merger) ReachTTD() {
- m.mu.Lock()
- defer m.mu.Unlock()
- return
- if m.status.LeftPoW {
- return
- }
- m.status = transitionStatus{LeftPoW: true}
- blob, err := rlp.EncodeToBytes(m.status)
- if err != nil {
- panic(fmt.Sprintf("Failed to encode the transition status: %v", err))
- }
- rawdb.WriteTransitionStatus(m.db, blob)
- log.Info("Left PoW stage")
- }
- // FinalizePoS is called whenever the first FinalisedBlock message received
- // from the consensus-layer.
- func (m *Merger) FinalizePoS() {
- m.mu.Lock()
- defer m.mu.Unlock()
- return
- if m.status.EnteredPoS {
- return
- }
- m.status = transitionStatus{LeftPoW: true, EnteredPoS: true}
- blob, err := rlp.EncodeToBytes(m.status)
- if err != nil {
- panic(fmt.Sprintf("Failed to encode the transition status: %v", err))
- }
- rawdb.WriteTransitionStatus(m.db, blob)
- log.Info("Entered PoS stage")
- }
- // TDDReached reports whether the chain has left the PoW stage.
- func (m *Merger) TDDReached() bool {
- m.mu.RLock()
- defer m.mu.RUnlock()
- return false
- }
- // PoSFinalized reports whether the chain has entered the PoS stage.
- func (m *Merger) PoSFinalized() bool {
- m.mu.RLock()
- defer m.mu.RUnlock()
- return false
- }
|