Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consortium: enable snap sync on Ronin #389

Merged
merged 5 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions cmd/ronin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,10 +329,6 @@ func prepare(ctx *cli.Context) {
case !ctx.IsSet(utils.NetworkIdFlag.Name):
log.Info("Starting Geth on Ethereum mainnet...")
}
// remove snap out of ronin
if ctx.String(utils.SyncModeFlag.Name) == "snap" {
ctx.Set(utils.SyncModeFlag.Name, "full")
}
// If we're a full node on mainnet without --cache specified, bump default cache allowance
if ctx.String(utils.SyncModeFlag.Name) != "light" && !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
// Make sure we're not on any supported preconfigured testnet either
Expand Down
2 changes: 1 addition & 1 deletion consensus/consortium/common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ type BaseSnapshot struct {
// ConsortiumAdapter defines a small collection of methods needed to access the private
// methods between consensus engines
type ConsortiumAdapter interface {
GetSnapshot(chain consensus.ChainHeaderReader, number uint64, parents []*types.Header) *BaseSnapshot
GetSnapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) *BaseSnapshot
}
10 changes: 7 additions & 3 deletions consensus/consortium/v1/consortium.go
Original file line number Diff line number Diff line change
Expand Up @@ -721,9 +721,13 @@ func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint
return c.doCalcDifficulty(c.val, number, validators)
}

func (c *Consortium) GetSnapshot(chain consensus.ChainHeaderReader, number uint64, parents []*types.Header) *consortiumCommon.BaseSnapshot {
header := chain.GetHeaderByNumber(number)
snap, err := c.snapshot(chain, number, header.Hash(), parents)
func (c *Consortium) GetSnapshot(
chain consensus.ChainHeaderReader,
number uint64,
hash common.Hash,
parents []*types.Header,
) *consortiumCommon.BaseSnapshot {
snap, err := c.snapshot(chain, number, hash, parents)
if err != nil {
return nil
}
Expand Down
61 changes: 58 additions & 3 deletions consensus/consortium/v2/consortium.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,11 @@ func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, h
// in a batch of parents (ascending order) to avoid looking those up from the
// database. This is useful for concurrently verifying a batch of new headers.
func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error {
var (
snap *Snapshot
err error
)

// The genesis block is the always valid dead-end
number := header.Number.Uint64()
if number == 0 {
Expand Down Expand Up @@ -395,8 +400,11 @@ func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, he
return err
}

// Retrieve the snapshot needed to verify this header and cache it
snap, err := c.snapshot(chain, number-1, header.ParentHash, parents)
if number == c.forkedBlock {
snap, err = c.snapshotAtConsortiumFork(chain, number-1, header.ParentHash, header, parents)
} else {
snap, err = c.snapshot(chain, number-1, header.ParentHash, parents)
}
if err != nil {
return err
}
Expand All @@ -408,6 +416,53 @@ func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, he
return c.verifySeal(chain, header, parents, snap)
}

// snapshotAtConsortiumFork is expected to have to the same
// behavior as snapshot. However, the validator list is read from
// header instead of statedb to support snap sync. We try to keep
// the snapshot function unchanged to minimize the changing effect.
func (c *Consortium) snapshotAtConsortiumFork(
chain consensus.ChainHeaderReader,
number uint64,
hash common.Hash,
forkedHeader *types.Header,
parents []*types.Header,
) (*Snapshot, error) {
var validators []common.Address

snap, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI, c.chainConfig)
if err == nil {
log.Trace("Loaded snapshot from disk", "number", number, "hash", hash.Hex())
return snap, nil
}

extraData, err := finality.DecodeExtra(forkedHeader.Extra, false)
if err != nil {
return nil, err
}

for _, validator := range extraData.CheckpointValidators {
validators = append(validators, validator.Address)
}

snap = newSnapshot(c.chainConfig, c.config, c.signatures, number, hash, validators, nil, c.ethAPI)

// load v1 recent list to prevent recent producing-block-validators produce block again
snapV1 := c.v1.GetSnapshot(chain, number, hash, parents)
huyngopt1994 marked this conversation as resolved.
Show resolved Hide resolved
if snapV1 == nil {
return nil, errors.New("snapshot v1 is not available")
}

snap.Recents = consortiumCommon.RemoveOutdatedRecents(snapV1.Recents, number)

if err := snap.store(c.db); err != nil {
return nil, err
}
log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash)
figure.NewColorFigure("Welcome to DPOS", "", "green", true).Print()

return snap, nil
}

// snapshot retrieves the authorization snapshot at a given point in time.
func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) {
// Search for a snapshot in memory or on disk for checkpoints
Expand Down Expand Up @@ -459,7 +514,7 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64,
snap = newSnapshot(c.chainConfig, c.config, c.signatures, number, hash, validators, nil, c.ethAPI)

// load v1 recent list to prevent recent producing-block-validators produce block again
snapV1 := c.v1.GetSnapshot(chain, number, parents)
snapV1 := c.v1.GetSnapshot(chain, number, hash, parents)

// NOTE(linh): In version 1, the snapshot is not used correctly, so we must clean up
// incorrect data in the recent list before going to version 2
Expand Down
3 changes: 2 additions & 1 deletion eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
log.Info("Unprotected transactions allowed")
}
ethAPI := ethapi.NewPublicBlockChainAPI(eth.APIBackend)
eth.engine = ethconfig.CreateConsensusEngine(stack, chainConfig, &ethashConfig, config.Miner.Notify, config.Miner.Noverify, chainDb, ethAPI)
eth.engine = ethconfig.CreateConsensusEngine(stack, chainConfig, &ethashConfig, config.Miner.Notify, config.Miner.Noverify,
chainDb, ethAPI, config.SyncMode)

bcVersion := rawdb.ReadDatabaseVersion(chainDb)
var dbVer = "<nil>"
Expand Down
9 changes: 7 additions & 2 deletions eth/ethconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ var LightClientGPO = gasprice.Config{

// Defaults contains default settings for use on the Ethereum main net.
var Defaults = Config{
SyncMode: downloader.SnapSync,
SyncMode: downloader.FullSync,
Ethash: ethash.Config{
CacheDir: "ethash",
CachesInMem: 2,
Expand Down Expand Up @@ -233,13 +233,18 @@ func CreateConsensusEngine(
noverify bool,
db ethdb.Database,
ee *ethapi.PublicBlockChainAPI,
syncMode downloader.SyncMode,
) consensus.Engine {
// If proof-of-authority is requested, set it up
if chainConfig.Clique != nil {
return clique.New(chainConfig.Clique, db)
}
if chainConfig.Consortium != nil {
return consortium.New(chainConfig, db, ee, false)
if syncMode == downloader.SnapSync {
return consortium.New(chainConfig, db, ee, true)
} else {
return consortium.New(chainConfig, db, ee, false)
}
}
// Otherwise assume proof-of-work
switch config.PowMode {
Expand Down
109 changes: 109 additions & 0 deletions eth/protocols/snap/sort_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright 2022 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 snap

import (
"bytes"
"fmt"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/trie"
)

func hexToNibbles(s string) []byte {
if len(s) >= 2 && s[0] == '0' && s[1] == 'x' {
s = s[2:]
}
var s2 []byte
for _, ch := range []byte(s) {
s2 = append(s2, '0')
s2 = append(s2, ch)
}
return common.Hex2Bytes(string(s2))
}

func TestRequestSorting(t *testing.T) {

// - Path 0x9 -> {0x19}
// - Path 0x99 -> {0x0099}
// - Path 0x01234567890123456789012345678901012345678901234567890123456789019 -> {0x0123456789012345678901234567890101234567890123456789012345678901, 0x19}
// - Path 0x012345678901234567890123456789010123456789012345678901234567890199 -> {0x0123456789012345678901234567890101234567890123456789012345678901, 0x0099}
var f = func(path string) (trie.SyncPath, TrieNodePathSet, common.Hash) {
data := hexToNibbles(path)
sp := trie.NewSyncPath(data)
tnps := TrieNodePathSet([][]byte(sp))
hash := common.Hash{}
return sp, tnps, hash
}
var (
hashes []common.Hash
paths []trie.SyncPath
pathsets []TrieNodePathSet
)
for _, x := range []string{
"0x9",
"0x012345678901234567890123456789010123456789012345678901234567890195",
"0x012345678901234567890123456789010123456789012345678901234567890197",
"0x012345678901234567890123456789010123456789012345678901234567890196",
"0x99",
"0x012345678901234567890123456789010123456789012345678901234567890199",
"0x01234567890123456789012345678901012345678901234567890123456789019",
"0x0123456789012345678901234567890101234567890123456789012345678901",
"0x01234567890123456789012345678901012345678901234567890123456789010",
"0x01234567890123456789012345678901012345678901234567890123456789011",
} {
sp, tnps, hash := f(x)
hashes = append(hashes, hash)
paths = append(paths, sp)
pathsets = append(pathsets, tnps)
}
_, paths, pathsets = sortByAccountPath(hashes, paths)
{
var b = new(bytes.Buffer)
for i := 0; i < len(paths); i++ {
fmt.Fprintf(b, "\n%d. paths %x", i, paths[i])
}
want := `
0. paths [0099]
1. paths [0123456789012345678901234567890101234567890123456789012345678901 00]
2. paths [0123456789012345678901234567890101234567890123456789012345678901 0095]
3. paths [0123456789012345678901234567890101234567890123456789012345678901 0096]
4. paths [0123456789012345678901234567890101234567890123456789012345678901 0097]
5. paths [0123456789012345678901234567890101234567890123456789012345678901 0099]
6. paths [0123456789012345678901234567890101234567890123456789012345678901 10]
7. paths [0123456789012345678901234567890101234567890123456789012345678901 11]
8. paths [0123456789012345678901234567890101234567890123456789012345678901 19]
9. paths [19]`
if have := b.String(); have != want {
t.Errorf("have:%v\nwant:%v\n", have, want)
}
}
{
var b = new(bytes.Buffer)
for i := 0; i < len(pathsets); i++ {
fmt.Fprintf(b, "\n%d. pathset %x", i, pathsets[i])
}
want := `
0. pathset [0099]
1. pathset [0123456789012345678901234567890101234567890123456789012345678901 00 0095 0096 0097 0099 10 11 19]
2. pathset [19]`
if have := b.String(); have != want {
t.Errorf("have:%v\nwant:%v\n", have, want)
}
}
}
Loading
Loading