Skip to content
Open
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
2 changes: 0 additions & 2 deletions consensus/XDPoS/XDPoS.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,6 @@ func New(chainConfig *params.ChainConfig, db ethdb.Database) (*XDPoS, error) {
return nil, errors.New("missing XDPoS config")
}

log.Info("xdc config loading", "v2 config", config.V2)

minePeriodCh := make(chan int)
newRoundCh := make(chan types.Round, newRoundChanSize)
engineV2, err := engine_v2.New(chainConfig, db, minePeriodCh, newRoundCh)
Expand Down
9 changes: 9 additions & 0 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ func New(stack *node.Node, config *ethconfig.Config, XDCXServ *XDCx.XDCX, lendin
if err != nil {
return nil, err
}
logXDPoSConfig(chainConfig, compatErr)

// Assemble the Ethereum object.
eth := &Ethereum{
Expand Down Expand Up @@ -462,6 +463,14 @@ func (e *Ethereum) APIs() []rpc.API {
}...)
}

func logXDPoSConfig(chainConfig *params.ChainConfig, compatErr *params.ConfigCompatError) {
if compatErr != nil || chainConfig == nil || chainConfig.XDPoS == nil || chainConfig.XDPoS.V2 == nil {
return
}

log.Info("Load xdc config", "config.V2", chainConfig.XDPoS.V2.StableLogValue())
}

func (e *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
e.blockchain.ResetWithGenesisBlock(gb)
}
Expand Down
26 changes: 26 additions & 0 deletions eth/backend_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package eth

import (
"bytes"
"encoding/json"
"math/big"
"strings"
"testing"

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/eth/util"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/params"
)

Expand Down Expand Up @@ -44,6 +47,29 @@ func TestRewardInflationUsesChainConfigTIPNoHalvingMNReward(t *testing.T) {
}
}

func TestLogXDPoSConfigSkipsOnCompatError(t *testing.T) {
var logBuf bytes.Buffer
prevLog := log.Root()
glog := log.NewGlogHandler(log.NewTerminalHandlerWithLevel(&logBuf, log.LevelTrace, false))
glog.Verbosity(log.LevelTrace)
log.SetDefault(log.NewLogger(glog))
defer log.SetDefault(prevLog)

logXDPoSConfig(params.TestnetChainConfig, &params.ConfigCompatError{What: "XDPoS.V2"})
if got := logBuf.String(); got != "" {
t.Fatalf("expected no XDPoS config log on compat error, got %q", got)
}

logXDPoSConfig(params.TestnetChainConfig, nil)
got := logBuf.String()
if !strings.Contains(got, "Load xdc config") {
t.Fatalf("expected XDPoS config log on healthy startup, got %q", got)
}
if !strings.Contains(got, "config.V2") {
t.Fatalf("expected V2 config details in startup log, got %q", got)
}
}

type testChainReader struct {
cfg *params.ChainConfig
}
Expand Down
48 changes: 48 additions & 0 deletions params/config_xdpos.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,54 @@ func (v2 *V2) String() string {
return fmt.Sprintf("V2{SwitchEpoch: %v, SwitchBlock: %v, %s}", snapshot.switchEpoch, snapshot.switchBlock, snapshot.currentConfig.String())
}

type stableLogConfigEntry struct {
Round uint64 `json:"round"`
Config *V2Config `json:"config"`
}

type stableLogView struct {
SwitchEpoch uint64 `json:"switchEpoch"`
SwitchBlock string `json:"switchBlock"`
CurrentConfig *V2Config `json:"currentConfig"`
AllConfigs []stableLogConfigEntry `json:"allConfigs"`
ConfigIndex []uint64 `json:"configIndex"`
}

// StableLogValue returns a full, deterministic structured value for startup
// logs. Callers can pass the returned object directly as a field value to
// avoid JSON string escaping in terminal log output.
func (v2 *V2) StableLogValue() stableLogView {
if v2 == nil {
return stableLogView{}
}

snapshot := snapshotV2ReadOnly(v2)

keys := slices.Collect(maps.Keys(snapshot.allConfigs))
slices.Sort(keys)

allConfigs := make([]stableLogConfigEntry, 0, len(keys))
for _, round := range keys {
allConfigs = append(allConfigs, stableLogConfigEntry{
Round: round,
Config: snapshot.allConfigs[round].Clone(),
})
}

var switchBlock string
if snapshot.switchBlock != nil {
switchBlock = snapshot.switchBlock.String()
}

return stableLogView{
SwitchEpoch: snapshot.switchEpoch,
SwitchBlock: switchBlock,
CurrentConfig: snapshot.currentConfig.Clone(),
AllConfigs: allConfigs,
ConfigIndex: append([]uint64(nil), snapshot.configIndex...),
}
}

// Description returns a human-readable description of V2
// NOTE: don't append "\n" to end
func (v2 *V2) Description(indent int) string {
Expand Down
39 changes: 39 additions & 0 deletions params/config_xdpos_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package params
import (
"encoding/json"
"math/big"
"strings"
"sync"
"testing"

Expand Down Expand Up @@ -192,6 +193,44 @@ func TestV2StringConcurrentWithUpdateConfig(t *testing.T) {
wg.Wait()
}

func TestV2StableLogValueDeterministicAndComplete(t *testing.T) {
v2 := &V2{
SwitchEpoch: 63143,
SwitchBlock: big.NewInt(56828700),
CurrentConfig: &V2Config{
MaxMasternodes: 15,
},
AllConfigs: map[uint64]*V2Config{
10: {SwitchRound: 10, MaxMasternodes: 16},
0: {SwitchRound: 0, MaxMasternodes: 15},
},
configIndex: []uint64{10, 0},
}

firstBytes, err := json.Marshal(v2.StableLogValue())
assert.NoError(t, err)
secondBytes, err := json.Marshal(v2.StableLogValue())
assert.NoError(t, err)

first := string(firstBytes)
second := string(secondBytes)
assert.Equal(t, first, second)

assert.Contains(t, first, `"switchEpoch":63143`)
assert.Contains(t, first, `"switchBlock":"56828700"`)
assert.Contains(t, first, `"configIndex":[10,0]`)
assert.Contains(t, first, `"currentConfig"`)

idxRound0 := strings.Index(first, `"round":0`)
idxRound10 := strings.Index(first, `"round":10`)
if idxRound0 == -1 || idxRound10 == -1 {
t.Fatalf("expected allConfigs rounds in stable log output, got %q", first)
}
if idxRound0 > idxRound10 {
t.Fatalf("expected allConfigs rounds sorted ascending, got %q", first)
}
}

func TestBuildConfigIndex(t *testing.T) {
TestXDPoSMockChainConfig.XDPoS.V2.BuildConfigIndex()
index := TestXDPoSMockChainConfig.XDPoS.V2.ConfigIndex()
Expand Down
Loading