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

draft release v1.3.7 #2088

Merged
merged 17 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
# Changelog
## v1.3.7
FEATURE
* [\#2067](https://github.com/bnb-chain/bsc/pull/2067) cmd/geth: add check func to validate state scheme
* [\#2068](https://github.com/bnb-chain/bsc/pull/2068) internal/ethapi: implement eth_getBlockReceipts

BUGFIX
* [\#2035](https://github.com/bnb-chain/bsc/pull/2035) all: pull snap sync PRs from upstream v1.13.5
* [\#2072](https://github.com/bnb-chain/bsc/pull/2072) fix: fix the pebble config of level option
* [\#2078](https://github.com/bnb-chain/bsc/pull/2078) core: LoadChainConfig return the predefined config for built-in networks firstly

## v1.3.6
FEATURE
* [\#2012](https://github.com/bnb-chain/bsc/pull/2012) cmd, core, ethdb: enable Pebble on 32 bits and OpenBSD
Expand Down
2 changes: 1 addition & 1 deletion cmd/clef/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -1206,7 +1206,7 @@ func GenDoc(ctx *cli.Context) error {
URL: accounts.URL{Path: ".. ignored .."},
},
{
Address: common.HexToAddress("0xffffffffffffffffffffffffffffffffffffffff"),
Address: common.MaxAddress,
},
}})
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/devp2p/internal/ethtest/snap.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type accRangeTest struct {
func (s *Suite) TestSnapGetAccountRange(t *utesting.T) {
var (
root = s.chain.RootAt(999)
ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
ffHash = common.MaxHash
zero = common.Hash{}
firstKeyMinus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf29")
firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
Expand Down Expand Up @@ -125,7 +125,7 @@ type stRangesTest struct {
// TestSnapGetStorageRanges various forms of GetStorageRanges requests.
func (s *Suite) TestSnapGetStorageRanges(t *utesting.T) {
var (
ffHash = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
ffHash = common.MaxHash
zero = common.Hash{}
firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606")
Expand Down
6 changes: 6 additions & 0 deletions cmd/geth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ func loadBaseConfig(ctx *cli.Context) gethConfig {
utils.Fatalf("%v", err)
}
}
if !utils.ValidateStateScheme(cfg.Eth.StateScheme) {
utils.Fatalf("invalid state scheme param in config: %s", cfg.Eth.StateScheme)
}
if cfg.Eth.Genesis != nil && cfg.Eth.Genesis.Config != nil {
log.Warn("Chain config in the configuration file is ignored!")
}

// Apply flags.
utils.SetNodeConfig(ctx, &cfg.Node)
Expand Down
63 changes: 60 additions & 3 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth"

"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/filters"
Expand Down Expand Up @@ -1940,7 +1939,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
}
// Parse state scheme, abort the process if it's not compatible.
chaindb := tryMakeReadOnlyDatabase(ctx, stack)
scheme, err := ParseStateScheme(ctx, chaindb)
scheme, err := ResolveStateScheme(ctx, cfg.StateScheme, chaindb)
chaindb.Close()
if err != nil {
Fatalf("%v", err)
Expand Down Expand Up @@ -2486,6 +2485,52 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
return preloads
}

// ResolveStateScheme resolve state scheme from CLI flag, config file and persistent state.
// The differences between ResolveStateScheme and ParseStateScheme are:
// - ResolveStateScheme adds config to compare with CLI and persistent state to ensure correctness.
// - ResolveStateScheme is only used in SetEthConfig function.
//
// 1. If config isn't provided, write hash mode to config by default, so in current function, config is nonempty.
// 2. If persistent state and cli is empty, use config param.
// 3. If persistent state is empty, provide CLI flag and config, choose CLI to return.
// 4. If persistent state is nonempty and CLI isn't provided, persistent state should be equal to config.
// 5. If all three items are provided: if any two of the three are not equal, return error.
func ResolveStateScheme(ctx *cli.Context, stateSchemeCfg string, disk ethdb.Database) (string, error) {
stored := rawdb.ReadStateScheme(disk)
if stored == "" {
// there is no persistent state data in disk db(e.g. geth init)
if !ctx.IsSet(StateSchemeFlag.Name) {
log.Info("State scheme set by config", "scheme", stateSchemeCfg)
return stateSchemeCfg, nil
}
// if both CLI flag and config are set, choose CLI
scheme := ctx.String(StateSchemeFlag.Name)
if !ValidateStateScheme(scheme) {
return "", fmt.Errorf("invalid state scheme param in CLI: %s", scheme)
}
log.Info("State scheme set by CLI", "scheme", scheme)
return scheme, nil
}
if !ctx.IsSet(StateSchemeFlag.Name) {
if stored != stateSchemeCfg {
return "", fmt.Errorf("incompatible state scheme, stored: %s, config: %s", stored, stateSchemeCfg)
}
log.Info("State scheme set to already existing", "scheme", stored)
return stored, nil
}
scheme := ctx.String(StateSchemeFlag.Name)
if !ValidateStateScheme(scheme) {
return "", fmt.Errorf("invalid state scheme param in CLI: %s", scheme)
}
// if there is persistent state data in disk db, and CLI flag, config are set,
// when they all are different, return error
if scheme != stored || scheme != stateSchemeCfg || stored != stateSchemeCfg {
return "", fmt.Errorf("incompatible state scheme, stored: %s, config: %s, CLI: %s", stored, stateSchemeCfg, scheme)
}
log.Info("All are provided, state scheme set to already existing", "scheme", stored)
return stored, nil
}

// ParseStateScheme resolves scheme identifier from CLI flag. If the provided
// state scheme is not compatible with the one of persistent scheme, an error
// will be returned.
Expand All @@ -2505,7 +2550,7 @@ func ParseStateScheme(ctx *cli.Context, disk ethdb.Database) (string, error) {
if stored == "" {
// use default scheme for empty database, flip it when
// path mode is chosen as default
log.Info("State schema set to default", "scheme", "hash")
log.Info("State scheme set to default", "scheme", "hash")
return rawdb.HashScheme, nil
}
log.Info("State scheme set to already existing", "scheme", stored)
Expand All @@ -2514,6 +2559,9 @@ func ParseStateScheme(ctx *cli.Context, disk ethdb.Database) (string, error) {
// If state scheme is specified, ensure it's compatible with
// persistent state.
scheme := ctx.String(StateSchemeFlag.Name)
if !ValidateStateScheme(scheme) {
return "", fmt.Errorf("invalid state scheme param in CLI: %s", scheme)
}
if stored == "" || scheme == stored {
log.Info("State scheme set by user", "scheme", scheme)
return scheme, nil
Expand Down Expand Up @@ -2544,3 +2592,12 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
}
return trie.NewDatabase(disk, config)
}

// ValidateStateScheme used to check state scheme whether is valid.
// Valid state scheme: hash and path.
func ValidateStateScheme(stateScheme string) bool {
if stateScheme == rawdb.HashScheme || stateScheme == rawdb.PathScheme {
return true
}
return false
}
33 changes: 33 additions & 0 deletions cmd/utils/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ package utils
import (
"reflect"
"testing"

"github.com/ethereum/go-ethereum/core/rawdb"
)

func Test_SplitTagsFlag(t *testing.T) {
Expand Down Expand Up @@ -62,3 +64,34 @@ func Test_SplitTagsFlag(t *testing.T) {
})
}
}

func TestValidateStateScheme(t *testing.T) {
tests := []struct {
name string
arg string
wantResult bool
}{
{
name: "hash scheme",
arg: rawdb.HashScheme,
wantResult: true,
},
{
name: "path scheme",
arg: rawdb.PathScheme,
wantResult: true,
},
{
name: "invalid scheme",
arg: "mockScheme",
wantResult: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ValidateStateScheme(tt.arg); got != tt.wantResult {
t.Errorf("ValidateStateScheme() = %v, want %v", got, tt.wantResult)
}
})
}
}
6 changes: 6 additions & 0 deletions common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ const (
var (
hashT = reflect.TypeOf(Hash{})
addressT = reflect.TypeOf(Address{})

// MaxAddress represents the maximum possible address value.
MaxAddress = HexToAddress("0xffffffffffffffffffffffffffffffffffffffff")

// MaxHash represents the maximum possible hash value.
MaxHash = HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
)

// Hash represents the 32 byte Keccak256 hash of arbitrary data.
Expand Down
1 change: 1 addition & 0 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ func New(
) *Parlia {
// get parlia config
parliaConfig := chainConfig.Parlia
log.Info("Parlia", "chainConfig", chainConfig)

// Set any missing consensus parameters to their defaults
if parliaConfig != nil && parliaConfig.Epoch == 0 {
Expand Down
83 changes: 13 additions & 70 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import (
"errors"
"fmt"
"math/big"
"reflect"
"regexp"
"strings"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -399,14 +397,19 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
return newcfg, stored, nil
}

// LoadChainConfig loads the stored chain config if it is already present in
// database, otherwise, return the config in the provided genesis specification.
// LoadChainConfig retrieves the predefined chain configuration for the built-in network.
// For non-built-in networks, it first attempts to load the stored chain configuration from the database.
// If the configuration is not present, it returns the configuration specified in the provided genesis specification.
func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
// Load the stored chain config from the database. It can be nil
// in case the database is empty. Notably, we only care about the
// chain config corresponds to the canonical chain.
stored := rawdb.ReadCanonicalHash(db, 0)
if stored != (common.Hash{}) {
builtInConf := params.GetBuiltInChainConfig(stored)
if builtInConf != nil {
return builtInConf, stored, nil
}
storedcfg := rawdb.ReadChainConfig(db, stored)
if storedcfg != nil {
return storedcfg, stored, nil
Expand All @@ -432,75 +435,15 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig,
return params.BSCChainConfig, params.BSCGenesisHash, nil
}

// For any block or time in g.Config which is nil but the same field in defaultConfig is not
// set the field in genesis config to the field in defaultConfig.
// Reflection is used to avoid a long series of if statements with hardcoded block names.
func (g *Genesis) setDefaultHardforkValues(defaultConfig *params.ChainConfig) {
// Regex to match Block names or Time names
hardforkPattern := []string{`.*Block$`, `.*Time$`}

for _, pat := range hardforkPattern {
hardforkRegex := regexp.MustCompile(pat)

// Get reflect values
gConfigElem := reflect.ValueOf(g.Config).Elem()
defaultConfigElem := reflect.ValueOf(defaultConfig).Elem()

// Iterate over fields in config
for i := 0; i < gConfigElem.NumField(); i++ {
gConfigField := gConfigElem.Field(i)
defaultConfigField := defaultConfigElem.Field(i)
fieldName := gConfigElem.Type().Field(i).Name

// Use the regex to check if the field is a Block or Time field
if gConfigField.Kind() == reflect.Ptr && hardforkRegex.MatchString(fieldName) {
if gConfigField.IsNil() {
gConfigField.Set(defaultConfigField)
}
}
}
}
}

// Hard fork field specified in config.toml has higher priority, but
// if it is not specified in config.toml, use the default height in code.
func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
var defaultConfig *params.ChainConfig
switch {
case ghash == params.MainnetGenesisHash:
defaultConfig = params.MainnetChainConfig
case ghash == params.BSCGenesisHash:
defaultConfig = params.BSCChainConfig
case ghash == params.ChapelGenesisHash:
defaultConfig = params.ChapelChainConfig
case ghash == params.RialtoGenesisHash:
defaultConfig = params.RialtoChainConfig
default:
if g != nil {
// it could be a custom config for QA test, just return
return g.Config
}
defaultConfig = params.AllEthashProtocolChanges
conf := params.GetBuiltInChainConfig(ghash)
if conf != nil {
return conf
}
if g == nil || g.Config == nil {
return defaultConfig
if g != nil {
return g.Config // it could be a custom config for QA test, just return
}

g.setDefaultHardforkValues(defaultConfig)

// BSC Parlia set up
if g.Config.Parlia == nil {
g.Config.Parlia = defaultConfig.Parlia
} else {
if g.Config.Parlia.Period == 0 {
g.Config.Parlia.Period = defaultConfig.Parlia.Period
}
if g.Config.Parlia.Epoch == 0 {
g.Config.Parlia.Epoch = defaultConfig.Parlia.Epoch
}
}

return g.Config
return params.AllEthashProtocolChanges
}

// ToBlock returns the genesis block according to genesis specification.
Expand Down
42 changes: 3 additions & 39 deletions core/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,12 @@ func TestConfigOrDefault(t *testing.T) {
gHash := params.BSCGenesisHash
config := defaultGenesis.configOrDefault(gHash)

if config.ChainID.Cmp(params.MainnetChainConfig.ChainID) != 0 {
if config.ChainID.Cmp(params.BSCChainConfig.ChainID) != 0 {
t.Errorf("ChainID of resulting config should be %v, but is %v instead", params.BSCChainConfig.ChainID, config.ChainID)
}

if config.HomesteadBlock.Cmp(params.MainnetChainConfig.HomesteadBlock) != 0 {
t.Errorf("resulting config should have HomesteadBlock = %v, but instead is %v", params.MainnetChainConfig, config.HomesteadBlock)
if config.HomesteadBlock.Cmp(params.BSCChainConfig.HomesteadBlock) != 0 {
t.Errorf("resulting config should have HomesteadBlock = %v, but instead is %v", params.BSCChainConfig, config.HomesteadBlock)
}

if config.PlanckBlock == nil {
Expand All @@ -258,42 +258,6 @@ func TestConfigOrDefault(t *testing.T) {
}
}

func TestSetDefaultHardforkValues(t *testing.T) {
genesis := &Genesis{Config: &params.ChainConfig{ChainID: big.NewInt(66), HomesteadBlock: big.NewInt(11)}}
genesis.setDefaultHardforkValues(params.BSCChainConfig)

// Make sure the non-nil block was not modified
if genesis.Config.HomesteadBlock.Cmp(big.NewInt(11)) != 0 {
t.Errorf("Homestead block should not have been modified. HomesteadBlock = %v", genesis.Config.HomesteadBlock)
}

// Spot check a few blocks
if genesis.Config.NielsBlock.Cmp(params.BSCChainConfig.NielsBlock) != 0 {
t.Errorf("Niels block not matching: in genesis = %v , in defaultConfig = %v", genesis.Config.NielsBlock, params.BSCChainConfig.NielsBlock)
}

if genesis.Config.NanoBlock.Cmp(params.BSCChainConfig.NanoBlock) != 0 {
t.Errorf("Nano block not matching: in genesis = %v , in defaultConfig = %v", genesis.Config.NanoBlock, params.BSCChainConfig.NanoBlock)
}

if genesis.Config.PlanckBlock.Cmp(params.BSCChainConfig.PlanckBlock) != 0 {
t.Errorf("Nano block not matching: in genesis = %v , in defaultConfig = %v", genesis.Config.PlanckBlock, params.BSCChainConfig.PlanckBlock)
}

// Spot check a few times
if *genesis.Config.ShanghaiTime != *params.BSCChainConfig.ShanghaiTime {
t.Errorf("Shanghai Time not matching: in genesis = %d , in defaultConfig = %d", *genesis.Config.ShanghaiTime, *params.BSCChainConfig.ShanghaiTime)
}
if *genesis.Config.KeplerTime != *params.BSCChainConfig.KeplerTime {
t.Errorf("Kepler Time not matching: in genesis = %d , in defaultConfig = %d", *genesis.Config.KeplerTime, *params.BSCChainConfig.KeplerTime)
}

// Lastly make sure non-block fields such as ChainID have not been modified
if genesis.Config.ChainID.Cmp(big.NewInt(66)) != 0 {
t.Errorf("ChainID should not have been modified. ChainID = %v", genesis.Config.ChainID)
}
}

func newDbConfig(scheme string) *trie.Config {
if scheme == rawdb.HashScheme {
return trie.HashDefaults
Expand Down
Loading
Loading