From 0edbf96c90f5a494fade20e9b1875f2fa7005bcd Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Wed, 15 Nov 2023 15:15:23 +0800 Subject: [PATCH 01/22] geth: add export segment cmd; --- cmd/geth/chaincmd.go | 21 +++++++++++++++++++++ cmd/utils/flags.go | 7 +++++++ 2 files changed, 28 insertions(+) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 2edf676ad4..befc8b1c05 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -191,6 +191,18 @@ It's deprecated, please use "geth db export" instead. }, utils.DatabasePathFlags), Description: ` This command dumps out the state for a given block (or latest, if none provided). +`, + } + exportSegmentCommand = &cli.Command{ + Action: exportSegment, + Name: "export-segment", + Usage: "Export history segments from start block", + ArgsUsage: "", + Flags: flags.Merge([]cli.Flag{ + utils.HistorySegOutputFlag, + }, utils.DatabasePathFlags), + Description: ` +This command export history segments from start block. `, } ) @@ -675,6 +687,15 @@ func dump(ctx *cli.Context) error { return nil } +func exportSegment(ctx *cli.Context) error { + stack, _ := makeConfigNode(ctx) + defer stack.Close() + + db := utils.MakeChainDatabase(ctx, stack, true, false) + defer db.Close() + +} + // hashish returns true for strings that look like hashes. func hashish(x string) bool { _, err := strconv.Atoi(x) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index da610fb7cc..915e966eb9 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1127,6 +1127,13 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server. Usage: "Path for the voteJournal dir in fast finality feature (default = inside the datadir)", Category: flags.FastFinalityCategory, } + + // Export history segment + HistorySegOutputFlag = &cli.StringFlag{ + Name: "output", + Usage: "Specific history segments output file name & type", + Value: "./gen_history_segments.go", + } ) var ( From 5f743c2e1d3cfc0ff072d6d4706e0e55ba4ebcdf Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Thu, 16 Nov 2023 21:39:10 +0800 Subject: [PATCH 02/22] chaincmd: add export history segment tools; --- cmd/geth/chaincmd.go | 78 ++++++++++++++++++++++++++++++++ core/headerchain.go | 11 +++++ params/history_segment_params.go | 20 ++++++++ 3 files changed, 109 insertions(+) create mode 100644 params/history_segment_params.go diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index befc8b1c05..1e05784c2e 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -30,6 +30,12 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum/consensus" + + "github.com/ethereum/go-ethereum/params" + + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -694,6 +700,78 @@ func exportSegment(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() + genesisHash := rawdb.ReadCanonicalHash(db, 0) + chainConfig := rawdb.ReadChainConfig(db, genesisHash) + if chainConfig == nil { + return errors.New("failed to load chainConfig") + } + engine, err := ethconfig.CreateConsensusEngine(chainConfig, db, nil, genesisHash) + if err != nil { + return err + } + if _, ok := engine.(consensus.PoSA); !ok { + return errors.New("current chain is not POSA, cannot generate history segment") + } + headerChain, err := core.NewHeaderChain(db, chainConfig, engine, func() bool { + return true + }) + if err != nil { + return err + } + latest := headerChain.CurrentHeader() + if !chainConfig.IsLuban(latest.Number) { + return errors.New("current chain is not enable Luban hard fork, cannot generate history segment") + } + if latest.Number.Uint64() < params.BoundStartBlock { + return errors.New("current chain is too short, less than BoundStartBlock") + } + + log.Info("start export segment", "from", params.BoundStartBlock, "to", latest.Number, "chainCfg", chainConfig) + segs := []params.HisSegment{ + { + Index: 0, + StartAtBlock: params.HisBlockInfo{ + Number: 0, + Hash: genesisHash, + }, + }, + } + // try find finalized block in every segment boundary + for num := params.BoundStartBlock; num <= latest.Number.Uint64(); num += params.HistorySegmentLength { + var fs, ft *types.Header + for next := num + 1; next <= latest.Number.Uint64(); next++ { + fs = headerChain.GetHeaderByNumber(next) + ft = headerChain.GetFinalizedHeader(fs) + if ft == nil { + continue + } + if ft.Number.Uint64() >= num { + break + } + } + if ft == nil || fs == nil { + // if there cannot found any finalized block, just skip + break + } + log.Info("found segment boundary", "startAt", ft.Number, "FinalityAt", fs.Number) + segs = append(segs, params.HisSegment{ + Index: uint64(len(segs)), + StartAtBlock: params.HisBlockInfo{ + Number: ft.Number.Uint64(), + Hash: ft.Hash(), + }, + FinalityAtBlock: params.HisBlockInfo{ + Number: fs.Number.Uint64(), + Hash: fs.Hash(), + }, + }) + } + output, err := json.MarshalIndent(segs, "", "\n") + if err != nil { + return err + } + fmt.Println(string(output)) + return nil } // hashish returns true for strings that look like hashes. diff --git a/core/headerchain.go b/core/headerchain.go index def9d3dc54..dc4211094b 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -134,6 +134,17 @@ func (hc *HeaderChain) getFinalizedNumber(header *types.Header) uint64 { return 0 } +// GetFinalizedHeader returns the highest finalized header before the specific block. +func (hc *HeaderChain) GetFinalizedHeader(header *types.Header) *types.Header { + if p, ok := hc.engine.(consensus.PoSA); ok { + if finalizedHeader := p.GetFinalizedHeader(hc, header); finalizedHeader != nil { + return finalizedHeader + } + } + + return nil +} + // GetBlockNumber retrieves the block number belonging to the given hash // from the cache or database func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 { diff --git a/params/history_segment_params.go b/params/history_segment_params.go new file mode 100644 index 0000000000..dc42b93ab4 --- /dev/null +++ b/params/history_segment_params.go @@ -0,0 +1,20 @@ +package params + +import "github.com/ethereum/go-ethereum/common" + +const ( + BoundStartBlock uint64 = 31268530 // The starting block height of the first segment, was produced on Aug-29-2023 + HistorySegmentLength uint64 = 2592000 // Assume 1 block for every 3 second, 2,592,000 blocks will be produced in 90 days. +) + +type HisBlockInfo struct { + Number uint64 `json:"number"` + Hash common.Hash `json:"hash"` +} + +type HisSegment struct { + Index uint64 `json:"index"` // segment index number + StartAtBlock HisBlockInfo `json:"start_at_block"` // target segment start from here + FinalityAtBlock HisBlockInfo `json:"finality_at_block"` // the StartAtBlock finality's block + // TODO(0xbundler): if need add more finality evidence? like signature? +} From ac4624bb1145db7cb80cd048f59b618e0fd32912 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Thu, 16 Nov 2023 23:15:01 +0800 Subject: [PATCH 03/22] params: add history block segment config; --- core/genesis.go | 3 +- core/systemcontracts/upgrade.go | 3 +- params/config.go | 6 +++ params/history_segment.go | 92 ++++++++++++++++++++++++++++++++ params/history_segment_params.go | 20 ------- params/history_segment_test.go | 76 ++++++++++++++++++++++++++ 6 files changed, 176 insertions(+), 24 deletions(-) create mode 100644 params/history_segment.go delete mode 100644 params/history_segment_params.go create mode 100644 params/history_segment_test.go diff --git a/core/genesis.go b/core/genesis.go index 47f316c258..86f6a1ef85 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -30,7 +30,6 @@ import ( "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/systemcontracts" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" @@ -322,7 +321,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen } // Just commit the new block if there is no stored genesis block. stored := rawdb.ReadCanonicalHash(db, 0) - systemcontracts.GenesisHash = stored + params.LocalGenesisHash = stored if (stored == common.Hash{}) { if genesis == nil { log.Info("Writing default BSC mainnet genesis block") diff --git a/core/systemcontracts/upgrade.go b/core/systemcontracts/upgrade.go index 26650673b8..7ff3776d25 100644 --- a/core/systemcontracts/upgrade.go +++ b/core/systemcontracts/upgrade.go @@ -34,7 +34,6 @@ const ( ) var ( - GenesisHash common.Hash // upgrade config ramanujanUpgrade = make(map[string]*Upgrade) @@ -557,7 +556,7 @@ func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.I return } var network string - switch GenesisHash { + switch params.LocalGenesisHash { /* Add mainnet genesis hash */ case params.BSCGenesisHash: network = mainNet diff --git a/params/config.go b/params/config.go index 2aad8f1d71..083e5346e6 100644 --- a/params/config.go +++ b/params/config.go @@ -30,6 +30,8 @@ var ( BSCGenesisHash = common.HexToHash("0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b") ChapelGenesisHash = common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34") RialtoGenesisHash = common.HexToHash("0xee835a629f9cf5510b48b6ba41d69e0ff7d6ef10f977166ef939db41f59f5501") + + LocalGenesisHash common.Hash // it will be initial by user program, aim to indicate testnet, mainnet, or other chain ) func newUint64(val uint64) *uint64 { return &val } @@ -1094,6 +1096,10 @@ func configTimestampEqual(x, y *uint64) bool { return *x == *y } +func SetupLocalGenesisHash(h common.Hash) { + LocalGenesisHash = h +} + // ConfigCompatError is raised if the locally-stored blockchain is initialised with a // ChainConfig that would alter the past. type ConfigCompatError struct { diff --git a/params/history_segment.go b/params/history_segment.go new file mode 100644 index 0000000000..a33990f1ef --- /dev/null +++ b/params/history_segment.go @@ -0,0 +1,92 @@ +package params + +import ( + "encoding/json" + + "github.com/ethereum/go-ethereum/common" +) + +const ( + BoundStartBlock uint64 = 31268530 // The starting block height of the first segment, was produced on Aug-29-2023 + HistorySegmentLength uint64 = 2592000 // Assume 1 block for every 3 second, 2,592,000 blocks will be produced in 90 days. +) + +var ( + historySegmentsInBSCMainnet = unmarshalHisSegments(` +{ + { + index: 0, + start_at_block: { + number: 0, + hash: 0x0000000000000000000000000000000000000000000000000000000000000000 + } + } +} +`) + historySegmentsInBSCChapel = unmarshalHisSegments(` +{ + { + index: 0, + start_at_block: { + number: 0, + hash: 0x0000000000000000000000000000000000000000000000000000000000000000 + } + } +} +`) + historySegmentsInBSCRialto []HisSegment +) + +type HisBlockInfo struct { + Number uint64 `json:"number"` + Hash common.Hash `json:"hash"` +} + +type HisSegment struct { + Index uint64 `json:"index"` // segment index number + StartAtBlock HisBlockInfo `json:"start_at_block"` // target segment start from here + FinalityAtBlock HisBlockInfo `json:"finality_at_block"` // the StartAtBlock finality's block + // TODO(0xbundler): if need add more finality evidence? like signature? +} + +func HisSegments() []HisSegment { + switch LocalGenesisHash { + case BSCGenesisHash: + return historySegmentsInBSCMainnet + case ChapelGenesisHash: + return historySegmentsInBSCChapel + case RialtoGenesisHash: + return historySegmentsInBSCRialto + default: + panic("sorry, this chain is not support history block segment, or init with wrong genesis hash") + } +} + +// CurrentSegment return which segment include this block +func CurrentSegment(num uint64) HisSegment { + segments := HisSegments() + i := len(segments) - 1 + for i >= 0 { + if segments[i].StartAtBlock.Number <= num { + break + } + i-- + } + return segments[i] +} + +// FindPrevSegment return the current's last segment, because the latest 2 segments is available, +// so user could keep current & prev segment +func FindPrevSegment(cur HisSegment) (HisSegment, bool) { + segments := HisSegments() + if cur.Index == 0 || cur.Index >= uint64(len(segments)) { + return HisSegment{}, false + } + return segments[cur.Index-1], true +} + +func unmarshalHisSegments(enc string) []HisSegment { + var ret []HisSegment + json.Unmarshal([]byte(enc), &ret) + return ret +} diff --git a/params/history_segment_params.go b/params/history_segment_params.go deleted file mode 100644 index dc42b93ab4..0000000000 --- a/params/history_segment_params.go +++ /dev/null @@ -1,20 +0,0 @@ -package params - -import "github.com/ethereum/go-ethereum/common" - -const ( - BoundStartBlock uint64 = 31268530 // The starting block height of the first segment, was produced on Aug-29-2023 - HistorySegmentLength uint64 = 2592000 // Assume 1 block for every 3 second, 2,592,000 blocks will be produced in 90 days. -) - -type HisBlockInfo struct { - Number uint64 `json:"number"` - Hash common.Hash `json:"hash"` -} - -type HisSegment struct { - Index uint64 `json:"index"` // segment index number - StartAtBlock HisBlockInfo `json:"start_at_block"` // target segment start from here - FinalityAtBlock HisBlockInfo `json:"finality_at_block"` // the StartAtBlock finality's block - // TODO(0xbundler): if need add more finality evidence? like signature? -} diff --git a/params/history_segment_test.go b/params/history_segment_test.go new file mode 100644 index 0000000000..e795dd5ae6 --- /dev/null +++ b/params/history_segment_test.go @@ -0,0 +1,76 @@ +package params + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/ethereum/go-ethereum/common" +) + +func init() { + LocalGenesisHash = RialtoGenesisHash + historySegmentsInBSCRialto = []HisSegment{ + { + Index: 0, + StartAtBlock: HisBlockInfo{ + Number: 0, + Hash: common.Hash{}, + }, + }, + { + Index: 1, + StartAtBlock: HisBlockInfo{ + Number: BoundStartBlock, + Hash: common.HexToHash("0xdb8a505f19ef04cb21ae79e3cb641963ffc44f3666e6fde499be55a72b6c7865"), + }, + FinalityAtBlock: HisBlockInfo{ + Number: 31268532, + Hash: common.HexToHash("0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7"), + }, + }, + { + Index: 2, + StartAtBlock: HisBlockInfo{ + Number: 33860530, + Hash: common.HexToHash("0xbf6d408bce0d531c41b00410e1c567e46b359db6e14d842cd8c8325039dff498"), + }, + FinalityAtBlock: HisBlockInfo{ + Number: 33860532, + Hash: common.HexToHash("0xb22bf5eb6fe8ed39894d32b148fdedd91bd11497e7744e6c84c6b104aa577a15"), + }, + }, + } +} + +func TestUnmarshalHisSegments(t *testing.T) { + enc, err := json.MarshalIndent(HisSegments(), "", " ") + assert.NoError(t, err) + t.Log(string(enc)) + segments := unmarshalHisSegments(string(enc)) + assert.Equal(t, HisSegments(), segments) +} + +func TestIndexSegment(t *testing.T) { + segments := HisSegments() + assert.Equal(t, segments[0], CurrentSegment(0)) + assert.Equal(t, segments[0], CurrentSegment(BoundStartBlock-1)) + assert.Equal(t, segments[1], CurrentSegment(BoundStartBlock)) + assert.Equal(t, segments[1], CurrentSegment(BoundStartBlock+HistorySegmentLength-1)) + assert.Equal(t, segments[2], CurrentSegment(BoundStartBlock+HistorySegmentLength)) + assert.Equal(t, segments[2], CurrentSegment(BoundStartBlock+HistorySegmentLength*2)) + + prev, ok := FindPrevSegment(segments[0]) + assert.Equal(t, false, ok) + prev, ok = FindPrevSegment(segments[1]) + assert.Equal(t, true, ok) + assert.Equal(t, segments[0], prev) + prev, ok = FindPrevSegment(segments[2]) + assert.Equal(t, true, ok) + assert.Equal(t, segments[1], prev) + _, ok = FindPrevSegment(HisSegment{ + Index: uint64(len(segments)), + }) + assert.Equal(t, false, ok) +} From dd3f969bcdb61d8db4f08f704adbad2551c7d8ea Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Tue, 21 Nov 2023 11:27:07 +0800 Subject: [PATCH 04/22] params: add history block segment config; --- cmd/geth/chaincmd.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 1e05784c2e..cf2f3295d5 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -722,11 +722,13 @@ func exportSegment(ctx *cli.Context) error { if !chainConfig.IsLuban(latest.Number) { return errors.New("current chain is not enable Luban hard fork, cannot generate history segment") } - if latest.Number.Uint64() < params.BoundStartBlock { + latestNum := latest.Number.Uint64() + if latestNum < params.FullImmutabilityThreshold || latestNum < params.BoundStartBlock { return errors.New("current chain is too short, less than BoundStartBlock") } - log.Info("start export segment", "from", params.BoundStartBlock, "to", latest.Number, "chainCfg", chainConfig) + target := latestNum - params.FullImmutabilityThreshold + log.Info("start export segment", "from", params.BoundStartBlock, "to", target, "chainCfg", chainConfig) segs := []params.HisSegment{ { Index: 0, @@ -737,9 +739,9 @@ func exportSegment(ctx *cli.Context) error { }, } // try find finalized block in every segment boundary - for num := params.BoundStartBlock; num <= latest.Number.Uint64(); num += params.HistorySegmentLength { + for num := params.BoundStartBlock; num <= target; num += params.HistorySegmentLength { var fs, ft *types.Header - for next := num + 1; next <= latest.Number.Uint64(); next++ { + for next := num + 1; next <= target; next++ { fs = headerChain.GetHeaderByNumber(next) ft = headerChain.GetFinalizedHeader(fs) if ft == nil { From ede66f65e9a51ce4463edf35947fdd79d104b521 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Wed, 22 Nov 2023 20:20:30 +0800 Subject: [PATCH 05/22] historysegment: add offline history segments tool; --- cmd/geth/chaincmd.go | 163 ++++++++++++++++++---- cmd/geth/main.go | 4 + cmd/utils/flags.go | 41 +++++- core/genesis.go | 3 +- core/rawdb/history_segment.go | 77 +++++++++++ core/systemcontracts/upgrade.go | 3 +- eth/backend.go | 47 ++++++- eth/ethconfig/config.go | 4 + eth/ethconfig/gen_config.go | 236 +++++++++++++++++--------------- params/config.go | 6 - params/history_segment.go | 181 +++++++++++++++++++----- params/history_segment_test.go | 155 ++++++++++++++++++--- 12 files changed, 722 insertions(+), 198 deletions(-) create mode 100644 core/rawdb/history_segment.go diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index cf2f3295d5..65350acc68 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -205,10 +205,28 @@ This command dumps out the state for a given block (or latest, if none provided) Usage: "Export history segments from start block", ArgsUsage: "", Flags: flags.Merge([]cli.Flag{ + utils.CacheFlag, + utils.SyncModeFlag, utils.HistorySegOutputFlag, + utils.BoundStartBlockFlag, + utils.HistorySegmentLengthFlag, }, utils.DatabasePathFlags), Description: ` This command export history segments from start block. +`, + } + pruneHistorySegmentsCommand = &cli.Command{ + Action: pruneHistorySegments, + Name: "prune-history-segments", + Usage: "Prune all history segments, it only keep latest 2 segments", + ArgsUsage: "", + Flags: flags.Merge([]cli.Flag{ + utils.CacheFlag, + utils.SyncModeFlag, + utils.HistorySegCustomFlag, + }, utils.DatabasePathFlags), + Description: ` +Prune all history segments, it only keep latest 2 segments. `, } ) @@ -697,24 +715,11 @@ func exportSegment(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() - db := utils.MakeChainDatabase(ctx, stack, true, false) + db := utils.MakeChainDatabase(ctx, stack, false, false) defer db.Close() genesisHash := rawdb.ReadCanonicalHash(db, 0) - chainConfig := rawdb.ReadChainConfig(db, genesisHash) - if chainConfig == nil { - return errors.New("failed to load chainConfig") - } - engine, err := ethconfig.CreateConsensusEngine(chainConfig, db, nil, genesisHash) - if err != nil { - return err - } - if _, ok := engine.(consensus.PoSA); !ok { - return errors.New("current chain is not POSA, cannot generate history segment") - } - headerChain, err := core.NewHeaderChain(db, chainConfig, engine, func() bool { - return true - }) + headerChain, chainConfig, err := simpleHeaderChain(db, genesisHash) if err != nil { return err } @@ -722,14 +727,36 @@ func exportSegment(ctx *cli.Context) error { if !chainConfig.IsLuban(latest.Number) { return errors.New("current chain is not enable Luban hard fork, cannot generate history segment") } + + var ( + boundStartBlock uint64 + historySegmentLength uint64 + ) + switch genesisHash { + case params.BSCGenesisHash, params.ChapelGenesisHash, params.RialtoGenesisHash: + boundStartBlock = params.BoundStartBlock + historySegmentLength = params.HistorySegmentLength + default: + if ctx.IsSet(utils.BoundStartBlockFlag.Name) { + boundStartBlock = ctx.Uint64(utils.BoundStartBlockFlag.Name) + } + if ctx.IsSet(utils.HistorySegmentLengthFlag.Name) { + historySegmentLength = ctx.Uint64(utils.HistorySegmentLengthFlag.Name) + } + } + if boundStartBlock == 0 || historySegmentLength == 0 { + return fmt.Errorf("wrong params, boundStartBlock: %v, historySegmentLength: %v", boundStartBlock, historySegmentLength) + } + latestNum := latest.Number.Uint64() - if latestNum < params.FullImmutabilityThreshold || latestNum < params.BoundStartBlock { + if latestNum < params.FullImmutabilityThreshold || latestNum < boundStartBlock { return errors.New("current chain is too short, less than BoundStartBlock") } target := latestNum - params.FullImmutabilityThreshold - log.Info("start export segment", "from", params.BoundStartBlock, "to", target, "chainCfg", chainConfig) - segs := []params.HisSegment{ + log.Info("start export segment", "from", boundStartBlock, "to", target, "boundStartBlock", boundStartBlock, + "historySegmentLength", historySegmentLength, "chainCfg", chainConfig) + segments := []params.HisSegment{ { Index: 0, StartAtBlock: params.HisBlockInfo{ @@ -739,7 +766,7 @@ func exportSegment(ctx *cli.Context) error { }, } // try find finalized block in every segment boundary - for num := params.BoundStartBlock; num <= target; num += params.HistorySegmentLength { + for num := boundStartBlock; num <= target; num += historySegmentLength { var fs, ft *types.Header for next := num + 1; next <= target; next++ { fs = headerChain.GetHeaderByNumber(next) @@ -755,9 +782,13 @@ func exportSegment(ctx *cli.Context) error { // if there cannot found any finalized block, just skip break } + if ft.Number.Uint64() < num { + // cannot find expect finality blocks, just skip + break + } log.Info("found segment boundary", "startAt", ft.Number, "FinalityAt", fs.Number) - segs = append(segs, params.HisSegment{ - Index: uint64(len(segs)), + segments = append(segments, params.HisSegment{ + Index: uint64(len(segments)), StartAtBlock: params.HisBlockInfo{ Number: ft.Number.Uint64(), Hash: ft.Hash(), @@ -768,11 +799,76 @@ func exportSegment(ctx *cli.Context) error { }, }) } - output, err := json.MarshalIndent(segs, "", "\n") + if err = params.ValidateHisSegments(genesisHash, segments); err != nil { + return err + } + output, err := json.MarshalIndent(segments, "", " ") + if err != nil { + return err + } + out := ctx.String(utils.HistorySegOutputFlag.Name) + outFile, err := os.OpenFile(out, os.O_CREATE|os.O_RDWR, 0644) if err != nil { return err } - fmt.Println(string(output)) + defer outFile.Close() + _, err = outFile.Write(output) + if err != nil { + return err + } + log.Info("write history segment success", "count", len(segments), "path", out) + return nil +} + +func pruneHistorySegments(ctx *cli.Context) error { + stack, _ := makeConfigNode(ctx) + defer stack.Close() + + db := utils.MakeChainDatabase(ctx, stack, false, false) + defer db.Close() + + genesisHash := rawdb.ReadCanonicalHash(db, 0) + headerChain, _, err := simpleHeaderChain(db, genesisHash) + if err != nil { + return err + } + cfg := ¶ms.HistorySegmentConfig{ + CustomPath: "", + Genesis: genesisHash, + } + if ctx.IsSet(utils.HistorySegCustomFlag.Name) { + cfg.CustomPath = ctx.String(utils.HistorySegCustomFlag.Name) + } + hsm, err := params.NewHistorySegmentManager(cfg) + if err != nil { + return err + } + + // get latest 2 segments + latestHeader := headerChain.CurrentHeader() + curSegment := hsm.CurSegment(latestHeader.Number.Uint64()) + prevSegment, ok := hsm.PrevSegment(curSegment) + if !ok { + return fmt.Errorf("there is no enough history to prune, cur: %v", curSegment) + } + + // check segment if match hard code + if err = rawdb.AvailableHistorySegment(db, curSegment, prevSegment); err != nil { + return err + } + + pruneTail := prevSegment.StartAtBlock.Number + log.Info("The older history will be pruned", "prevSegment", prevSegment, "curSegment", curSegment, "pruneTail", pruneTail) + if err = rawdb.PruneTxLookupToTail(db, pruneTail); err != nil { + return err + } + + start := time.Now() + old, err := db.TruncateTail(pruneTail) + if err != nil { + return err + } + log.Info("TruncateTail in freezerDB", "old", old, "now", pruneTail, "elapsed", common.PrettyDuration(time.Since(start))) return nil } @@ -781,3 +877,24 @@ func hashish(x string) bool { _, err := strconv.Atoi(x) return err != nil } + +func simpleHeaderChain(db ethdb.Database, genesisHash common.Hash) (*core.HeaderChain, *params.ChainConfig, error) { + chainConfig := rawdb.ReadChainConfig(db, genesisHash) + if chainConfig == nil { + return nil, nil, errors.New("failed to load chainConfig") + } + engine, err := ethconfig.CreateConsensusEngine(chainConfig, db, nil, genesisHash) + if err != nil { + return nil, nil, err + } + if _, ok := engine.(consensus.PoSA); !ok { + return nil, nil, errors.New("current chain is not POSA, cannot generate history segment") + } + headerChain, err := core.NewHeaderChain(db, chainConfig, engine, func() bool { + return true + }) + if err != nil { + return nil, nil, err + } + return headerChain, chainConfig, nil +} diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 27f77d5015..c2d09f9d93 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -170,6 +170,8 @@ var ( utils.BLSPasswordFileFlag, utils.BLSWalletDirFlag, utils.VoteJournalDirFlag, + utils.HistorySegEnableFlag, + utils.HistorySegCustomFlag, }, utils.NetworkFlags, utils.DatabasePathFlags) rpcFlags = []cli.Flag{ @@ -261,6 +263,8 @@ func init() { blsCommand, // See verkle.go verkleCommand, + exportSegmentCommand, + pruneHistorySegmentsCommand, } sort.Sort(cli.CommandsByName(app.Commands)) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 915e966eb9..cdbe49a1a1 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1128,11 +1128,36 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server. Category: flags.FastFinalityCategory, } - // Export history segment + // History segment + HistorySegEnableFlag = &cli.BoolFlag{ + Name: "history-segment", + Usage: "Enable history segment feature, it will auto prune history segments by hard-code segment hash", + Value: false, + Category: flags.HistoryCategory, + } + HistorySegCustomFlag = &cli.StringFlag{ + Name: "history-segment.custom", + Usage: "Specific history segments custom definition", + Value: "./history_segments.json", + Category: flags.HistoryCategory, + } HistorySegOutputFlag = &cli.StringFlag{ - Name: "output", - Usage: "Specific history segments output file name & type", - Value: "./gen_history_segments.go", + Name: "history-segment.output", + Usage: "Specific history segments output file", + Value: "./history_segments.json", + Category: flags.HistoryCategory, + } + BoundStartBlockFlag = &cli.Uint64Flag{ + Name: "history-segment.boundstart", + Usage: "Specific history segments BoundStartBlock, it indicate segment1 start block", + Value: params.BoundStartBlock, + Category: flags.HistoryCategory, + } + HistorySegmentLengthFlag = &cli.Uint64Flag{ + Name: "history-segment.segmentlen", + Usage: "Specific history segments HistorySegmentLength", + Value: params.HistorySegmentLength, + Category: flags.HistoryCategory, } ) @@ -2155,6 +2180,14 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { if err := kzg4844.UseCKZG(ctx.String(CryptoKZGFlag.Name) == "ckzg"); err != nil { Fatalf("Failed to set KZG library implementation to %s: %v", ctx.String(CryptoKZGFlag.Name), err) } + + // parse History Segment flags + if ctx.IsSet(HistorySegEnableFlag.Name) { + cfg.HistorySegmentEnable = ctx.Bool(HistorySegEnableFlag.Name) + } + if ctx.IsSet(HistorySegCustomFlag.Name) { + cfg.HistorySegmentCustomFile = ctx.String(HistorySegCustomFlag.Name) + } } // SetDNSDiscoveryDefaults configures DNS discovery with the given URL if diff --git a/core/genesis.go b/core/genesis.go index 86f6a1ef85..47f316c258 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/systemcontracts" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" @@ -321,7 +322,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen } // Just commit the new block if there is no stored genesis block. stored := rawdb.ReadCanonicalHash(db, 0) - params.LocalGenesisHash = stored + systemcontracts.GenesisHash = stored if (stored == common.Hash{}) { if genesis == nil { log.Info("Writing default BSC mainnet genesis block") diff --git a/core/rawdb/history_segment.go b/core/rawdb/history_segment.go new file mode 100644 index 0000000000..d3c0211af1 --- /dev/null +++ b/core/rawdb/history_segment.go @@ -0,0 +1,77 @@ +package rawdb + +import ( + "bytes" + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/params" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" +) + +// PruneTxLookupToTail it will iterator tx look up and delete to tail +func PruneTxLookupToTail(db ethdb.KeyValueStore, tail uint64) error { + indexTail := ReadTxIndexTail(db) + if tail == 0 || tail <= *indexTail { + return nil + } + + var ( + start = time.Now() + logged = time.Now() + txlookups stat + + batch = db.NewBatch() + iter = db.NewIterator(txLookupPrefix, nil) + ) + + for iter.Next() { + key := iter.Key() + val := iter.Value() + if !bytes.HasPrefix(key, txLookupPrefix) || len(key) != (len(txLookupPrefix)+common.HashLength) { + continue + } + txlookups.Add(common.StorageSize(len(key) + len(val))) + // check if need delete current tx index + number := new(big.Int).SetBytes(val).Uint64() + if number >= tail { + continue + } + + batch.Delete(key) + if batch.ValueSize() > ethdb.IdealBatchSize { + if err := batch.Write(); err != nil { + return err + } + batch.Reset() + } + if time.Since(logged) > 30*time.Second { + log.Info("PruneTxLookupToTail", "count", txlookups.Count(), "size", txlookups.Size(), "elapsed", common.PrettyDuration(time.Since(start))) + logged = time.Now() + } + } + WriteTxIndexTail(batch, tail) + if err := batch.Write(); err != nil { + return err + } + log.Info("PruneTxLookupToTail finish", "count", txlookups.Count(), "size", txlookups.Size(), "elapsed", common.PrettyDuration(time.Since(start))) + return nil +} + +func AvailableHistorySegment(db ethdb.Reader, segments ...params.HisSegment) error { + for _, s := range segments { + hash := ReadCanonicalHash(db, s.StartAtBlock.Number) + if hash != s.StartAtBlock.Hash { + return fmt.Errorf("cannot find segment StartAtBlock, seg: %v", s) + } + hash = ReadCanonicalHash(db, s.FinalityAtBlock.Number) + if hash != s.FinalityAtBlock.Hash { + return fmt.Errorf("cannot find segment FinalityAtBlock, seg: %v", s) + } + } + return nil +} diff --git a/core/systemcontracts/upgrade.go b/core/systemcontracts/upgrade.go index 7ff3776d25..26650673b8 100644 --- a/core/systemcontracts/upgrade.go +++ b/core/systemcontracts/upgrade.go @@ -34,6 +34,7 @@ const ( ) var ( + GenesisHash common.Hash // upgrade config ramanujanUpgrade = make(map[string]*Upgrade) @@ -556,7 +557,7 @@ func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.I return } var network string - switch params.LocalGenesisHash { + switch GenesisHash { /* Add mainnet genesis hash */ case params.BSCGenesisHash: network = mainNet diff --git a/eth/backend.go b/eth/backend.go index bf4ad84962..7dfd6e049a 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -23,6 +23,7 @@ import ( "math/big" "runtime" "sync" + "time" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" @@ -184,6 +185,13 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { overrides.OverrideVerkle = config.OverrideVerkle } + // if enable history segment, try prune ancient data when restart + if config.HistorySegmentEnable { + if err = truncateAncientTail(chainDb, genesisHash, config.HistorySegmentCustomFile); err != nil { + return nil, err + } + } + eth := &Ethereum{ config: config, merger: consensus.NewMerger(chainDb), @@ -259,7 +267,12 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { peers := newPeerSet() bcOps = append(bcOps, core.EnableBlockValidator(chainConfig, eth.engine, config.TriesVerifyMode, peers)) - eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory, bcOps...) + txLookupLimit := &config.TransactionHistory + // if enable HistorySegment, just skip txLookupLimit params, may cause regenerate tx index + if config.HistorySegmentEnable { + txLookupLimit = nil + } + eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, txLookupLimit, bcOps...) if err != nil { return nil, err } @@ -375,6 +388,38 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { return eth, nil } +func truncateAncientTail(db ethdb.Database, genesisHash common.Hash, CustomPath string) error { + hsm, err := params.NewHistorySegmentManager(¶ms.HistorySegmentConfig{ + CustomPath: CustomPath, + Genesis: genesisHash, + }) + if err != nil { + return err + } + + // get latest 2 segments + latestHeader := rawdb.ReadHeadHeader(db) + curSegment := hsm.CurSegment(latestHeader.Number.Uint64()) + prevSegment, ok := hsm.PrevSegment(curSegment) + if !ok { + return fmt.Errorf("there is no enough history to prune, cur: %v", curSegment) + } + + // check segment if match hard code + if err = rawdb.AvailableHistorySegment(db, curSegment, prevSegment); err != nil { + return err + } + + pruneTail := prevSegment.StartAtBlock.Number + start := time.Now() + old, err := db.TruncateTail(pruneTail) + if err != nil { + return err + } + log.Info("TruncateTail in freezerDB", "old", old, "now", pruneTail, "elapsed", common.PrettyDuration(time.Since(start))) + return nil +} + func makeExtraData(extra []byte) []byte { if len(extra) == 0 { // create default extradata diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 16e6984bda..8488af5f41 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -203,6 +203,10 @@ type Config struct { // OverrideVerkle (TODO: remove after the fork) OverrideVerkle *uint64 `toml:",omitempty"` + + // History Segment + HistorySegmentEnable bool `toml:",omitempty"` + HistorySegmentCustomFile string `toml:",omitempty"` } // CreateConsensusEngine creates a consensus engine for the given chain config. diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index 729e108afb..61137241eb 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -17,62 +17,64 @@ import ( // MarshalTOML marshals as TOML. func (c Config) MarshalTOML() (interface{}, error) { type Config struct { - Genesis *core.Genesis `toml:",omitempty"` - NetworkId uint64 - SyncMode downloader.SyncMode - DisablePeerTxBroadcast bool - EthDiscoveryURLs []string - SnapDiscoveryURLs []string - TrustDiscoveryURLs []string - BscDiscoveryURLs []string - NoPruning bool - NoPrefetch bool - DirectBroadcast bool - DisableSnapProtocol bool - EnableTrustProtocol bool - PipeCommit bool - RangeLimit bool - TxLookupLimit uint64 `toml:",omitempty"` - TransactionHistory uint64 `toml:",omitempty"` - StateHistory uint64 `toml:",omitempty"` - StateScheme string `toml:",omitempty"` - PathSyncFlush bool `toml:",omitempty"` - RequiredBlocks map[uint64]common.Hash `toml:"-"` - LightServ int `toml:",omitempty"` - LightIngress int `toml:",omitempty"` - LightEgress int `toml:",omitempty"` - LightPeers int `toml:",omitempty"` - LightNoPrune bool `toml:",omitempty"` - LightNoSyncServe bool `toml:",omitempty"` - SkipBcVersionCheck bool `toml:"-"` - DatabaseHandles int `toml:"-"` - DatabaseCache int - DatabaseFreezer string - DatabaseDiff string - PersistDiff bool - DiffBlock uint64 - PruneAncientData bool - TrieCleanCache int - TrieDirtyCache int - TrieTimeout time.Duration - SnapshotCache int - TriesInMemory uint64 - TriesVerifyMode core.VerifyMode - Preimages bool - FilterLogCacheSize int - Miner miner.Config - TxPool legacypool.Config - BlobPool blobpool.Config - GPO gasprice.Config - EnablePreimageRecording bool - DocRoot string `toml:"-"` - RPCGasCap uint64 - RPCEVMTimeout time.Duration - RPCTxFeeCap float64 - OverrideShanghai *uint64 `toml:",omitempty"` - OverrideKepler *uint64 `toml:",omitempty"` - OverrideCancun *uint64 `toml:",omitempty"` - OverrideVerkle *uint64 `toml:",omitempty"` + Genesis *core.Genesis `toml:",omitempty"` + NetworkId uint64 + SyncMode downloader.SyncMode + DisablePeerTxBroadcast bool + EthDiscoveryURLs []string + SnapDiscoveryURLs []string + TrustDiscoveryURLs []string + BscDiscoveryURLs []string + NoPruning bool + NoPrefetch bool + DirectBroadcast bool + DisableSnapProtocol bool + EnableTrustProtocol bool + PipeCommit bool + RangeLimit bool + TxLookupLimit uint64 `toml:",omitempty"` + TransactionHistory uint64 `toml:",omitempty"` + StateHistory uint64 `toml:",omitempty"` + StateScheme string `toml:",omitempty"` + PathSyncFlush bool `toml:",omitempty"` + RequiredBlocks map[uint64]common.Hash `toml:"-"` + LightServ int `toml:",omitempty"` + LightIngress int `toml:",omitempty"` + LightEgress int `toml:",omitempty"` + LightPeers int `toml:",omitempty"` + LightNoPrune bool `toml:",omitempty"` + LightNoSyncServe bool `toml:",omitempty"` + SkipBcVersionCheck bool `toml:"-"` + DatabaseHandles int `toml:"-"` + DatabaseCache int + DatabaseFreezer string + DatabaseDiff string + PersistDiff bool + DiffBlock uint64 + PruneAncientData bool + TrieCleanCache int + TrieDirtyCache int + TrieTimeout time.Duration + SnapshotCache int + TriesInMemory uint64 + TriesVerifyMode core.VerifyMode + Preimages bool + FilterLogCacheSize int + Miner miner.Config + TxPool legacypool.Config + BlobPool blobpool.Config + GPO gasprice.Config + EnablePreimageRecording bool + DocRoot string `toml:"-"` + RPCGasCap uint64 + RPCEVMTimeout time.Duration + RPCTxFeeCap float64 + OverrideShanghai *uint64 `toml:",omitempty"` + OverrideKepler *uint64 `toml:",omitempty"` + OverrideCancun *uint64 `toml:",omitempty"` + OverrideVerkle *uint64 `toml:",omitempty"` + HistorySegmentEnable bool `toml:",omitempty"` + HistorySegmentCustomFile string `toml:",omitempty"` } var enc Config enc.Genesis = c.Genesis @@ -131,68 +133,72 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.OverrideKepler = c.OverrideKepler enc.OverrideCancun = c.OverrideCancun enc.OverrideVerkle = c.OverrideVerkle + enc.HistorySegmentEnable = c.HistorySegmentEnable + enc.HistorySegmentCustomFile = c.HistorySegmentCustomFile return &enc, nil } // UnmarshalTOML unmarshals from TOML. func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { type Config struct { - Genesis *core.Genesis `toml:",omitempty"` - NetworkId *uint64 - SyncMode *downloader.SyncMode - DisablePeerTxBroadcast *bool - EthDiscoveryURLs []string - SnapDiscoveryURLs []string - TrustDiscoveryURLs []string - BscDiscoveryURLs []string - NoPruning *bool - NoPrefetch *bool - DirectBroadcast *bool - DisableSnapProtocol *bool - EnableTrustProtocol *bool - PipeCommit *bool - RangeLimit *bool - TxLookupLimit *uint64 `toml:",omitempty"` - TransactionHistory *uint64 `toml:",omitempty"` - StateHistory *uint64 `toml:",omitempty"` - StateScheme *string `toml:",omitempty"` - PathSyncFlush *bool `toml:",omitempty"` - RequiredBlocks map[uint64]common.Hash `toml:"-"` - LightServ *int `toml:",omitempty"` - LightIngress *int `toml:",omitempty"` - LightEgress *int `toml:",omitempty"` - LightPeers *int `toml:",omitempty"` - LightNoPrune *bool `toml:",omitempty"` - LightNoSyncServe *bool `toml:",omitempty"` - SkipBcVersionCheck *bool `toml:"-"` - DatabaseHandles *int `toml:"-"` - DatabaseCache *int - DatabaseFreezer *string - DatabaseDiff *string - PersistDiff *bool - DiffBlock *uint64 - PruneAncientData *bool - TrieCleanCache *int - TrieDirtyCache *int - TrieTimeout *time.Duration - SnapshotCache *int - TriesInMemory *uint64 - TriesVerifyMode *core.VerifyMode - Preimages *bool - FilterLogCacheSize *int - Miner *miner.Config - TxPool *legacypool.Config - BlobPool *blobpool.Config - GPO *gasprice.Config - EnablePreimageRecording *bool - DocRoot *string `toml:"-"` - RPCGasCap *uint64 - RPCEVMTimeout *time.Duration - RPCTxFeeCap *float64 - OverrideShanghai *uint64 `toml:",omitempty"` - OverrideKepler *uint64 `toml:",omitempty"` - OverrideCancun *uint64 `toml:",omitempty"` - OverrideVerkle *uint64 `toml:",omitempty"` + Genesis *core.Genesis `toml:",omitempty"` + NetworkId *uint64 + SyncMode *downloader.SyncMode + DisablePeerTxBroadcast *bool + EthDiscoveryURLs []string + SnapDiscoveryURLs []string + TrustDiscoveryURLs []string + BscDiscoveryURLs []string + NoPruning *bool + NoPrefetch *bool + DirectBroadcast *bool + DisableSnapProtocol *bool + EnableTrustProtocol *bool + PipeCommit *bool + RangeLimit *bool + TxLookupLimit *uint64 `toml:",omitempty"` + TransactionHistory *uint64 `toml:",omitempty"` + StateHistory *uint64 `toml:",omitempty"` + StateScheme *string `toml:",omitempty"` + PathSyncFlush *bool `toml:",omitempty"` + RequiredBlocks map[uint64]common.Hash `toml:"-"` + LightServ *int `toml:",omitempty"` + LightIngress *int `toml:",omitempty"` + LightEgress *int `toml:",omitempty"` + LightPeers *int `toml:",omitempty"` + LightNoPrune *bool `toml:",omitempty"` + LightNoSyncServe *bool `toml:",omitempty"` + SkipBcVersionCheck *bool `toml:"-"` + DatabaseHandles *int `toml:"-"` + DatabaseCache *int + DatabaseFreezer *string + DatabaseDiff *string + PersistDiff *bool + DiffBlock *uint64 + PruneAncientData *bool + TrieCleanCache *int + TrieDirtyCache *int + TrieTimeout *time.Duration + SnapshotCache *int + TriesInMemory *uint64 + TriesVerifyMode *core.VerifyMode + Preimages *bool + FilterLogCacheSize *int + Miner *miner.Config + TxPool *legacypool.Config + BlobPool *blobpool.Config + GPO *gasprice.Config + EnablePreimageRecording *bool + DocRoot *string `toml:"-"` + RPCGasCap *uint64 + RPCEVMTimeout *time.Duration + RPCTxFeeCap *float64 + OverrideShanghai *uint64 `toml:",omitempty"` + OverrideKepler *uint64 `toml:",omitempty"` + OverrideCancun *uint64 `toml:",omitempty"` + OverrideVerkle *uint64 `toml:",omitempty"` + HistorySegmentEnable *bool `toml:",omitempty"` + HistorySegmentCustomFile *string `toml:",omitempty"` } var dec Config if err := unmarshal(&dec); err != nil { @@ -366,5 +372,11 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.OverrideVerkle != nil { c.OverrideVerkle = dec.OverrideVerkle } + if dec.HistorySegmentEnable != nil { + c.HistorySegmentEnable = *dec.HistorySegmentEnable + } + if dec.HistorySegmentCustomFile != nil { + c.HistorySegmentCustomFile = *dec.HistorySegmentCustomFile + } return nil } diff --git a/params/config.go b/params/config.go index 083e5346e6..2aad8f1d71 100644 --- a/params/config.go +++ b/params/config.go @@ -30,8 +30,6 @@ var ( BSCGenesisHash = common.HexToHash("0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b") ChapelGenesisHash = common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34") RialtoGenesisHash = common.HexToHash("0xee835a629f9cf5510b48b6ba41d69e0ff7d6ef10f977166ef939db41f59f5501") - - LocalGenesisHash common.Hash // it will be initial by user program, aim to indicate testnet, mainnet, or other chain ) func newUint64(val uint64) *uint64 { return &val } @@ -1096,10 +1094,6 @@ func configTimestampEqual(x, y *uint64) bool { return *x == *y } -func SetupLocalGenesisHash(h common.Hash) { - LocalGenesisHash = h -} - // ConfigCompatError is raised if the locally-stored blockchain is initialised with a // ChainConfig that would alter the past. type ConfigCompatError struct { diff --git a/params/history_segment.go b/params/history_segment.go index a33990f1ef..59153304c0 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -2,6 +2,9 @@ package params import ( "encoding/json" + "errors" + "fmt" + "os" "github.com/ethereum/go-ethereum/common" ) @@ -12,29 +15,60 @@ const ( ) var ( - historySegmentsInBSCMainnet = unmarshalHisSegments(` -{ - { - index: 0, - start_at_block: { - number: 0, - hash: 0x0000000000000000000000000000000000000000000000000000000000000000 - } + historySegmentsInBSCMainnet = []HisSegment{ + { + Index: 0, + StartAtBlock: HisBlockInfo{ + Number: 0, + Hash: BSCGenesisHash, + }, + }, } -} -`) historySegmentsInBSCChapel = unmarshalHisSegments(` -{ - { - index: 0, - start_at_block: { - number: 0, - hash: 0x0000000000000000000000000000000000000000000000000000000000000000 - } +[ + { + "index": 0, + "start_at_block": { + "number": 0, + "hash": "0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34" + }, + "finality_at_block": { + "number": 0, + "hash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + { + "index": 1, + "start_at_block": { + "number": 31268530, + "hash": "0x2ab32e1541202ac43f3dc9ff80b998002ad9130ecc24c40a1f00a8e45dc1f786" + }, + "finality_at_block": { + "number": 31268532, + "hash": "0x59203b593d2e4c213e65f68db2c19309380416a93592aa8f923d59aebc481c28" + } + }, + { + "index": 2, + "start_at_block": { + "number": 33860530, + "hash": "0x252e966e2420ecb2c5c51da62f147ac89004943e2b76c343bb1b2d8465f29a29" + }, + "finality_at_block": { + "number": 33860532, + "hash": "0x424e526d901ae91897340655c81db7de16428a3322df4fa712693bda83572f8f" + } + } +]`) + historySegmentsInBSCRialto = []HisSegment{ + { + Index: 0, + StartAtBlock: HisBlockInfo{ + Number: 0, + Hash: RialtoGenesisHash, + }, + }, } -} -`) - historySegmentsInBSCRialto []HisSegment ) type HisBlockInfo struct { @@ -49,22 +83,100 @@ type HisSegment struct { // TODO(0xbundler): if need add more finality evidence? like signature? } -func HisSegments() []HisSegment { - switch LocalGenesisHash { +func (h *HisSegment) String() string { + return fmt.Sprintf("[Index: %v, StartAt: %v, FinalityAt: %v]", h.Index, h.StartAtBlock, h.FinalityAtBlock) +} + +type HistorySegmentConfig struct { + CustomPath string // custom HistorySegments file path, need read from the file + Genesis common.Hash // specific chain genesis, it may use hard-code config +} + +func (cfg *HistorySegmentConfig) LoadCustomSegments() ([]HisSegment, error) { + if _, err := os.Stat(cfg.CustomPath); err != nil { + return nil, err + } + enc, err := os.ReadFile(cfg.CustomPath) + if err != nil { + return nil, err + } + var ret []HisSegment + if err = json.Unmarshal(enc, &ret); err != nil { + return nil, err + } + return ret, nil +} + +type HistorySegmentManager struct { + segments []HisSegment + cfg *HistorySegmentConfig +} + +func NewHistorySegmentManager(cfg *HistorySegmentConfig) (*HistorySegmentManager, error) { + if cfg == nil { + return nil, errors.New("cannot init HistorySegmentManager by nil config") + } + + // if genesis is one of the hard code history segment, just ignore input custom file + var ( + segments []HisSegment + err error + ) + switch cfg.Genesis { case BSCGenesisHash: - return historySegmentsInBSCMainnet + segments = historySegmentsInBSCMainnet case ChapelGenesisHash: - return historySegmentsInBSCChapel + segments = historySegmentsInBSCChapel case RialtoGenesisHash: - return historySegmentsInBSCRialto + segments = historySegmentsInBSCRialto default: - panic("sorry, this chain is not support history block segment, or init with wrong genesis hash") + segments, err = cfg.LoadCustomSegments() + if err != nil { + return nil, err + } + } + if err = ValidateHisSegments(cfg.Genesis, segments); err != nil { + return nil, err } + return &HistorySegmentManager{ + segments: segments, + cfg: cfg, + }, nil } -// CurrentSegment return which segment include this block -func CurrentSegment(num uint64) HisSegment { - segments := HisSegments() +func ValidateHisSegments(genesis common.Hash, segments []HisSegment) error { + if len(segments) == 0 { + return errors.New("history segment length cannot be 0") + } + expectSeg0 := HisSegment{ + Index: 0, + StartAtBlock: HisBlockInfo{ + Number: 0, + Hash: genesis, + }, + } + if segments[0] != expectSeg0 { + return fmt.Errorf("wrong segement0 start block, it must be genesis, expect: %v, actual: %v", expectSeg0, segments[0]) + } + for i := 1; i < len(segments); i++ { + if segments[i].Index != uint64(i) || + segments[i].StartAtBlock.Number <= segments[i-1].StartAtBlock.Number || + segments[i].StartAtBlock.Number+2 > segments[i].FinalityAtBlock.Number { + return fmt.Errorf("wrong segement, index: %v, segment: %v", i, segments[i]) + } + } + + return nil +} + +// HisSegments return all history segments +func (m *HistorySegmentManager) HisSegments() []HisSegment { + return m.segments +} + +// CurSegment return which segment include this block +func (m *HistorySegmentManager) CurSegment(num uint64) HisSegment { + segments := m.HisSegments() i := len(segments) - 1 for i >= 0 { if segments[i].StartAtBlock.Number <= num { @@ -75,10 +187,10 @@ func CurrentSegment(num uint64) HisSegment { return segments[i] } -// FindPrevSegment return the current's last segment, because the latest 2 segments is available, +// PrevSegment return the current's last segment, because the latest 2 segments is available, // so user could keep current & prev segment -func FindPrevSegment(cur HisSegment) (HisSegment, bool) { - segments := HisSegments() +func (m *HistorySegmentManager) PrevSegment(cur HisSegment) (HisSegment, bool) { + segments := m.HisSegments() if cur.Index == 0 || cur.Index >= uint64(len(segments)) { return HisSegment{}, false } @@ -87,6 +199,9 @@ func FindPrevSegment(cur HisSegment) (HisSegment, bool) { func unmarshalHisSegments(enc string) []HisSegment { var ret []HisSegment - json.Unmarshal([]byte(enc), &ret) + err := json.Unmarshal([]byte(enc), &ret) + if err != nil { + panic(err) + } return ret } diff --git a/params/history_segment_test.go b/params/history_segment_test.go index e795dd5ae6..7198b95c38 100644 --- a/params/history_segment_test.go +++ b/params/history_segment_test.go @@ -9,9 +9,8 @@ import ( "github.com/ethereum/go-ethereum/common" ) -func init() { - LocalGenesisHash = RialtoGenesisHash - historySegmentsInBSCRialto = []HisSegment{ +var ( + historySegmentsInTest = []HisSegment{ { Index: 0, StartAtBlock: HisBlockInfo{ @@ -42,34 +41,156 @@ func init() { }, }, } + testGenesis = common.HexToHash("0x50b168d3ba07cc77c13a5469b9a1aad8752ba725ff989b76bc7df89dc936e866") +) + +func TestNewHisSegmentManager_HardCode(t *testing.T) { + tests := []struct { + cfg *HistorySegmentConfig + }{ + { + cfg: &HistorySegmentConfig{ + CustomPath: "", + Genesis: BSCGenesisHash, + }, + }, + { + cfg: &HistorySegmentConfig{ + CustomPath: "", + Genesis: ChapelGenesisHash, + }, + }, + { + cfg: &HistorySegmentConfig{ + CustomPath: "", + Genesis: RialtoGenesisHash, + }, + }, + } + for i, item := range tests { + _, err := NewHistorySegmentManager(item.cfg) + assert.NoError(t, err, i) + } +} + +func TestHisSegmentManager_Validate(t *testing.T) { + tests := []struct { + genesis common.Hash + segments []HisSegment + err bool + }{ + { + genesis: testGenesis, + segments: []HisSegment{ + { + Index: 1, + StartAtBlock: HisBlockInfo{ + Number: 1, + Hash: common.Hash{}, + }, + }, + }, + err: true, + }, + { + genesis: testGenesis, + segments: []HisSegment{ + { + Index: 0, + StartAtBlock: HisBlockInfo{ + Number: 0, + Hash: testGenesis, + }, + }, + }, + }, + { + genesis: testGenesis, + segments: []HisSegment{ + { + Index: 0, + StartAtBlock: HisBlockInfo{ + Number: 0, + Hash: testGenesis, + }, + }, + { + Index: 1, + StartAtBlock: HisBlockInfo{ + Number: 1, + Hash: common.HexToHash("0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7"), + }, + }, + }, + err: true, + }, + { + genesis: testGenesis, + segments: []HisSegment{ + { + Index: 0, + StartAtBlock: HisBlockInfo{ + Number: 0, + Hash: testGenesis, + }, + }, + { + Index: 1, + StartAtBlock: HisBlockInfo{ + Number: 1, + Hash: common.HexToHash("0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7"), + }, + FinalityAtBlock: HisBlockInfo{ + Number: 3, + Hash: common.HexToHash("0xb22bf5eb6fe8ed39894d32b148fdedd91bd11497e7744e6c84c6b104aa577a15"), + }, + }, + }, + }, + } + for i, item := range tests { + err := ValidateHisSegments(item.genesis, item.segments) + if item.err { + assert.Error(t, err, i) + continue + } + assert.NoError(t, err, i) + } } func TestUnmarshalHisSegments(t *testing.T) { - enc, err := json.MarshalIndent(HisSegments(), "", " ") + enc, err := json.MarshalIndent(historySegmentsInTest, "", " ") assert.NoError(t, err) - t.Log(string(enc)) + //t.Log(string(enc)) segments := unmarshalHisSegments(string(enc)) - assert.Equal(t, HisSegments(), segments) + assert.Equal(t, historySegmentsInTest, segments) } func TestIndexSegment(t *testing.T) { - segments := HisSegments() - assert.Equal(t, segments[0], CurrentSegment(0)) - assert.Equal(t, segments[0], CurrentSegment(BoundStartBlock-1)) - assert.Equal(t, segments[1], CurrentSegment(BoundStartBlock)) - assert.Equal(t, segments[1], CurrentSegment(BoundStartBlock+HistorySegmentLength-1)) - assert.Equal(t, segments[2], CurrentSegment(BoundStartBlock+HistorySegmentLength)) - assert.Equal(t, segments[2], CurrentSegment(BoundStartBlock+HistorySegmentLength*2)) + segments := historySegmentsInTest + hsm := HistorySegmentManager{ + segments: historySegmentsInTest, + } + assert.Equal(t, segments[0], hsm.CurSegment(0)) + assert.Equal(t, segments[0], hsm.CurSegment(BoundStartBlock-1)) + assert.Equal(t, segments[1], hsm.CurSegment(BoundStartBlock)) + assert.Equal(t, segments[1], hsm.CurSegment(BoundStartBlock+HistorySegmentLength-1)) + assert.Equal(t, segments[2], hsm.CurSegment(BoundStartBlock+HistorySegmentLength)) + assert.Equal(t, segments[2], hsm.CurSegment(BoundStartBlock+HistorySegmentLength*2)) - prev, ok := FindPrevSegment(segments[0]) + var ( + prev HisSegment + ok bool + ) + _, ok = hsm.PrevSegment(segments[0]) assert.Equal(t, false, ok) - prev, ok = FindPrevSegment(segments[1]) + prev, ok = hsm.PrevSegment(segments[1]) assert.Equal(t, true, ok) assert.Equal(t, segments[0], prev) - prev, ok = FindPrevSegment(segments[2]) + prev, ok = hsm.PrevSegment(segments[2]) assert.Equal(t, true, ok) assert.Equal(t, segments[1], prev) - _, ok = FindPrevSegment(HisSegment{ + _, ok = hsm.PrevSegment(HisSegment{ Index: uint64(len(segments)), }) assert.Equal(t, false, ok) From 81c48aee6140734f0722f77dd33aeca797115c00 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Thu, 23 Nov 2023 00:11:57 +0800 Subject: [PATCH 06/22] historysegment: add offline history segments tool; --- params/history_segment.go | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/params/history_segment.go b/params/history_segment.go index 59153304c0..49effa32c3 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -15,15 +15,31 @@ const ( ) var ( - historySegmentsInBSCMainnet = []HisSegment{ - { - Index: 0, - StartAtBlock: HisBlockInfo{ - Number: 0, - Hash: BSCGenesisHash, - }, - }, - } + historySegmentsInBSCMainnet = unmarshalHisSegments(` +[ + { + "index": 0, + "start_at_block": { + "number": 0, + "hash": "0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b" + }, + "finality_at_block": { + "number": 0, + "hash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + { + "index": 1, + "start_at_block": { + "number": 31268530, + "hash": "0xdb8a505f19ef04cb21ae79e3cb641963ffc44f3666e6fde499be55a72b6c7865" + }, + "finality_at_block": { + "number": 31268532, + "hash": "0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7" + } + } +]`) historySegmentsInBSCChapel = unmarshalHisSegments(` [ { From f1dfe1b6fdc6aab8974415ceeea588e5f4174fda Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Thu, 23 Nov 2023 10:46:00 +0800 Subject: [PATCH 07/22] historysegment: add offline history segments tool; --- cmd/geth/chaincmd.go | 7 ++++++- eth/backend.go | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 65350acc68..0cbffb1925 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -753,6 +753,7 @@ func exportSegment(ctx *cli.Context) error { return errors.New("current chain is too short, less than BoundStartBlock") } + start := time.Now() target := latestNum - params.FullImmutabilityThreshold log.Info("start export segment", "from", boundStartBlock, "to", target, "boundStartBlock", boundStartBlock, "historySegmentLength", historySegmentLength, "chainCfg", chainConfig) @@ -806,6 +807,8 @@ func exportSegment(ctx *cli.Context) error { if err != nil { return err } + log.Info("Generate History Segment done", "count", len(segments), "elapsed", common.PrettyDuration(time.Since(start))) + out := ctx.String(utils.HistorySegOutputFlag.Name) outFile, err := os.OpenFile(out, os.O_CREATE|os.O_RDWR, 0644) if err != nil { @@ -816,7 +819,7 @@ func exportSegment(ctx *cli.Context) error { if err != nil { return err } - log.Info("write history segment success", "count", len(segments), "path", out) + log.Info("write history segment success", "path", out) return nil } @@ -868,6 +871,8 @@ func pruneHistorySegments(ctx *cli.Context) error { if err != nil { return err } + // update prune offset + rawdb.WriteOffSetOfCurrentAncientFreezer(db, pruneTail) log.Info("TruncateTail in freezerDB", "old", old, "now", pruneTail, "elapsed", common.PrettyDuration(time.Since(start))) return nil } diff --git a/eth/backend.go b/eth/backend.go index 7dfd6e049a..5911cb3ff1 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -416,6 +416,8 @@ func truncateAncientTail(db ethdb.Database, genesisHash common.Hash, CustomPath if err != nil { return err } + // update prune offset + rawdb.WriteOffSetOfCurrentAncientFreezer(db, pruneTail) log.Info("TruncateTail in freezerDB", "old", old, "now", pruneTail, "elapsed", common.PrettyDuration(time.Since(start))) return nil } From e5d0d2473b0e1a09e16148c78a82a1a4949004dd Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Thu, 23 Nov 2023 11:10:20 +0800 Subject: [PATCH 08/22] dbcmd: opt ancient inspect tool; --- cmd/geth/chaincmd.go | 2 -- cmd/geth/dbcmd.go | 4 ++-- consensus/parlia/parlia.go | 16 +++++++++------- core/rawdb/database.go | 37 ++++++++++++++++++++++++++++++++++--- eth/backend.go | 2 -- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 0cbffb1925..4dffb30051 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -871,8 +871,6 @@ func pruneHistorySegments(ctx *cli.Context) error { if err != nil { return err } - // update prune offset - rawdb.WriteOffSetOfCurrentAncientFreezer(db, pruneTail) log.Info("TruncateTail in freezerDB", "old", old, "now", pruneTail, "elapsed", common.PrettyDuration(time.Since(start))) return nil } diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 275dc1fa50..4a2b930866 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -257,7 +257,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, } ancientInspectCmd = &cli.Command{ Action: ancientInspect, - Name: "inspect-reserved-oldest-blocks", + Name: "inspect-ancient", Flags: []cli.Flag{ utils.DataDirFlag, }, @@ -448,7 +448,7 @@ func ancientInspect(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() - db := utils.MakeChainDatabase(ctx, stack, true, true) + db := utils.MakeChainDatabase(ctx, stack, true, false) defer db.Close() return rawdb.AncientInspect(db) } diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index f2ae2d86f1..deffd06d8f 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -1710,13 +1710,15 @@ func (p *Parlia) applyTransaction( } actualTx := (*receivedTxs)[0] if !bytes.Equal(p.signer.Hash(actualTx).Bytes(), expectedHash.Bytes()) { - return fmt.Errorf("expected tx hash %v, get %v, nonce %d, to %s, value %s, gas %d, gasPrice %s, data %s", expectedHash.String(), actualTx.Hash().String(), - expectedTx.Nonce(), - expectedTx.To().String(), - expectedTx.Value().String(), - expectedTx.Gas(), - expectedTx.GasPrice().String(), - hex.EncodeToString(expectedTx.Data()), + return fmt.Errorf("expected tx hash %v:%v, nonce %d:%d, to %s:%s, value %s:%s, gas %d:%d, gasPrice %s:%s, data %s:%s, dbErr: %v", + expectedHash.String(), actualTx.Hash().String(), + expectedTx.Nonce(), actualTx.Nonce(), + expectedTx.To().String(), actualTx.To().String(), + expectedTx.Value().String(), actualTx.Value().String(), + expectedTx.Gas(), actualTx.Gas(), + expectedTx.GasPrice().String(), actualTx.GasPrice().String(), + hex.EncodeToString(expectedTx.Data()), hex.EncodeToString(actualTx.Data()), + state.Error(), ) } expectedTx = actualTx diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 7a5d0aeb48..a3d7d5ec2c 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -308,8 +308,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st // it to the freezer content. // Only to check the followings when offset equal to 0, otherwise the block number // in ancientdb did not start with 0, no genesis block in ancientdb as well. - - if kvgenesis, _ := db.Get(headerHashKey(0)); offset == 0 && len(kvgenesis) > 0 { + if kvgenesis, _ := db.Get(headerHashKey(0)); (offset == 0 && frdb.tail.Load() == 0) && len(kvgenesis) > 0 { if frozen, _ := frdb.Ancients(); frozen > 0 { // If the freezer already contains something, ensure that the genesis blocks // match, otherwise we might mix up freezers across chains and destroy both @@ -557,7 +556,39 @@ func (s *stat) Count() string { return s.count.String() } func AncientInspect(db ethdb.Database) error { + log.Info("Inspect freezerDB...") + var stats [][]string + var total common.StorageSize + frds, err := inspectFreezers(db) + if err != nil { + return err + } + for _, ancient := range frds { + for _, table := range ancient.sizes { + stats = append(stats, []string{ + fmt.Sprintf("Ancient store (%s)", strings.Title(ancient.name)), + strings.Title(table.name), + table.size.String(), + fmt.Sprintf("%d", ancient.tail), + fmt.Sprintf("%d", ancient.head), + fmt.Sprintf("%d", ancient.count()), + }) + } + total += ancient.size() + } + frdTable := tablewriter.NewWriter(os.Stdout) + frdTable.SetHeader([]string{"Database", "Category", "Size", "tail", "head", "Items"}) + frdTable.SetFooter([]string{"", "Total", total.String(), " ", " ", " "}) + frdTable.AppendBulk(stats) + frdTable.Render() + + log.Info("Inspect ancient prune situation...") offset := counter(ReadOffSetOfCurrentAncientFreezer(db)) + // if tail is not 0, just overwrite it + tail, _ := db.Tail() + if tail > 0 { + offset = counter(tail) + } // Get number of ancient rows inside the freezer. ancients := counter(0) if count, err := db.ItemAmountInAncient(); err != nil { @@ -572,7 +603,7 @@ func AncientInspect(db ethdb.Database) error { } else { endNumber = offset + ancients - 1 } - stats := [][]string{ + stats = [][]string{ {"Offset/StartBlockNumber", "Offset/StartBlockNumber of ancientDB", offset.String()}, {"Amount of remained items in AncientStore", "Remaining items of ancientDB", ancients.String()}, {"The last BlockNumber within ancientDB", "The last BlockNumber", endNumber.String()}, diff --git a/eth/backend.go b/eth/backend.go index 5911cb3ff1..7dfd6e049a 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -416,8 +416,6 @@ func truncateAncientTail(db ethdb.Database, genesisHash common.Hash, CustomPath if err != nil { return err } - // update prune offset - rawdb.WriteOffSetOfCurrentAncientFreezer(db, pruneTail) log.Info("TruncateTail in freezerDB", "old", old, "now", pruneTail, "elapsed", common.PrettyDuration(time.Since(start))) return nil } From ff9e23982841c28128506e902653d1548053d734 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Thu, 23 Nov 2023 23:58:56 +0800 Subject: [PATCH 09/22] snapsync: ensure sync from last segment in snap sync when using history segment; --- cmd/geth/chaincmd.go | 8 +++--- core/blockchain.go | 7 +++++ core/blockchain_reader.go | 4 +++ eth/backend.go | 47 ++++++++++++++++++++++------------ eth/downloader/downloader.go | 23 +++++++++++++++++ params/history_segment.go | 21 ++++++++++++--- params/history_segment_test.go | 8 +++--- 7 files changed, 90 insertions(+), 28 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 4dffb30051..aa28cd1cf2 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -850,18 +850,18 @@ func pruneHistorySegments(ctx *cli.Context) error { // get latest 2 segments latestHeader := headerChain.CurrentHeader() curSegment := hsm.CurSegment(latestHeader.Number.Uint64()) - prevSegment, ok := hsm.PrevSegment(curSegment) + lastSegment, ok := hsm.LastSegment(curSegment) if !ok { return fmt.Errorf("there is no enough history to prune, cur: %v", curSegment) } // check segment if match hard code - if err = rawdb.AvailableHistorySegment(db, curSegment, prevSegment); err != nil { + if err = rawdb.AvailableHistorySegment(db, curSegment, lastSegment); err != nil { return err } - pruneTail := prevSegment.StartAtBlock.Number - log.Info("The older history will be pruned", "prevSegment", prevSegment, "curSegment", curSegment, "pruneTail", pruneTail) + pruneTail := lastSegment.StartAtBlock.Number + log.Info("The older history will be pruned", "lastSegment", lastSegment, "curSegment", curSegment, "pruneTail", pruneTail) if err = rawdb.PruneTxLookupToTail(db, pruneTail); err != nil { return err } diff --git a/core/blockchain.go b/core/blockchain.go index e528c667c4..3778a9c861 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -298,6 +298,9 @@ type BlockChain struct { vmConfig vm.Config pipeCommit bool + // history segment + lastSegment *params.HisSegment + // monitor doubleSignMonitor *monitor.DoubleSignMonitor } @@ -557,6 +560,10 @@ func (bc *BlockChain) GetVMConfig() *vm.Config { return &bc.vmConfig } +func (bc *BlockChain) SetupHistorySegment(lastSegment *params.HisSegment) { + bc.lastSegment = lastSegment +} + func (bc *BlockChain) cacheReceipts(hash common.Hash, receipts types.Receipts, block *types.Block) { // TODO, This is a hot fix for the block hash of logs is `0x0000000000000000000000000000000000000000000000000000000000000000` for system tx // Please check details in https://github.com/bnb-chain/bsc/issues/443 diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index 802b979a10..0f47e6dd83 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -448,3 +448,7 @@ func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscr func (bc *BlockChain) SubscribeFinalizedHeaderEvent(ch chan<- FinalizedHeaderEvent) event.Subscription { return bc.scope.Track(bc.finalizedHeaderFeed.Subscribe(ch)) } + +func (bc *BlockChain) LastHistorySegment() *params.HisSegment { + return bc.lastSegment +} diff --git a/eth/backend.go b/eth/backend.go index 7dfd6e049a..6d0a8978e4 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -185,13 +185,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { overrides.OverrideVerkle = config.OverrideVerkle } - // if enable history segment, try prune ancient data when restart - if config.HistorySegmentEnable { - if err = truncateAncientTail(chainDb, genesisHash, config.HistorySegmentCustomFile); err != nil { - return nil, err - } - } - eth := &Ethereum{ config: config, merger: consensus.NewMerger(chainDb), @@ -268,10 +261,25 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { peers := newPeerSet() bcOps = append(bcOps, core.EnableBlockValidator(chainConfig, eth.engine, config.TriesVerifyMode, peers)) txLookupLimit := &config.TransactionHistory - // if enable HistorySegment, just skip txLookupLimit params, may cause regenerate tx index + // if enable HistorySegment, just skip txLookupLimit params, + // may cause regenerate tx index, but it will also generate new block index if config.HistorySegmentEnable { txLookupLimit = nil } + bcOps = append(bcOps, func(bc *core.BlockChain) (*core.BlockChain, error) { + // if enable history segment, try prune ancient data when restart + if config.HistorySegmentEnable { + _, lastSegment, err := GetHistorySegmentAndLastSegment(chainDb, genesisHash, config.HistorySegmentCustomFile) + if err != nil { + return nil, err + } + if err = truncateAncientTail(chainDb, lastSegment); err != nil { + return nil, err + } + bc.SetupHistorySegment(lastSegment) + } + return bc, nil + }) eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, txLookupLimit, bcOps...) if err != nil { return nil, err @@ -388,29 +396,36 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { return eth, nil } -func truncateAncientTail(db ethdb.Database, genesisHash common.Hash, CustomPath string) error { +func GetHistorySegmentAndLastSegment(db ethdb.Database, genesisHash common.Hash, CustomPath string) (*params.HistorySegmentManager, *params.HisSegment, error) { hsm, err := params.NewHistorySegmentManager(¶ms.HistorySegmentConfig{ CustomPath: CustomPath, Genesis: genesisHash, }) if err != nil { - return err + return nil, nil, err } // get latest 2 segments latestHeader := rawdb.ReadHeadHeader(db) - curSegment := hsm.CurSegment(latestHeader.Number.Uint64()) - prevSegment, ok := hsm.PrevSegment(curSegment) + lastSegment, ok := hsm.LastSegmentByNumber(latestHeader.Number.Uint64()) if !ok { - return fmt.Errorf("there is no enough history to prune, cur: %v", curSegment) + log.Warn("there is no enough history to prune", "head", latestHeader.Number) + return hsm, nil, nil } // check segment if match hard code - if err = rawdb.AvailableHistorySegment(db, curSegment, prevSegment); err != nil { - return err + if err = rawdb.AvailableHistorySegment(db, lastSegment); err != nil { + return nil, nil, err + } + return hsm, &lastSegment, nil +} + +func truncateAncientTail(db ethdb.Database, lastSegment *params.HisSegment) error { + if lastSegment == nil { + return nil } - pruneTail := prevSegment.StartAtBlock.Number + pruneTail := lastSegment.StartAtBlock.Number start := time.Now() old, err := db.TruncateTail(pruneTail) if err != nil { diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 14d68844eb..063ac43313 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -207,6 +207,9 @@ type BlockChain interface { // TrieDB retrieves the low level trie database used for interacting // with trie nodes. TrieDB() *trie.Database + + // LastHistorySegment get last history segment + LastHistorySegment() *params.HisSegment } type DownloadOption func(downloader *Downloader) *Downloader @@ -230,6 +233,9 @@ func New(stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchai stateSyncStart: make(chan *stateSync), syncStartBlock: chain.CurrentSnapBlock().Number.Uint64(), } + for _, op := range options { + dl = op(dl) + } go dl.stateFetcher() return dl @@ -490,6 +496,13 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * localHeight = d.blockchain.CurrentBlock().Number.Uint64() case SnapSync: localHeight = d.blockchain.CurrentSnapBlock().Number.Uint64() + // if enable history segment, ensure local height >= lastSegment height + if d.blockchain.LastHistorySegment() != nil { + lastSegment := d.blockchain.LastHistorySegment() + if localHeight < lastSegment.StartAtBlock.Number { + localHeight = lastSegment.StartAtBlock.Number + } + } default: localHeight = d.lightchain.CurrentHeader().Number.Uint64() } @@ -875,6 +888,11 @@ func (d *Downloader) findAncestorSpanSearch(p *peerConnection, mode SyncMode, re known = d.blockchain.HasBlock(h, n) case SnapSync: known = d.blockchain.HasFastBlock(h, n) + // if enable history segment, check in last segment + if d.blockchain.LastHistorySegment() != nil && !known { + lastSegment := d.blockchain.LastHistorySegment() + known = lastSegment.MatchBlock(h, n) + } default: known = d.lightchain.HasHeader(h, n) } @@ -928,6 +946,11 @@ func (d *Downloader) findAncestorBinarySearch(p *peerConnection, mode SyncMode, known = d.blockchain.HasBlock(h, n) case SnapSync: known = d.blockchain.HasFastBlock(h, n) + // if enable history segment, check in last segment + if d.blockchain.LastHistorySegment() != nil && !known { + lastSegment := d.blockchain.LastHistorySegment() + known = lastSegment.MatchBlock(h, n) + } default: known = d.lightchain.HasHeader(h, n) } diff --git a/params/history_segment.go b/params/history_segment.go index 49effa32c3..603ef498fc 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -99,8 +99,15 @@ type HisSegment struct { // TODO(0xbundler): if need add more finality evidence? like signature? } -func (h *HisSegment) String() string { - return fmt.Sprintf("[Index: %v, StartAt: %v, FinalityAt: %v]", h.Index, h.StartAtBlock, h.FinalityAtBlock) +func (s *HisSegment) String() string { + return fmt.Sprintf("[Index: %v, StartAt: %v, FinalityAt: %v]", s.Index, s.StartAtBlock, s.FinalityAtBlock) +} + +func (s *HisSegment) MatchBlock(h common.Hash, n uint64) bool { + if s.StartAtBlock.Number == n && s.StartAtBlock.Hash == h { + return true + } + return false } type HistorySegmentConfig struct { @@ -203,9 +210,9 @@ func (m *HistorySegmentManager) CurSegment(num uint64) HisSegment { return segments[i] } -// PrevSegment return the current's last segment, because the latest 2 segments is available, +// LastSegment return the current's last segment, because the latest 2 segments is available, // so user could keep current & prev segment -func (m *HistorySegmentManager) PrevSegment(cur HisSegment) (HisSegment, bool) { +func (m *HistorySegmentManager) LastSegment(cur HisSegment) (HisSegment, bool) { segments := m.HisSegments() if cur.Index == 0 || cur.Index >= uint64(len(segments)) { return HisSegment{}, false @@ -213,6 +220,12 @@ func (m *HistorySegmentManager) PrevSegment(cur HisSegment) (HisSegment, bool) { return segments[cur.Index-1], true } +// LastSegmentByNumber return the current's last segment +func (m *HistorySegmentManager) LastSegmentByNumber(num uint64) (HisSegment, bool) { + cur := m.CurSegment(num) + return m.LastSegment(cur) +} + func unmarshalHisSegments(enc string) []HisSegment { var ret []HisSegment err := json.Unmarshal([]byte(enc), &ret) diff --git a/params/history_segment_test.go b/params/history_segment_test.go index 7198b95c38..b3fe5d621f 100644 --- a/params/history_segment_test.go +++ b/params/history_segment_test.go @@ -182,15 +182,15 @@ func TestIndexSegment(t *testing.T) { prev HisSegment ok bool ) - _, ok = hsm.PrevSegment(segments[0]) + _, ok = hsm.LastSegment(segments[0]) assert.Equal(t, false, ok) - prev, ok = hsm.PrevSegment(segments[1]) + prev, ok = hsm.LastSegment(segments[1]) assert.Equal(t, true, ok) assert.Equal(t, segments[0], prev) - prev, ok = hsm.PrevSegment(segments[2]) + prev, ok = hsm.LastSegment(segments[2]) assert.Equal(t, true, ok) assert.Equal(t, segments[1], prev) - _, ok = hsm.PrevSegment(HisSegment{ + _, ok = hsm.LastSegment(HisSegment{ Index: uint64(len(segments)), }) assert.Equal(t, false, ok) From c8b2a04bfde0e6a305af8e34d469816e98e2d44d Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Mon, 27 Nov 2023 15:23:09 +0800 Subject: [PATCH 10/22] snapsync: fix some sync error; --- consensus/parlia/parlia.go | 2 +- core/blockchain_reader.go | 11 +++++ eth/downloader/downloader.go | 47 +++++++++++++++++--- eth/handler_test.go | 4 +- eth/sync_test.go | 84 ++++++++++++++++++++++++++++++++++++ params/history_segment.go | 2 + 6 files changed, 142 insertions(+), 8 deletions(-) diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index deffd06d8f..fbb721bfa5 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -677,7 +677,7 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash break } } - + // TODO(0xbundler): check history consensus data, load snapshot // If we're at the genesis, snapshot the initial state. Alternatively if we have // piled up more headers than allowed to be reorged (chain reinit from a freezer), // consider the checkpoint trusted and snapshot it. diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index 0f47e6dd83..a5bb70239a 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -452,3 +452,14 @@ func (bc *BlockChain) SubscribeFinalizedHeaderEvent(ch chan<- FinalizedHeaderEve func (bc *BlockChain) LastHistorySegment() *params.HisSegment { return bc.lastSegment } + +func (bc *BlockChain) WriteCanonicalHeaders(headers []*types.Header, tds []uint64) error { + for i, header := range headers { + h := header.Hash() + n := header.Number.Uint64() + rawdb.WriteTd(bc.db, h, n, new(big.Int).SetUint64(tds[i])) + rawdb.WriteHeader(bc.db, header) + rawdb.WriteCanonicalHash(bc.db, h, n) + } + return nil +} diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 063ac43313..e038292d37 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -210,6 +210,9 @@ type BlockChain interface { // LastHistorySegment get last history segment LastHistorySegment() *params.HisSegment + + // WriteHeaders just write header into db, it an unsafe interface, just for history segment + WriteCanonicalHeaders([]*types.Header, []uint64) error } type DownloadOption func(downloader *Downloader) *Downloader @@ -845,6 +848,13 @@ func (d *Downloader) findAncestor(p *peerConnection, localHeight uint64, remoteH if err != nil { return 0, err } + + if ancestor == 0 && mode == SnapSync { + ancestor, err = d.findAncestorFromHistorySegment(p, remoteHeight) + if err != nil { + return 0, err + } + } return ancestor, nil } @@ -888,11 +898,6 @@ func (d *Downloader) findAncestorSpanSearch(p *peerConnection, mode SyncMode, re known = d.blockchain.HasBlock(h, n) case SnapSync: known = d.blockchain.HasFastBlock(h, n) - // if enable history segment, check in last segment - if d.blockchain.LastHistorySegment() != nil && !known { - lastSegment := d.blockchain.LastHistorySegment() - known = lastSegment.MatchBlock(h, n) - } default: known = d.lightchain.HasHeader(h, n) } @@ -1749,3 +1754,35 @@ func (d *Downloader) reportSnapSyncProgress(force bool) { log.Info("Syncing: chain download in progress", "synced", progress, "chain", syncedBytes, "headers", headers, "bodies", bodies, "receipts", receipts, "eta", common.PrettyDuration(eta)) d.syncLogTime = time.Now() } + +func (d *Downloader) findAncestorFromHistorySegment(p *peerConnection, remoteHeight uint64) (uint64, error) { + lastSegment := d.blockchain.LastHistorySegment() + if lastSegment == nil { + return 0, nil + } + + expect := lastSegment.StartAtBlock.Number + if expect > remoteHeight { + return 0, nil + } + headers, hashes, err := d.fetchHeadersByNumber(p, expect, 1, 0, false) + if err != nil { + return 0, err + } + // Make sure the peer actually gave something valid + if len(headers) != 1 { + return 0, fmt.Errorf("%w: multiple headers (%d) for single request", errBadPeer, len(headers)) + } + + // check if it matches local last segment + h := hashes[0] + n := headers[0].Number.Uint64() + if lastSegment.MatchBlock(h, n) && headers[0].Hash() == h { + // just write header, td, because it's snap sync, just sync history is enough + if err = d.blockchain.WriteCanonicalHeaders(headers, []uint64{lastSegment.StartAtBlock.TD}); err != nil { + return 0, err + } + return n, nil + } + return 0, nil +} diff --git a/eth/handler_test.go b/eth/handler_test.go index bc22af7114..4723a4fd89 100644 --- a/eth/handler_test.go +++ b/eth/handler_test.go @@ -171,14 +171,14 @@ func newTestHandler() *testHandler { // newTestHandlerWithBlocks creates a new handler for testing purposes, with a // given number of initial blocks. -func newTestHandlerWithBlocks(blocks int) *testHandler { +func newTestHandlerWithBlocks(blocks int, options ...core.BlockChainOption) *testHandler { // Create a database pre-initialize with a genesis block db := rawdb.NewMemoryDatabase() gspec := &core.Genesis{ Config: params.TestChainConfig, Alloc: core.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}}, } - chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) + chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, options...) _, bs, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), blocks, nil) if _, err := chain.InsertChain(bs); err != nil { diff --git a/eth/sync_test.go b/eth/sync_test.go index b5e00298b9..449f4ccb38 100644 --- a/eth/sync_test.go +++ b/eth/sync_test.go @@ -20,6 +20,12 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + + "github.com/ethereum/go-ethereum/params" + + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/snap" @@ -94,3 +100,81 @@ func testSnapSyncDisabling(t *testing.T, ethVer uint, snapVer uint) { t.Fatalf("snap sync not disabled after successful synchronisation") } } + +func TestSnapSyncWithHistorySegment(t *testing.T) { + t.Parallel() + // Create a full handler and ensure snap sync ends up disabled + full := newTestHandlerWithBlocks(1024) + if full.handler.snapSync.Load() { + t.Fatalf("snap sync not disabled on non-empty blockchain") + } + defer full.close() + + // Create an empty handler and ensure it's in snap sync mode + empty := newTestHandlerWithBlocks(0, func(bc *core.BlockChain) (*core.BlockChain, error) { + header := full.chain.GetHeaderByNumber(500) + bc.SetupHistorySegment(¶ms.HisSegment{ + Index: 1, + StartAtBlock: params.HisBlockInfo{ + Number: header.Number.Uint64(), + Hash: header.Hash(), + TD: full.chain.GetTd(header.Hash(), header.Number.Uint64()).Uint64(), + }, + }) + return bc, nil + }) + if !empty.handler.snapSync.Load() { + t.Fatalf("snap sync disabled on pristine blockchain") + } + defer empty.close() + + // Sync up the two handlers via both `eth` and `snap` + ethVer := uint(eth.ETH66) + snapVer := uint(snap.SNAP1) + caps := []p2p.Cap{{Name: "eth", Version: ethVer}, {Name: "snap", Version: snap.SNAP1}} + + emptyPipeEth, fullPipeEth := p2p.MsgPipe() + defer emptyPipeEth.Close() + defer fullPipeEth.Close() + + emptyPeerEth := eth.NewPeer(ethVer, p2p.NewPeer(enode.ID{1}, "", caps), emptyPipeEth, empty.txpool) + fullPeerEth := eth.NewPeer(ethVer, p2p.NewPeer(enode.ID{2}, "", caps), fullPipeEth, full.txpool) + defer emptyPeerEth.Close() + defer fullPeerEth.Close() + + go empty.handler.runEthPeer(emptyPeerEth, func(peer *eth.Peer) error { + return eth.Handle((*ethHandler)(empty.handler), peer) + }) + go full.handler.runEthPeer(fullPeerEth, func(peer *eth.Peer) error { + return eth.Handle((*ethHandler)(full.handler), peer) + }) + + emptyPipeSnap, fullPipeSnap := p2p.MsgPipe() + defer emptyPipeSnap.Close() + defer fullPipeSnap.Close() + + emptyPeerSnap := snap.NewPeer(snapVer, p2p.NewPeer(enode.ID{1}, "", caps), emptyPipeSnap) + fullPeerSnap := snap.NewPeer(snapVer, p2p.NewPeer(enode.ID{2}, "", caps), fullPipeSnap) + + go empty.handler.runSnapExtension(emptyPeerSnap, func(peer *snap.Peer) error { + return snap.Handle((*snapHandler)(empty.handler), peer) + }) + go full.handler.runSnapExtension(fullPeerSnap, func(peer *snap.Peer) error { + return snap.Handle((*snapHandler)(full.handler), peer) + }) + // Wait a bit for the above handlers to start + time.Sleep(250 * time.Millisecond) + + // Check that snap sync was disabled + op := peerToSyncOp(downloader.SnapSync, empty.handler.peers.peerWithHighestTD()) + if err := empty.handler.doSync(op); err != nil { + t.Fatal("sync failed:", err) + } + if empty.handler.snapSync.Load() { + t.Fatalf("snap sync not disabled after successful synchronisation") + } + assert.Nil(t, empty.chain.GetHeaderByNumber(1), 1) + assert.Nil(t, empty.chain.GetHeaderByNumber(251), 251) + assert.NotNil(t, empty.chain.GetHeaderByNumber(500), 500) + assert.NotNil(t, empty.chain.GetHeaderByNumber(1024), 1024) +} diff --git a/params/history_segment.go b/params/history_segment.go index 603ef498fc..7042b3095b 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -90,6 +90,8 @@ var ( type HisBlockInfo struct { Number uint64 `json:"number"` Hash common.Hash `json:"hash"` + TD uint64 + // TODO(0xbundler): add consensus data, parlia snapshot } type HisSegment struct { From eb1141c05c973a356e7d302470ed44327063c469 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Tue, 28 Nov 2023 21:01:59 +0800 Subject: [PATCH 11/22] historysegment: support parlia snapshot; parlia: support load snap from history segment; --- cmd/geth/chaincmd.go | 31 +++++++++++++++++-------- consensus/consensus.go | 2 ++ consensus/parlia/parlia.go | 36 ++++++++++++++++++++++++++++- core/vote/vote_pool_test.go | 14 +++++++++++ eth/backend.go | 16 +++++++++---- params/history_segment.go | 46 +++++++++++++++++++++++++++++++++---- 6 files changed, 124 insertions(+), 21 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index aa28cd1cf2..5f74977821 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -719,7 +719,7 @@ func exportSegment(ctx *cli.Context) error { defer db.Close() genesisHash := rawdb.ReadCanonicalHash(db, 0) - headerChain, chainConfig, err := simpleHeaderChain(db, genesisHash) + chainConfig, engine, headerChain, err := simpleHeaderChain(db, genesisHash) if err != nil { return err } @@ -788,7 +788,7 @@ func exportSegment(ctx *cli.Context) error { break } log.Info("found segment boundary", "startAt", ft.Number, "FinalityAt", fs.Number) - segments = append(segments, params.HisSegment{ + segment := params.HisSegment{ Index: uint64(len(segments)), StartAtBlock: params.HisBlockInfo{ Number: ft.Number.Uint64(), @@ -798,7 +798,18 @@ func exportSegment(ctx *cli.Context) error { Number: fs.Number.Uint64(), Hash: fs.Hash(), }, - }) + } + segment.StartAtBlock.TD = headerChain.GetTd(segment.StartAtBlock.Hash, segment.StartAtBlock.Number).Uint64() + segment.FinalityAtBlock.TD = headerChain.GetTd(segment.FinalityAtBlock.Hash, segment.FinalityAtBlock.Number).Uint64() + // if using posa consensus, just get snapshot as consensus data + if p, ok := engine.(consensus.PoSA); ok { + enc, err := p.GetConsensusData(headerChain, ft) + if err != nil { + return err + } + segment.StartAtBlock.ConsensusData = enc + } + segments = append(segments, segment) } if err = params.ValidateHisSegments(genesisHash, segments); err != nil { return err @@ -831,7 +842,7 @@ func pruneHistorySegments(ctx *cli.Context) error { defer db.Close() genesisHash := rawdb.ReadCanonicalHash(db, 0) - headerChain, _, err := simpleHeaderChain(db, genesisHash) + _, _, headerChain, err := simpleHeaderChain(db, genesisHash) if err != nil { return err } @@ -881,23 +892,23 @@ func hashish(x string) bool { return err != nil } -func simpleHeaderChain(db ethdb.Database, genesisHash common.Hash) (*core.HeaderChain, *params.ChainConfig, error) { +func simpleHeaderChain(db ethdb.Database, genesisHash common.Hash) (*params.ChainConfig, consensus.Engine, *core.HeaderChain, error) { chainConfig := rawdb.ReadChainConfig(db, genesisHash) if chainConfig == nil { - return nil, nil, errors.New("failed to load chainConfig") + return nil, nil, nil, errors.New("failed to load chainConfig") } engine, err := ethconfig.CreateConsensusEngine(chainConfig, db, nil, genesisHash) if err != nil { - return nil, nil, err + return nil, nil, nil, err } if _, ok := engine.(consensus.PoSA); !ok { - return nil, nil, errors.New("current chain is not POSA, cannot generate history segment") + return nil, nil, nil, errors.New("current chain is not POSA, cannot generate history segment") } headerChain, err := core.NewHeaderChain(db, chainConfig, engine, func() bool { return true }) if err != nil { - return nil, nil, err + return nil, nil, nil, err } - return headerChain, chainConfig, nil + return chainConfig, engine, headerChain, nil } diff --git a/consensus/consensus.go b/consensus/consensus.go index 709622ce34..d59a1bd99b 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -154,4 +154,6 @@ type PoSA interface { GetFinalizedHeader(chain ChainHeaderReader, header *types.Header) *types.Header VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool + GetConsensusData(chain ChainHeaderReader, header *types.Header) ([]byte, error) + SetupLastSegment(segment *params.HisSegment) } diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index fbb721bfa5..6c4d9343e7 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/hex" + "encoding/json" "errors" "fmt" "io" @@ -230,6 +231,9 @@ type Parlia struct { // The fields below are for testing only fakeDiff bool // Skip difficulty verifications + + // history segment, it provides history segment's consensus data to prevent generate snap from older headers + lastSegment *params.HisSegment } // New creates a Parlia consensus engine. @@ -286,6 +290,10 @@ func New( return c } +func (p *Parlia) SetupLastSegment(segment *params.HisSegment) { + p.lastSegment = segment +} + func (p *Parlia) IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) { // deploy a contract if tx.To() == nil { @@ -677,7 +685,20 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash break } } - // TODO(0xbundler): check history consensus data, load snapshot + // check history consensus data, load snapshot + if p.lastSegment != nil && p.lastSegment.MatchBlock(hash, number) { + var tmp Snapshot + err := json.Unmarshal(p.lastSegment.StartAtBlock.ConsensusData, &tmp) + if err == nil { + tmp.config = p.config + tmp.sigCache = p.signatures + tmp.ethAPI = p.ethAPI + snap = &tmp + break + } + log.Error("Try load snapshot from history segment, wrong encode", "number", number, "hash", hash, "err", err) + } + // If we're at the genesis, snapshot the initial state. Alternatively if we have // piled up more headers than allowed to be reorged (chain reinit from a freezer), // consider the checkpoint trusted and snapshot it. @@ -1512,6 +1533,19 @@ func (p *Parlia) Close() error { return nil } +func (p *Parlia) GetConsensusData(chain consensus.ChainHeaderReader, header *types.Header) ([]byte, error) { + number := header.Number.Uint64() + snap, err := p.snapshot(chain, number, header.Hash(), nil) + if err != nil { + return nil, err + } + enc, err := json.Marshal(snap) + if err != nil { + return nil, err + } + return enc, nil +} + // ========================== interaction with contract/account ========= // getCurrentValidators get current validators diff --git a/core/vote/vote_pool_test.go b/core/vote/vote_pool_test.go index 0588c3fb92..be658570c3 100644 --- a/core/vote/vote_pool_test.go +++ b/core/vote/vote_pool_test.go @@ -106,6 +106,20 @@ func (m *mockInvalidPOSA) IsActiveValidatorAt(chain consensus.ChainHeaderReader, return true } +func (m *mockPOSA) GetConsensusData(chain consensus.ChainHeaderReader, header *types.Header) ([]byte, error) { + return nil, nil +} + +func (m *mockInvalidPOSA) GetConsensusData(chain consensus.ChainHeaderReader, header *types.Header) ([]byte, error) { + return nil, nil +} + +func (m *mockPOSA) SetupLastSegment(segment *params.HisSegment) { +} + +func (m *mockInvalidPOSA) SetupLastSegment(segment *params.HisSegment) { +} + func (pool *VotePool) verifyStructureSizeOfVotePool(receivedVotes, curVotes, futureVotes, curVotesPq, futureVotesPq int) bool { for i := 0; i < timeThreshold; i++ { time.Sleep(1 * time.Second) diff --git a/eth/backend.go b/eth/backend.go index 6d0a8978e4..bcfed22251 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -210,6 +210,16 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if err != nil { return nil, err } + var lastSegment *params.HisSegment + if config.HistorySegmentEnable { + _, lastSegment, err = GetHistorySegmentAndLastSegment(chainDb, genesisHash, config.HistorySegmentCustomFile) + if err != nil { + return nil, err + } + if p, ok := eth.engine.(consensus.PoSA); ok { + p.SetupLastSegment(lastSegment) + } + } bcVersion := rawdb.ReadDatabaseVersion(chainDb) var dbVer = "" @@ -268,11 +278,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } bcOps = append(bcOps, func(bc *core.BlockChain) (*core.BlockChain, error) { // if enable history segment, try prune ancient data when restart - if config.HistorySegmentEnable { - _, lastSegment, err := GetHistorySegmentAndLastSegment(chainDb, genesisHash, config.HistorySegmentCustomFile) - if err != nil { - return nil, err - } + if config.HistorySegmentEnable && lastSegment != nil { if err = truncateAncientTail(chainDb, lastSegment); err != nil { return nil, err } diff --git a/params/history_segment.go b/params/history_segment.go index 7042b3095b..5b3dd4f4db 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -1,6 +1,7 @@ package params import ( + "bytes" "encoding/json" "errors" "fmt" @@ -88,10 +89,29 @@ var ( ) type HisBlockInfo struct { - Number uint64 `json:"number"` - Hash common.Hash `json:"hash"` - TD uint64 - // TODO(0xbundler): add consensus data, parlia snapshot + Number uint64 `json:"number"` + Hash common.Hash `json:"hash"` + TD uint64 `json:"td"` + ConsensusData []byte `json:"consensus_data"` // add consensus data, like parlia snapshot +} + +func (b *HisBlockInfo) Equals(c *HisBlockInfo) bool { + if b == nil || c == nil { + return b == c + } + if b.Number != c.Number { + return false + } + if b.Hash != c.Hash { + return false + } + if b.TD != c.TD { + return false + } + if !bytes.Equal(b.ConsensusData, c.ConsensusData) { + return false + } + return true } type HisSegment struct { @@ -112,6 +132,22 @@ func (s *HisSegment) MatchBlock(h common.Hash, n uint64) bool { return false } +func (s *HisSegment) Equals(compared *HisSegment) bool { + if s == nil || compared == nil { + return s == compared + } + if s.Index != compared.Index { + return false + } + if !s.StartAtBlock.Equals(&compared.StartAtBlock) { + return false + } + if !s.FinalityAtBlock.Equals(&compared.FinalityAtBlock) { + return false + } + return true +} + type HistorySegmentConfig struct { CustomPath string // custom HistorySegments file path, need read from the file Genesis common.Hash // specific chain genesis, it may use hard-code config @@ -180,7 +216,7 @@ func ValidateHisSegments(genesis common.Hash, segments []HisSegment) error { Hash: genesis, }, } - if segments[0] != expectSeg0 { + if !segments[0].Equals(&expectSeg0) { return fmt.Errorf("wrong segement0 start block, it must be genesis, expect: %v, actual: %v", expectSeg0, segments[0]) } for i := 1; i < len(segments); i++ { From 3d8c301b3b0b5b10a11c5228dc9088fcb55a43d1 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:52:19 +0800 Subject: [PATCH 12/22] parlia: support load snap from history segment; --- params/history_segment.go | 44 ++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/params/history_segment.go b/params/history_segment.go index 5b3dd4f4db..9ad8339dcc 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -22,22 +22,27 @@ var ( "index": 0, "start_at_block": { "number": 0, - "hash": "0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b" + "hash": "0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b", + "td": 0 }, "finality_at_block": { "number": 0, - "hash": "0x0000000000000000000000000000000000000000000000000000000000000000" + "hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "td": 0 } }, { "index": 1, "start_at_block": { "number": 31268530, - "hash": "0xdb8a505f19ef04cb21ae79e3cb641963ffc44f3666e6fde499be55a72b6c7865" + "hash": "0xdb8a505f19ef04cb21ae79e3cb641963ffc44f3666e6fde499be55a72b6c7865", + "td": 62131329, + "consensus_data": "eyJudW1iZXIiOjMxMjY4NTMwLCJoYXNoIjoiMHhkYjhhNTA1ZjE5ZWYwNGNiMjFhZTc5ZTNjYjY0MTk2M2ZmYzQ0ZjM2NjZlNmZkZTQ5OWJlNTVhNzJiNmM3ODY1IiwidmFsaWRhdG9ycyI6eyIweDBiYWM0OTIzODY4NjJhZDNkZjRiNjY2YmMwOTZiMDUwNWJiNjk0ZGEiOnsiaW5kZXg6b21pdGVtcHR5IjoxLCJ2b3RlX2FkZHJlc3MiOlsxNzYsMTkwLDE5NSw3MiwxMDQsMjYsMjQ3LDEwMiwxMTcsMjgsMTg0LDU3LDg3LDExMCwxNTYsODEsOTAsOSwyMDAsMTkxLDI1MCw0OCwxNjQsOTgsMTUwLDIwNCwxOTcsMTAyLDE4LDczLDE0LDE4MCwxMjgsMjA4LDU5LDI0OSw3MiwyMjUsMCw1LDE4NywyMDQsNCwzMywyNDksMTEsNjEsNzhdfSwiMHgyNDY1MTc2YzQ2MWFmYjMxNmViYzc3M2M2MWZhZWU4NWE2NTE1ZGFhIjp7ImluZGV4Om9taXRlbXB0eSI6Miwidm90ZV9hZGRyZXNzIjpbMTM4LDE0Niw1MywxMDAsMTk4LDI1NSwyMTEsMTI3LDE3OCwyNTQsMTU5LDE3LDE0MiwyNDgsMTI4LDE0NiwyMzIsMTE4LDQ0LDEyMiwyMjEsMTgxLDM4LDE3MSwxMjYsMTc3LDIzMSwxMTQsMTg2LDIzOSwxMzMsMjQsMzEsMTM3LDQ0LDExNSwyNywyMjQsMTkzLDEzNywyNiw4MCwyMzAsMTc2LDk4LDk4LDIwMCwyMl19LCIweDJkNGM0MDdiYmU0OTQzOGVkODU5ZmU5NjViMTQwZGNmMWFhYjcxYTkiOnsiaW5kZXg6b21pdGVtcHR5IjozLCJ2b3RlX2FkZHJlc3MiOlsxNDcsMTkzLDI0NywyNDYsMTQ2LDE1NywzMSwyMjYsMTYxLDEyMyw3OCwyMCw5Nyw3OCwyNDksMjUyLDkxLDIyMCwxMTMsNjEsMTAyLDQ5LDIxNCwxMTcsNjQsNjMsMTkwLDIzOSwxNzIsODUsOTcsMjcsMjQ2LDE4LDExMiwxMSwyNywxMDEsMjQ0LDExNiw3Miw5NywxODQsMTEsMTUsMTI1LDEwNiwxNzZdfSwiMHgzZjM0OWJiYWZlYzE1NTE4MTliOGJlMWVmZWEyZmM0NmNhNzQ5YWExIjp7ImluZGV4Om9taXRlbXB0eSI6NCwidm90ZV9hZGRyZXNzIjpbMTMyLDM2LDEzOCw2OSwxNDgsMTAwLDIzOCwxOTMsMTYyLDMwLDEyNywxOTksMTgzLDI2LDUsNjEsMTUwLDY4LDIzMywxODcsMTQxLDE2NCwxMzMsNTksMTQzLDEzNSw0NCwyMTUsMTkzLDIxNCwxNzksMzYsMTkxLDI1LDM0LDEzMCwxNTIsNDgsMTAwLDEwOCwyMzQsMjIzLDE4Miw4OCwyMTEsMjIyLDAsMTU0XX0sIjB4NjFkZDQ4MWExMTRhMmU3NjFjNTU0YjY0MTc0MmM5NzM4Njc4OTlkMyI6eyJpbmRleDpvbWl0ZW1wdHkiOjUsInZvdGVfYWRkcmVzcyI6WzEzOCwxMjgsMTUwLDEyNSw1NywyMjgsNiwxNjAsMTY5LDEwMCw0NSw2NSwyMzMsMCwxMjIsMzksMjUyLDE3LDgwLDE2MiwxMDMsMjA5LDY3LDE2OSwyNDcsMTM0LDIwNSw0Myw5NCwyMzYsMTg5LDIwNCw2NCw1NCwzOSw1NSw1LDM0LDkxLDE0OSwxMDksOTQsNDcsMTQzLDk0LDE4NSw5MywzN119LCIweDY4NWIxZGVkODAxMzc4NWQ2NjIzY2MxOGQyMTQzMjBiNmJiNjQ3NTkiOnsiaW5kZXg6b21pdGVtcHR5Ijo2LCJ2b3RlX2FkZHJlc3MiOlsxMzgsOTYsMjQ4LDQyLDEyMywyMDcsMTE2LDE4MCwyMDMsNSw1OSwxNTUsMjU0LDEzMSwyMDgsMjM3LDIsMTY4LDc4LDE4NywxNiwxMzQsOTMsMjUzLDIxNiwyMjYsMTEwLDExNyw1MywxOTYsNTgsMjgsMjA0LDIxMCwxMDQsMjMyLDk2LDI0NSwyLDMzLDEwNyw1NSwxNTcsMjUyLDE1MywxMTMsMjExLDg4XX0sIjB4NzBmNjU3MTY0ZTViNzU2ODliNjRiN2ZkMWZhMjc1ZjMzNGYyOGUxOCI6eyJpbmRleDpvbWl0ZW1wdHkiOjcsInZvdGVfYWRkcmVzcyI6WzE1MCwxNjIsMTA2LDI1MCwxOCwxNDksMjE4LDEyOSw2NSwxMzMsMTQ3LDE4OSwxOCwxMjksNjgsOTksMjE3LDI0NiwyMjgsOTIsNTQsMTYwLDIyOCwxMjYsMTgwLDIwNSw2Miw5MSwxMDYsMjQyLDE1Niw2NSwyMjYsMTYzLDE2NSw5OSwxMDAsNDgsMjEsOTAsNzAsMTEwLDMzLDEwMSwxMzMsMTc1LDU5LDE2N119LCIweDcyYjYxYzYwMTQzNDJkOTE0NDcwZWM3YWMyOTc1YmUzNDU3OTZjMmIiOnsiaW5kZXg6b21pdGVtcHR5Ijo4LCJ2b3RlX2FkZHJlc3MiOlsxMjksMjE5LDQsMzQsMTY1LDI1Myw4LDIyOCwxMywxNzcsMjUyLDM1LDEwNCwyMTAsMzYsOTQsNzUsMjQsMTc3LDIwOCwxODQsOTIsMTQ2LDI2LDE3MCwxNzUsMjEwLDIyNyw2NSwxMTgsMTQsNDEsMjUyLDk3LDYyLDIyMSw1NywyNDcsMTgsODQsOTcsNzgsMzIsODUsMTk1LDQwLDEyMiw4MV19LCIweDdhZTJmNWI5ZTM4NmNkMWI1MGE0NTUwNjk2ZDk1N2NiNDkwMGYwM2EiOnsiaW5kZXg6b21pdGVtcHR5Ijo5LCJ2b3RlX2FkZHJlc3MiOlsxODQsNzksMTMxLDI1NSw0NSwyNDQsNjUsMTQ3LDczLDEwMywxNDcsMTg0LDcxLDI0Niw3OCwxNTcsMTA5LDE3NywxNzksMTQ5LDU0LDEzMCwxODcsMTQ5LDIzNywyMDgsMTUwLDIzNSwzMCwxMDUsMTg3LDIxMSw4NywxOTQsMCwxNTMsNDQsMTY3LDEyOCw4MCwyMDgsMjAzLDIyNSwxMjgsMjA3LDE3MCwxLDE0Ml19LCIweDhiNmM4ZmQ5M2Q2ZjRjZWE0MmJiYjM0NWRiYzZmMGRmZGI1YmVjNzMiOnsiaW5kZXg6b21pdGVtcHR5IjoxMCwidm90ZV9hZGRyZXNzIjpbMTY4LDE2Miw4Nyw3LDc4LDEzMCwxODQsMTI5LDIwNywxNjAsMTEwLDI0MywyMzUsNzgsMjU0LDIwMiw2LDEyLDM3LDQ5LDUzLDE1NCwxODksMTQsMTcxLDEzOCwyNDEsMjI3LDIzNywyNTAsMzIsMzcsMjUyLDE2NCwxMDAsMTcyLDE1Niw2MywyMDksMzUsMjQ2LDE5NCw3NCwxMywxMjAsMTM0LDE0OCwxMzNdfSwiMHhhNmY3OWI2MDM1OWYxNDFkZjkwYTBjNzQ1MTI1YjEzMWNhYWZmZDEyIjp7ImluZGV4Om9taXRlbXB0eSI6MTEsInZvdGVfYWRkcmVzcyI6WzE4MywxMTQsMjI1LDEyOCwyNTEsMjQzLDEzOCw1LDI4LDE1MSwyMTgsMTg4LDEzOCwxNzAsMSwzOCwxNjIsNTEsMTY5LDIzMiw0MCwyMDUsMTc1LDIwNCwxMTYsMzQsMTk2LDE4NywzMSw2NCw0OCwxNjUsMTA3LDE2MywxMDAsMTk3LDY1LDMsMjQyLDEwNywxNzMsMTQ1LDgwLDEzOSw4MiwzMiwxODMsNjVdfSwiMHhiMjE4YzVkNmFmMWY5NzlhYzQyYmM2OGQ5OGE1YTBkNzk2YzZhYjAxIjp7ImluZGV4Om9taXRlbXB0eSI6MTIsInZvdGVfYWRkcmVzcyI6WzE4Miw4OSwxNzMsMTUsMTg5LDE1OSw4MSw4OCwxNDcsMjUzLDIxNSw2NCwxNzgsMTU1LDE2MCwxMTksNDUsMTg5LDIzMywxODAsOTksODksMzMsMjIxLDE0NSwxODksNDEsOTksMTYwLDI1MiwxMzMsOTQsNDksMjQ2LDUxLDE0Myw2OSwxNzgsMTcsMTk2LDIzMywyMjIsMjE5LDEyNyw0NiwxNzYsMTU3LDIzMV19LCIweGI0ZGQ2NmQ3YzJjN2U1N2Y2MjgyMTAxODcxOTJmYjg5ZDRiOTlkZDQiOnsiaW5kZXg6b21pdGVtcHR5IjoxMywidm90ZV9hZGRyZXNzIjpbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdfSwiMHhiZTgwN2RkZGIwNzQ2MzljZDlmYTYxYjQ3Njc2YzA2NGZjNTBkNjJjIjp7ImluZGV4Om9taXRlbXB0eSI6MTQsInZvdGVfYWRkcmVzcyI6WzE3NywyNDIsMTk5LDIxLDExOSwyMjIsMjQzLDIwLDc5LDE3MSwyMzUsMTE3LDE2OCwxNjEsMjAwLDIwMyw5MSw4MSwyMDksMjA5LDE4MCwxNjAsOTQsMjM2LDEwMywxNTIsMTM5LDEzNCwxMzMsMCwxMzksMTcwLDIzLDY5LDE1OCwxOTYsMzcsMjE5LDE3NCwxODgsMTMzLDQ3LDczLDEwOSwyMDEsMzMsMTUwLDIwNV19LCIweGNjOGU2ZDAwYzE3ZWI0MzEzNTBjNmM1MGQ4YjhmMDUxNzZiOTBiMTEiOnsiaW5kZXg6b21pdGVtcHR5IjoxNSwidm90ZV9hZGRyZXNzIjpbMTc5LDE2MywyMTIsMjU0LDE4NCwzNywxNzQsMTUxLDIsMTEzLDIxLDEwMiwyMjMsOTMsMTkxLDU2LDIzMiw0MiwyMjEsNzcsMjA5LDE4MSwxMTUsMTg1LDkzLDM2LDEwMiwyNTAsMTAxLDEsMjA0LDE4NCwzMCwxNTcsMzgsMTYzLDgyLDE4NSw5Nyw4MCwyMDQsMTkxLDEyMywxMDUsMTI3LDIwOCwxNjQsMjVdfSwiMHhjZTJmZDc1NDRlMGIyY2M5NDY5MmQ0YTcwNGRlYmVmN2JjYjYxMzI4Ijp7ImluZGV4Om9taXRlbXB0eSI6MTYsInZvdGVfYWRkcmVzcyI6WzE4Miw3NCwxOTAsMzcsOTcsNzYsMTU2LDI1Myw1MCwyMjgsODYsMTgwLDIxMywzMywyNDIsMTU2LDEzMSw4NywyNDQsMTc1LDcwLDYsMTUxLDEzMCwxNTAsMjAxLDE5MCwxNDcsNzMsNjQsMTE0LDE3Miw1LDI1MCwxMzQsMjI3LDIxMCwxMjQsMjAwLDIxNCwxMTAsMTAxLDAsMTUsMTM5LDE2Myw2MywxODddfSwiMHhlMmQzYTczOWVmZmNkM2E5OTM4N2QwMTVlMjYwZWVmYWM3MmViZWExIjp7ImluZGV4Om9taXRlbXB0eSI6MTcsInZvdGVfYWRkcmVzcyI6WzE0OSwxMDgsNzEsMTMsMjIzLDI0NCwxNDAsMTgwLDE0NywwLDMyLDExLDk1LDEzMSw3MywxMjcsNTgsNjAsMjAzLDU4LDIzNSwxMzEsMTk3LDIzNywyMTcsMTI5LDEzMywxMDUsMywxNDIsOTcsMjA5LDE1MSwyNCw3OSw3NCwxNjYsMTQ3LDE1OCwxNjUsMjMzLDE0NSwzMCw2MiwxNTIsMTcyLDEwOSwzM119LCIweGU5YWUzMjYxYTQ3NWEyN2JiMTAyOGYxNDBiYzJhN2M4NDMzMThhZmQiOnsiaW5kZXg6b21pdGVtcHR5IjoxOCwidm90ZV9hZGRyZXNzIjpbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdfSwiMHhlYTBhNmUzYzUxMWJiZDEwZjQ1MTllY2UzN2RjMjQ4ODdlMTFiNTVkIjp7ImluZGV4Om9taXRlbXB0eSI6MTksInZvdGVfYWRkcmVzcyI6WzE3OCwyMTIsMTk4LDQwLDYwLDY4LDE2MSwxOTksMTg5LDgwLDU4LDE3MSwxNjcsMTAyLDExMCwxNTksMTIsMTMxLDE0LDE1LDI0MCwyMiwxOTMsMTk5LDgwLDE2NSwyMjgsMTM1LDg3LDE2NywxOSwyMDgsMTMxLDEwNywyOCwxNzEsMjUzLDkyLDQwLDI3LDI5LDIyNywxODMsMTI1LDI4LDI1LDMzLDEzMV19LCIweGVlMjI2Mzc5ZGI4M2NmZmM2ODE0OTU3MzBjMTFmZGRlNzliYTRjMGMiOnsiaW5kZXg6b21pdGVtcHR5IjoyMCwidm90ZV9hZGRyZXNzIjpbMTc0LDEyMywxOTgsMjUwLDE2MywyNDAsMjA0LDYyLDk2LDE0NywxODIsNTEsMjUzLDEyNiwyMjgsMjQ4LDEwNSwxMTIsMTQ2LDEwNSw4OCwyMDgsMTgzLDIzNiwxMjgsNjcsMTI3LDE0NywxMDYsMjA3LDMzLDQzLDEyMCwyNDAsMjA1LDksOTUsNjksMTAxLDI1NSwyNDEsNjgsMjUzLDY5LDE0MSwzNSw1OCw5MV19LCIweGVmMDI3NGUzMTgxMGM5ZGYwMmY5OGZhZmRlMGY4NDFmNGU2NmExY2QiOnsiaW5kZXg6b21pdGVtcHR5IjoyMSwidm90ZV9hZGRyZXNzIjpbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdfX0sInJlY2VudHMiOnsiMzEyNjg1MjAiOiIweDNmMzQ5YmJhZmVjMTU1MTgxOWI4YmUxZWZlYTJmYzQ2Y2E3NDlhYTEiLCIzMTI2ODUyMSI6IjB4NjFkZDQ4MWExMTRhMmU3NjFjNTU0YjY0MTc0MmM5NzM4Njc4OTlkMyIsIjMxMjY4NTIyIjoiMHg2ODViMWRlZDgwMTM3ODVkNjYyM2NjMThkMjE0MzIwYjZiYjY0NzU5IiwiMzEyNjg1MjMiOiIweDcwZjY1NzE2NGU1Yjc1Njg5YjY0YjdmZDFmYTI3NWYzMzRmMjhlMTgiLCIzMTI2ODUyNCI6IjB4NzJiNjFjNjAxNDM0MmQ5MTQ0NzBlYzdhYzI5NzViZTM0NTc5NmMyYiIsIjMxMjY4NTI1IjoiMHg3YWUyZjViOWUzODZjZDFiNTBhNDU1MDY5NmQ5NTdjYjQ5MDBmMDNhIiwiMzEyNjg1MjYiOiIweDhiNmM4ZmQ5M2Q2ZjRjZWE0MmJiYjM0NWRiYzZmMGRmZGI1YmVjNzMiLCIzMTI2ODUyNyI6IjB4YTZmNzliNjAzNTlmMTQxZGY5MGEwYzc0NTEyNWIxMzFjYWFmZmQxMiIsIjMxMjY4NTI4IjoiMHhiMjE4YzVkNmFmMWY5NzlhYzQyYmM2OGQ5OGE1YTBkNzk2YzZhYjAxIiwiMzEyNjg1MjkiOiIweGI0ZGQ2NmQ3YzJjN2U1N2Y2MjgyMTAxODcxOTJmYjg5ZDRiOTlkZDQiLCIzMTI2ODUzMCI6IjB4YmU4MDdkZGRiMDc0NjM5Y2Q5ZmE2MWI0NzY3NmMwNjRmYzUwZDYyYyJ9LCJyZWNlbnRfZm9ya19oYXNoZXMiOnsiMzEyNjg1MTAiOiJiMTlkZjRhMiIsIjMxMjY4NTExIjoiYjE5ZGY0YTIiLCIzMTI2ODUxMiI6ImIxOWRmNGEyIiwiMzEyNjg1MTMiOiJiMTlkZjRhMiIsIjMxMjY4NTE0IjoiYjE5ZGY0YTIiLCIzMTI2ODUxNSI6ImIxOWRmNGEyIiwiMzEyNjg1MTYiOiJiMTlkZjRhMiIsIjMxMjY4NTE3IjoiYjE5ZGY0YTIiLCIzMTI2ODUxOCI6ImIxOWRmNGEyIiwiMzEyNjg1MTkiOiJiMTlkZjRhMiIsIjMxMjY4NTIwIjoiYjE5ZGY0YTIiLCIzMTI2ODUyMSI6ImIxOWRmNGEyIiwiMzEyNjg1MjIiOiJiMTlkZjRhMiIsIjMxMjY4NTIzIjoiYjE5ZGY0YTIiLCIzMTI2ODUyNCI6ImIxOWRmNGEyIiwiMzEyNjg1MjUiOiJiMTlkZjRhMiIsIjMxMjY4NTI2IjoiYjE5ZGY0YTIiLCIzMTI2ODUyNyI6ImIxOWRmNGEyIiwiMzEyNjg1MjgiOiJiMTlkZjRhMiIsIjMxMjY4NTI5IjoiYjE5ZGY0YTIiLCIzMTI2ODUzMCI6ImIxOWRmNGEyIn0sImF0dGVzdGF0aW9uOm9taXRlbXB0eSI6eyJTb3VyY2VOdW1iZXIiOjMxMjY4NTI4LCJTb3VyY2VIYXNoIjoiMHg1NTc4MGUwMmMyYTE0MjFkZWZmODhmYzIzMmRmMzZiM2EwNjdmNmQ0ZDVkYjhmZGFjYTI4YjQxYmNmNjg0YmZiIiwiVGFyZ2V0TnVtYmVyIjozMTI2ODUyOSwiVGFyZ2V0SGFzaCI6IjB4OTg4ODA1MjYzMTZlMDU3ZWFiOTA4MWE3OWViNDJjYTZjYjhlN2E3YzA4MDZkMTIyYTlhMmY1OGViNTQ3YzcwNSJ9fQ==" }, "finality_at_block": { "number": 31268532, - "hash": "0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7" + "hash": "0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7", + "td": 62131333 } } ]`) @@ -47,33 +52,41 @@ var ( "index": 0, "start_at_block": { "number": 0, - "hash": "0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34" + "hash": "0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34", + "td": 0 }, "finality_at_block": { "number": 0, - "hash": "0x0000000000000000000000000000000000000000000000000000000000000000" + "hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "td": 0 } }, { "index": 1, "start_at_block": { "number": 31268530, - "hash": "0x2ab32e1541202ac43f3dc9ff80b998002ad9130ecc24c40a1f00a8e45dc1f786" + "hash": "0x2ab32e1541202ac43f3dc9ff80b998002ad9130ecc24c40a1f00a8e45dc1f786", + "td": 62348266, + "consensus_data": "eyJudW1iZXIiOjMxMjY4NTMwLCJoYXNoIjoiMHgyYWIzMmUxNTQxMjAyYWM0M2YzZGM5ZmY4MGI5OTgwMDJhZDkxMzBlY2MyNGM0MGExZjAwYThlNDVkYzFmNzg2IiwidmFsaWRhdG9ycyI6eyIweDEyODQyMTRiOWI5Yzg1NTQ5YWIzZDJiOTcyZGYwZGVlZjY2YWMyYzkiOnsiaW5kZXg6b21pdGVtcHR5IjoxLCJ2b3RlX2FkZHJlc3MiOlsxNDIsMTMwLDE0Nyw3NiwxNjksMTE2LDI1MywyMDUsMTUxLDI0Myw0OCwxNTcsMjMzLDEwMywyMTEsMjAxLDE5Niw2MywxNjcsMTcsMTY4LDIxNCwxMTUsMTc1LDkzLDExNyw3MCw4OCw2OCwxOTEsMTM3LDEwNSwyMDAsMjA5LDE0OCwxNDEsMTQ0LDU1LDcyLDE3MiwxMjMsMTM5LDIzLDMyLDI1MCwxMDAsMjI5LDEyXX0sIjB4MzU1NTJjMTY3MDRkMjE0MzQ3ZjI5ZmE3N2Y3N2RhNmQ3NWQ3Yzc1MiI6eyJpbmRleDpvbWl0ZW1wdHkiOjIsInZvdGVfYWRkcmVzcyI6WzE4Myw2NiwxNzMsNzIsODUsMTg2LDIyNyw0OCw2NiwxMDcsMTMwLDYyLDExNiw0NSwxNjMsMzEsMTI5LDEwOCwyMDAsNTksMTkzLDEwOSwxMDUsMTY5LDE5LDc1LDIyNCwyMDcsMTgwLDE2MSwyMDksMTI2LDE5NSw3OSwyNyw5MSw1MCwyMTMsMTk0LDQsNjQsMTg0LDgzLDEwNywzMCwxMzYsMjQwLDI0Ml19LCIweDk4MGE3NWVjZDEzMDllYTEyZmEyZWQ4N2E4NzQ0ZmJmYzliODYzZDUiOnsiaW5kZXg6b21pdGVtcHR5IjozLCJ2b3RlX2FkZHJlc3MiOlsxMzcsMywxMjIsMTU0LDIwNiw1OSw4OSwxLDEwMSwyMzQsMjgsMTIsOTAsMTk5LDQzLDI0NiwwLDE4MywyMDAsMTQwLDMwLDY3LDk1LDY1LDE0Nyw0NCwxNyw1MCwxNzAsMjI1LDE5MSwxNjAsMTg3LDEwNCwyMjgsMTA3LDE1MCwyMDQsMTc3LDQ0LDUyLDIxLDIyOCwyMTYsNDIsMjQ3LDIzLDIxNl19LCIweGEyOTU5ZDNmOTVlYWU1ZGM3ZDcwMTQ0Y2UxYjczYjQwM2I3ZWI2ZTAiOnsiaW5kZXg6b21pdGVtcHR5Ijo0LCJ2b3RlX2FkZHJlc3MiOlsxODUsMTE1LDE5NCwyMTEsMTMyLDEzNSwyMjksMTQzLDIxNCwyMjUsNjksNzMsMjcsMTcsMCwxMjgsMjUxLDIwLDE3MiwxNDUsOTAsNCwxNywyNTIsMTIwLDI0MSwxNTgsOSwxNjMsMTUzLDIyMSwyMzgsMTMsMzIsMTk4LDU4LDExNywyMTYsMjQ5LDQ4LDI0MSwxMDUsNjksNjgsMTczLDQ1LDE5MiwyN119LCIweGI3MWIyMTRjYjg4NTUwMDg0NDM2NWU5NWNkOTk0MmM3Mjc2ZTdmZDgiOnsiaW5kZXg6b21pdGVtcHR5Ijo1LCJ2b3RlX2FkZHJlc3MiOlsxNjIsMTE3LDE0LDE5OCwyMjEsMjM3LDYxLDIwNSwxOTQsMjQzLDgxLDEyMCwzNSwxNiwxNzYsMjM0LDIyMCw3LDEyNSwxODEsMTU0LDE4OCwxNjAsMjQwLDIwNSwzOCwxMTksMTEwLDQ2LDEyMiwyMDMsMTU5LDU5LDIwNiw2NCwxNzcsMjUwLDgyLDMzLDI1MywyMSw5NywzNCwxMDgsOTgsOTksMjA0LDk1XX0sIjB4ZjQ3NGNmMDNjY2VmZjI4YWJjNjVjOWNiYWU1OTRmNzI1YzgwZTEyZCI6eyJpbmRleDpvbWl0ZW1wdHkiOjYsInZvdGVfYWRkcmVzcyI6WzE1MCwyMDEsMTg0LDEwOCw1MiwwLDIyOSw0MSwxOTEsMjI1LDEzMiw1LDExMCwzNywxMjQsNywxNDgsMTEsMTgyLDEwMCw5OSwxMTEsMTA0LDE1OCwxNDEsMzIsMzksMjAwLDUyLDEwNCwzMSwxNDMsMTM1LDEzOSwxMTUsNjgsODIsOTcsMyw3OCwxNDgsMTA3LDE3OCwyMTcsMSwxODAsMTg0LDEyMF19fSwicmVjZW50cyI6eyIzMTI2ODUyNyI6IjB4MzU1NTJjMTY3MDRkMjE0MzQ3ZjI5ZmE3N2Y3N2RhNmQ3NWQ3Yzc1MiIsIjMxMjY4NTI4IjoiMHg5ODBhNzVlY2QxMzA5ZWExMmZhMmVkODdhODc0NGZiZmM5Yjg2M2Q1IiwiMzEyNjg1MjkiOiIweGEyOTU5ZDNmOTVlYWU1ZGM3ZDcwMTQ0Y2UxYjczYjQwM2I3ZWI2ZTAiLCIzMTI2ODUzMCI6IjB4YjcxYjIxNGNiODg1NTAwODQ0MzY1ZTk1Y2Q5OTQyYzcyNzZlN2ZkOCJ9LCJyZWNlbnRfZm9ya19oYXNoZXMiOnsiMzEyNjg1MjUiOiJkYzU1OTA1YyIsIjMxMjY4NTI2IjoiZGM1NTkwNWMiLCIzMTI2ODUyNyI6ImRjNTU5MDVjIiwiMzEyNjg1MjgiOiJkYzU1OTA1YyIsIjMxMjY4NTI5IjoiZGM1NTkwNWMiLCIzMTI2ODUzMCI6ImRjNTU5MDVjIn0sImF0dGVzdGF0aW9uOm9taXRlbXB0eSI6eyJTb3VyY2VOdW1iZXIiOjMxMjY4NTI4LCJTb3VyY2VIYXNoIjoiMHgxMzZjNWI0YzZmODdmOWVkYzQ0NDI5NTkzNzY3YTNhOTg5MWJiM2MxNTZiNzM5OWRlYzRmNjIyMDcwOWQwYjU1IiwiVGFyZ2V0TnVtYmVyIjozMTI2ODUyOSwiVGFyZ2V0SGFzaCI6IjB4YzQyODQxNjYzODBhYzk0OGQzMzhmYzU1ZGI2ZWEyY2E4NWViMDllZDdkYTAwM2QzYTVhNDEzNzMyMjlhZDkwZCJ9fQ==" }, "finality_at_block": { "number": 31268532, - "hash": "0x59203b593d2e4c213e65f68db2c19309380416a93592aa8f923d59aebc481c28" + "hash": "0x59203b593d2e4c213e65f68db2c19309380416a93592aa8f923d59aebc481c28", + "td": 62348270 } }, { "index": 2, "start_at_block": { "number": 33860530, - "hash": "0x252e966e2420ecb2c5c51da62f147ac89004943e2b76c343bb1b2d8465f29a29" + "hash": "0x252e966e2420ecb2c5c51da62f147ac89004943e2b76c343bb1b2d8465f29a29", + "td": 67529251, + "consensus_data": "eyJudW1iZXIiOjMzODYwNTMwLCJoYXNoIjoiMHgyNTJlOTY2ZTI0MjBlY2IyYzVjNTFkYTYyZjE0N2FjODkwMDQ5NDNlMmI3NmMzNDNiYjFiMmQ4NDY1ZjI5YTI5IiwidmFsaWRhdG9ycyI6eyIweDEyODQyMTRiOWI5Yzg1NTQ5YWIzZDJiOTcyZGYwZGVlZjY2YWMyYzkiOnsiaW5kZXg6b21pdGVtcHR5IjoxLCJ2b3RlX2FkZHJlc3MiOlsxNDIsMTMwLDE0Nyw3NiwxNjksMTE2LDI1MywyMDUsMTUxLDI0Myw0OCwxNTcsMjMzLDEwMywyMTEsMjAxLDE5Niw2MywxNjcsMTcsMTY4LDIxNCwxMTUsMTc1LDkzLDExNyw3MCw4OCw2OCwxOTEsMTM3LDEwNSwyMDAsMjA5LDE0OCwxNDEsMTQ0LDU1LDcyLDE3MiwxMjMsMTM5LDIzLDMyLDI1MCwxMDAsMjI5LDEyXX0sIjB4MzU1NTJjMTY3MDRkMjE0MzQ3ZjI5ZmE3N2Y3N2RhNmQ3NWQ3Yzc1MiI6eyJpbmRleDpvbWl0ZW1wdHkiOjIsInZvdGVfYWRkcmVzcyI6WzE4Myw2NiwxNzMsNzIsODUsMTg2LDIyNyw0OCw2NiwxMDcsMTMwLDYyLDExNiw0NSwxNjMsMzEsMTI5LDEwOCwyMDAsNTksMTkzLDEwOSwxMDUsMTY5LDE5LDc1LDIyNCwyMDcsMTgwLDE2MSwyMDksMTI2LDE5NSw3OSwyNyw5MSw1MCwyMTMsMTk0LDQsNjQsMTg0LDgzLDEwNywzMCwxMzYsMjQwLDI0Ml19LCIweDQ3Nzg4Mzg2ZDBlZDZjNzQ4ZTAzYTUzMTYwYjRiMzBlZDM3NDhjYzUiOnsiaW5kZXg6b21pdGVtcHR5IjozLCJ2b3RlX2FkZHJlc3MiOlswLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF19LCIweDk4MGE3NWVjZDEzMDllYTEyZmEyZWQ4N2E4NzQ0ZmJmYzliODYzZDUiOnsiaW5kZXg6b21pdGVtcHR5Ijo0LCJ2b3RlX2FkZHJlc3MiOlsxMzcsMywxMjIsMTU0LDIwNiw1OSw4OSwxLDEwMSwyMzQsMjgsMTIsOTAsMTk5LDQzLDI0NiwwLDE4MywyMDAsMTQwLDMwLDY3LDk1LDY1LDE0Nyw0NCwxNyw1MCwxNzAsMjI1LDE5MSwxNjAsMTg3LDEwNCwyMjgsMTA3LDE1MCwyMDQsMTc3LDQ0LDUyLDIxLDIyOCwyMTYsNDIsMjQ3LDIzLDIxNl19LCIweGEyOTU5ZDNmOTVlYWU1ZGM3ZDcwMTQ0Y2UxYjczYjQwM2I3ZWI2ZTAiOnsiaW5kZXg6b21pdGVtcHR5Ijo1LCJ2b3RlX2FkZHJlc3MiOlsxODUsMTE1LDE5NCwyMTEsMTMyLDEzNSwyMjksMTQzLDIxNCwyMjUsNjksNzMsMjcsMTcsMCwxMjgsMjUxLDIwLDE3MiwxNDUsOTAsNCwxNywyNTIsMTIwLDI0MSwxNTgsOSwxNjMsMTUzLDIyMSwyMzgsMTMsMzIsMTk4LDU4LDExNywyMTYsMjQ5LDQ4LDI0MSwxMDUsNjksNjgsMTczLDQ1LDE5MiwyN119LCIweGI3MWIyMTRjYjg4NTUwMDg0NDM2NWU5NWNkOTk0MmM3Mjc2ZTdmZDgiOnsiaW5kZXg6b21pdGVtcHR5Ijo2LCJ2b3RlX2FkZHJlc3MiOlsxNjIsMTE3LDE0LDE5OCwyMjEsMjM3LDYxLDIwNSwxOTQsMjQzLDgxLDEyMCwzNSwxNiwxNzYsMjM0LDIyMCw3LDEyNSwxODEsMTU0LDE4OCwxNjAsMjQwLDIwNSwzOCwxMTksMTEwLDQ2LDEyMiwyMDMsMTU5LDU5LDIwNiw2NCwxNzcsMjUwLDgyLDMzLDI1MywyMSw5NywzNCwxMDgsOTgsOTksMjA0LDk1XX0sIjB4ZjQ3NGNmMDNjY2VmZjI4YWJjNjVjOWNiYWU1OTRmNzI1YzgwZTEyZCI6eyJpbmRleDpvbWl0ZW1wdHkiOjcsInZvdGVfYWRkcmVzcyI6WzE1MCwyMDEsMTg0LDEwOCw1MiwwLDIyOSw0MSwxOTEsMjI1LDEzMiw1LDExMCwzNywxMjQsNywxNDgsMTEsMTgyLDEwMCw5OSwxMTEsMTA0LDE1OCwxNDEsMzIsMzksMjAwLDUyLDEwNCwzMSwxNDMsMTM1LDEzOSwxMTUsNjgsODIsOTcsMyw3OCwxNDgsMTA3LDE3OCwyMTcsMSwxODAsMTg0LDEyMF19fSwicmVjZW50cyI6eyIzMzg2MDUyNyI6IjB4MzU1NTJjMTY3MDRkMjE0MzQ3ZjI5ZmE3N2Y3N2RhNmQ3NWQ3Yzc1MiIsIjMzODYwNTI4IjoiMHg0Nzc4ODM4NmQwZWQ2Yzc0OGUwM2E1MzE2MGI0YjMwZWQzNzQ4Y2M1IiwiMzM4NjA1MjkiOiIweDk4MGE3NWVjZDEzMDllYTEyZmEyZWQ4N2E4NzQ0ZmJmYzliODYzZDUiLCIzMzg2MDUzMCI6IjB4YTI5NTlkM2Y5NWVhZTVkYzdkNzAxNDRjZTFiNzNiNDAzYjdlYjZlMCJ9LCJyZWNlbnRfZm9ya19oYXNoZXMiOnsiMzM4NjA1MjQiOiJkYzU1OTA1YyIsIjMzODYwNTI1IjoiZGM1NTkwNWMiLCIzMzg2MDUyNiI6ImRjNTU5MDVjIiwiMzM4NjA1MjciOiJkYzU1OTA1YyIsIjMzODYwNTI4IjoiZGM1NTkwNWMiLCIzMzg2MDUyOSI6ImRjNTU5MDVjIiwiMzM4NjA1MzAiOiJkYzU1OTA1YyJ9LCJhdHRlc3RhdGlvbjpvbWl0ZW1wdHkiOnsiU291cmNlTnVtYmVyIjozMzg2MDUyOCwiU291cmNlSGFzaCI6IjB4MGUwNmFhZmMzODU2ZWE2ZDg3OTA1MGJlMWIwNGQ0MjgwNDc1OTkyNDRkZDY2OTE5NzdiMDkwZTA1ZDM0ZTNjZSIsIlRhcmdldE51bWJlciI6MzM4NjA1MjksIlRhcmdldEhhc2giOiIweGFlYzc4ZDlhZjRiYjk0Y2VmNjFiMmU1MDg2OWQwYTVjNzMzZGFiNzI3ZDE1NDcwYjkyMzA2ZmNmNThjMTEzMmUifX0=" }, "finality_at_block": { "number": 33860532, - "hash": "0x424e526d901ae91897340655c81db7de16428a3322df4fa712693bda83572f8f" + "hash": "0x424e526d901ae91897340655c81db7de16428a3322df4fa712693bda83572f8f", + "td": 67529255 } } ]`) @@ -92,7 +105,7 @@ type HisBlockInfo struct { Number uint64 `json:"number"` Hash common.Hash `json:"hash"` TD uint64 `json:"td"` - ConsensusData []byte `json:"consensus_data"` // add consensus data, like parlia snapshot + ConsensusData []byte `json:"consensus_data,omitempty"` // add consensus data, like parlia snapshot } func (b *HisBlockInfo) Equals(c *HisBlockInfo) bool { @@ -186,10 +199,11 @@ func NewHistorySegmentManager(cfg *HistorySegmentConfig) (*HistorySegmentManager switch cfg.Genesis { case BSCGenesisHash: segments = historySegmentsInBSCMainnet - case ChapelGenesisHash: - segments = historySegmentsInBSCChapel - case RialtoGenesisHash: - segments = historySegmentsInBSCRialto + // TODO(0xbundler): temporary got testing + //case ChapelGenesisHash: + // segments = historySegmentsInBSCChapel + //case RialtoGenesisHash: + // segments = historySegmentsInBSCRialto default: segments, err = cfg.LoadCustomSegments() if err != nil { From 1d8fa8b884779f46e09a9522e585617aee9f1884 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:52:11 +0800 Subject: [PATCH 13/22] historysegment: simplify segment definition; --- cmd/geth/chaincmd.go | 64 +++++------ consensus/consensus.go | 2 +- consensus/parlia/parlia.go | 6 +- core/blockchain.go | 4 +- core/blockchain_reader.go | 2 +- core/rawdb/history_segment.go | 10 +- core/vote/vote_pool_test.go | 4 +- eth/backend.go | 8 +- eth/downloader/downloader.go | 10 +- eth/sync_test.go | 12 +-- params/history_segment.go | 190 ++++++++------------------------- params/history_segment_test.go | 116 +++++++++----------- 12 files changed, 147 insertions(+), 281 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 5f74977821..bddd15f892 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -729,21 +729,22 @@ func exportSegment(ctx *cli.Context) error { } var ( - boundStartBlock uint64 - historySegmentLength uint64 - ) - switch genesisHash { - case params.BSCGenesisHash, params.ChapelGenesisHash, params.RialtoGenesisHash: - boundStartBlock = params.BoundStartBlock + boundStartBlock = params.BoundStartBlock historySegmentLength = params.HistorySegmentLength - default: - if ctx.IsSet(utils.BoundStartBlockFlag.Name) { - boundStartBlock = ctx.Uint64(utils.BoundStartBlockFlag.Name) - } - if ctx.IsSet(utils.HistorySegmentLengthFlag.Name) { - historySegmentLength = ctx.Uint64(utils.HistorySegmentLengthFlag.Name) - } - } + ) + // TODO(0xbundler): for testing + //switch genesisHash { + //case params.BSCGenesisHash, params.ChapelGenesisHash, params.RialtoGenesisHash: + // boundStartBlock = params.BoundStartBlock + // historySegmentLength = params.HistorySegmentLength + //default: + if ctx.IsSet(utils.BoundStartBlockFlag.Name) { + boundStartBlock = ctx.Uint64(utils.BoundStartBlockFlag.Name) + } + if ctx.IsSet(utils.HistorySegmentLengthFlag.Name) { + historySegmentLength = ctx.Uint64(utils.HistorySegmentLengthFlag.Name) + } + //} if boundStartBlock == 0 || historySegmentLength == 0 { return fmt.Errorf("wrong params, boundStartBlock: %v, historySegmentLength: %v", boundStartBlock, historySegmentLength) } @@ -757,13 +758,11 @@ func exportSegment(ctx *cli.Context) error { target := latestNum - params.FullImmutabilityThreshold log.Info("start export segment", "from", boundStartBlock, "to", target, "boundStartBlock", boundStartBlock, "historySegmentLength", historySegmentLength, "chainCfg", chainConfig) - segments := []params.HisSegment{ + segments := []params.HistorySegment{ { - Index: 0, - StartAtBlock: params.HisBlockInfo{ - Number: 0, - Hash: genesisHash, - }, + Index: 0, + ReGenesisNumber: 0, + ReGenesisHash: genesisHash, }, } // try find finalized block in every segment boundary @@ -788,26 +787,19 @@ func exportSegment(ctx *cli.Context) error { break } log.Info("found segment boundary", "startAt", ft.Number, "FinalityAt", fs.Number) - segment := params.HisSegment{ - Index: uint64(len(segments)), - StartAtBlock: params.HisBlockInfo{ - Number: ft.Number.Uint64(), - Hash: ft.Hash(), - }, - FinalityAtBlock: params.HisBlockInfo{ - Number: fs.Number.Uint64(), - Hash: fs.Hash(), - }, + segment := params.HistorySegment{ + Index: uint64(len(segments)), + ReGenesisNumber: ft.Number.Uint64(), + ReGenesisHash: ft.Hash(), } - segment.StartAtBlock.TD = headerChain.GetTd(segment.StartAtBlock.Hash, segment.StartAtBlock.Number).Uint64() - segment.FinalityAtBlock.TD = headerChain.GetTd(segment.FinalityAtBlock.Hash, segment.FinalityAtBlock.Number).Uint64() + segment.TD = headerChain.GetTd(segment.ReGenesisHash, segment.ReGenesisNumber).Uint64() // if using posa consensus, just get snapshot as consensus data if p, ok := engine.(consensus.PoSA); ok { enc, err := p.GetConsensusData(headerChain, ft) if err != nil { return err } - segment.StartAtBlock.ConsensusData = enc + segment.ConsensusData = enc } segments = append(segments, segment) } @@ -863,7 +855,7 @@ func pruneHistorySegments(ctx *cli.Context) error { curSegment := hsm.CurSegment(latestHeader.Number.Uint64()) lastSegment, ok := hsm.LastSegment(curSegment) if !ok { - return fmt.Errorf("there is no enough history to prune, cur: %v", curSegment) + return fmt.Errorf("there is no enough history to prune, cur: %v", &curSegment) } // check segment if match hard code @@ -871,8 +863,8 @@ func pruneHistorySegments(ctx *cli.Context) error { return err } - pruneTail := lastSegment.StartAtBlock.Number - log.Info("The older history will be pruned", "lastSegment", lastSegment, "curSegment", curSegment, "pruneTail", pruneTail) + pruneTail := lastSegment.ReGenesisNumber + log.Info("The older history will be pruned", "lastSegment", &lastSegment, "curSegment", &curSegment, "pruneTail", pruneTail) if err = rawdb.PruneTxLookupToTail(db, pruneTail); err != nil { return err } diff --git a/consensus/consensus.go b/consensus/consensus.go index d59a1bd99b..8beecc6175 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -155,5 +155,5 @@ type PoSA interface { VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool GetConsensusData(chain ChainHeaderReader, header *types.Header) ([]byte, error) - SetupLastSegment(segment *params.HisSegment) + SetupLastSegment(segment *params.HistorySegment) } diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 6c4d9343e7..8185852bac 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -233,7 +233,7 @@ type Parlia struct { fakeDiff bool // Skip difficulty verifications // history segment, it provides history segment's consensus data to prevent generate snap from older headers - lastSegment *params.HisSegment + lastSegment *params.HistorySegment } // New creates a Parlia consensus engine. @@ -290,7 +290,7 @@ func New( return c } -func (p *Parlia) SetupLastSegment(segment *params.HisSegment) { +func (p *Parlia) SetupLastSegment(segment *params.HistorySegment) { p.lastSegment = segment } @@ -688,7 +688,7 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash // check history consensus data, load snapshot if p.lastSegment != nil && p.lastSegment.MatchBlock(hash, number) { var tmp Snapshot - err := json.Unmarshal(p.lastSegment.StartAtBlock.ConsensusData, &tmp) + err := json.Unmarshal(p.lastSegment.ConsensusData, &tmp) if err == nil { tmp.config = p.config tmp.sigCache = p.signatures diff --git a/core/blockchain.go b/core/blockchain.go index 3778a9c861..9ab44ec719 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -299,7 +299,7 @@ type BlockChain struct { pipeCommit bool // history segment - lastSegment *params.HisSegment + lastSegment *params.HistorySegment // monitor doubleSignMonitor *monitor.DoubleSignMonitor @@ -560,7 +560,7 @@ func (bc *BlockChain) GetVMConfig() *vm.Config { return &bc.vmConfig } -func (bc *BlockChain) SetupHistorySegment(lastSegment *params.HisSegment) { +func (bc *BlockChain) SetupHistorySegment(lastSegment *params.HistorySegment) { bc.lastSegment = lastSegment } diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index a5bb70239a..a59397ffcb 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -449,7 +449,7 @@ func (bc *BlockChain) SubscribeFinalizedHeaderEvent(ch chan<- FinalizedHeaderEve return bc.scope.Track(bc.finalizedHeaderFeed.Subscribe(ch)) } -func (bc *BlockChain) LastHistorySegment() *params.HisSegment { +func (bc *BlockChain) LastHistorySegment() *params.HistorySegment { return bc.lastSegment } diff --git a/core/rawdb/history_segment.go b/core/rawdb/history_segment.go index d3c0211af1..616c330e84 100644 --- a/core/rawdb/history_segment.go +++ b/core/rawdb/history_segment.go @@ -62,16 +62,12 @@ func PruneTxLookupToTail(db ethdb.KeyValueStore, tail uint64) error { return nil } -func AvailableHistorySegment(db ethdb.Reader, segments ...params.HisSegment) error { +func AvailableHistorySegment(db ethdb.Reader, segments ...params.HistorySegment) error { for _, s := range segments { - hash := ReadCanonicalHash(db, s.StartAtBlock.Number) - if hash != s.StartAtBlock.Hash { + hash := ReadCanonicalHash(db, s.ReGenesisNumber) + if hash != s.ReGenesisHash { return fmt.Errorf("cannot find segment StartAtBlock, seg: %v", s) } - hash = ReadCanonicalHash(db, s.FinalityAtBlock.Number) - if hash != s.FinalityAtBlock.Hash { - return fmt.Errorf("cannot find segment FinalityAtBlock, seg: %v", s) - } } return nil } diff --git a/core/vote/vote_pool_test.go b/core/vote/vote_pool_test.go index be658570c3..69695a0048 100644 --- a/core/vote/vote_pool_test.go +++ b/core/vote/vote_pool_test.go @@ -114,10 +114,10 @@ func (m *mockInvalidPOSA) GetConsensusData(chain consensus.ChainHeaderReader, he return nil, nil } -func (m *mockPOSA) SetupLastSegment(segment *params.HisSegment) { +func (m *mockPOSA) SetupLastSegment(segment *params.HistorySegment) { } -func (m *mockInvalidPOSA) SetupLastSegment(segment *params.HisSegment) { +func (m *mockInvalidPOSA) SetupLastSegment(segment *params.HistorySegment) { } func (pool *VotePool) verifyStructureSizeOfVotePool(receivedVotes, curVotes, futureVotes, curVotesPq, futureVotesPq int) bool { diff --git a/eth/backend.go b/eth/backend.go index bcfed22251..7337a91c87 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -210,7 +210,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if err != nil { return nil, err } - var lastSegment *params.HisSegment + var lastSegment *params.HistorySegment if config.HistorySegmentEnable { _, lastSegment, err = GetHistorySegmentAndLastSegment(chainDb, genesisHash, config.HistorySegmentCustomFile) if err != nil { @@ -402,7 +402,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { return eth, nil } -func GetHistorySegmentAndLastSegment(db ethdb.Database, genesisHash common.Hash, CustomPath string) (*params.HistorySegmentManager, *params.HisSegment, error) { +func GetHistorySegmentAndLastSegment(db ethdb.Database, genesisHash common.Hash, CustomPath string) (*params.HistorySegmentManager, *params.HistorySegment, error) { hsm, err := params.NewHistorySegmentManager(¶ms.HistorySegmentConfig{ CustomPath: CustomPath, Genesis: genesisHash, @@ -426,12 +426,12 @@ func GetHistorySegmentAndLastSegment(db ethdb.Database, genesisHash common.Hash, return hsm, &lastSegment, nil } -func truncateAncientTail(db ethdb.Database, lastSegment *params.HisSegment) error { +func truncateAncientTail(db ethdb.Database, lastSegment *params.HistorySegment) error { if lastSegment == nil { return nil } - pruneTail := lastSegment.StartAtBlock.Number + pruneTail := lastSegment.ReGenesisNumber start := time.Now() old, err := db.TruncateTail(pruneTail) if err != nil { diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index e038292d37..7519f5d129 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -209,7 +209,7 @@ type BlockChain interface { TrieDB() *trie.Database // LastHistorySegment get last history segment - LastHistorySegment() *params.HisSegment + LastHistorySegment() *params.HistorySegment // WriteHeaders just write header into db, it an unsafe interface, just for history segment WriteCanonicalHeaders([]*types.Header, []uint64) error @@ -502,8 +502,8 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * // if enable history segment, ensure local height >= lastSegment height if d.blockchain.LastHistorySegment() != nil { lastSegment := d.blockchain.LastHistorySegment() - if localHeight < lastSegment.StartAtBlock.Number { - localHeight = lastSegment.StartAtBlock.Number + if localHeight < lastSegment.ReGenesisNumber { + localHeight = lastSegment.ReGenesisNumber } } default: @@ -1761,7 +1761,7 @@ func (d *Downloader) findAncestorFromHistorySegment(p *peerConnection, remoteHei return 0, nil } - expect := lastSegment.StartAtBlock.Number + expect := lastSegment.ReGenesisNumber if expect > remoteHeight { return 0, nil } @@ -1779,7 +1779,7 @@ func (d *Downloader) findAncestorFromHistorySegment(p *peerConnection, remoteHei n := headers[0].Number.Uint64() if lastSegment.MatchBlock(h, n) && headers[0].Hash() == h { // just write header, td, because it's snap sync, just sync history is enough - if err = d.blockchain.WriteCanonicalHeaders(headers, []uint64{lastSegment.StartAtBlock.TD}); err != nil { + if err = d.blockchain.WriteCanonicalHeaders(headers, []uint64{lastSegment.TD}); err != nil { return 0, err } return n, nil diff --git a/eth/sync_test.go b/eth/sync_test.go index 449f4ccb38..e32249e3a8 100644 --- a/eth/sync_test.go +++ b/eth/sync_test.go @@ -113,13 +113,11 @@ func TestSnapSyncWithHistorySegment(t *testing.T) { // Create an empty handler and ensure it's in snap sync mode empty := newTestHandlerWithBlocks(0, func(bc *core.BlockChain) (*core.BlockChain, error) { header := full.chain.GetHeaderByNumber(500) - bc.SetupHistorySegment(¶ms.HisSegment{ - Index: 1, - StartAtBlock: params.HisBlockInfo{ - Number: header.Number.Uint64(), - Hash: header.Hash(), - TD: full.chain.GetTd(header.Hash(), header.Number.Uint64()).Uint64(), - }, + bc.SetupHistorySegment(¶ms.HistorySegment{ + Index: 1, + ReGenesisNumber: header.Number.Uint64(), + ReGenesisHash: header.Hash(), + TD: full.chain.GetTd(header.Hash(), header.Number.Uint64()).Uint64(), }) return bc, nil }) diff --git a/params/history_segment.go b/params/history_segment.go index 9ad8339dcc..57a958aa3a 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -16,146 +16,43 @@ const ( ) var ( - historySegmentsInBSCMainnet = unmarshalHisSegments(` -[ - { - "index": 0, - "start_at_block": { - "number": 0, - "hash": "0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b", - "td": 0 - }, - "finality_at_block": { - "number": 0, - "hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "td": 0 - } - }, - { - "index": 1, - "start_at_block": { - "number": 31268530, - "hash": "0xdb8a505f19ef04cb21ae79e3cb641963ffc44f3666e6fde499be55a72b6c7865", - "td": 62131329, - "consensus_data": "eyJudW1iZXIiOjMxMjY4NTMwLCJoYXNoIjoiMHhkYjhhNTA1ZjE5ZWYwNGNiMjFhZTc5ZTNjYjY0MTk2M2ZmYzQ0ZjM2NjZlNmZkZTQ5OWJlNTVhNzJiNmM3ODY1IiwidmFsaWRhdG9ycyI6eyIweDBiYWM0OTIzODY4NjJhZDNkZjRiNjY2YmMwOTZiMDUwNWJiNjk0ZGEiOnsiaW5kZXg6b21pdGVtcHR5IjoxLCJ2b3RlX2FkZHJlc3MiOlsxNzYsMTkwLDE5NSw3MiwxMDQsMjYsMjQ3LDEwMiwxMTcsMjgsMTg0LDU3LDg3LDExMCwxNTYsODEsOTAsOSwyMDAsMTkxLDI1MCw0OCwxNjQsOTgsMTUwLDIwNCwxOTcsMTAyLDE4LDczLDE0LDE4MCwxMjgsMjA4LDU5LDI0OSw3MiwyMjUsMCw1LDE4NywyMDQsNCwzMywyNDksMTEsNjEsNzhdfSwiMHgyNDY1MTc2YzQ2MWFmYjMxNmViYzc3M2M2MWZhZWU4NWE2NTE1ZGFhIjp7ImluZGV4Om9taXRlbXB0eSI6Miwidm90ZV9hZGRyZXNzIjpbMTM4LDE0Niw1MywxMDAsMTk4LDI1NSwyMTEsMTI3LDE3OCwyNTQsMTU5LDE3LDE0MiwyNDgsMTI4LDE0NiwyMzIsMTE4LDQ0LDEyMiwyMjEsMTgxLDM4LDE3MSwxMjYsMTc3LDIzMSwxMTQsMTg2LDIzOSwxMzMsMjQsMzEsMTM3LDQ0LDExNSwyNywyMjQsMTkzLDEzNywyNiw4MCwyMzAsMTc2LDk4LDk4LDIwMCwyMl19LCIweDJkNGM0MDdiYmU0OTQzOGVkODU5ZmU5NjViMTQwZGNmMWFhYjcxYTkiOnsiaW5kZXg6b21pdGVtcHR5IjozLCJ2b3RlX2FkZHJlc3MiOlsxNDcsMTkzLDI0NywyNDYsMTQ2LDE1NywzMSwyMjYsMTYxLDEyMyw3OCwyMCw5Nyw3OCwyNDksMjUyLDkxLDIyMCwxMTMsNjEsMTAyLDQ5LDIxNCwxMTcsNjQsNjMsMTkwLDIzOSwxNzIsODUsOTcsMjcsMjQ2LDE4LDExMiwxMSwyNywxMDEsMjQ0LDExNiw3Miw5NywxODQsMTEsMTUsMTI1LDEwNiwxNzZdfSwiMHgzZjM0OWJiYWZlYzE1NTE4MTliOGJlMWVmZWEyZmM0NmNhNzQ5YWExIjp7ImluZGV4Om9taXRlbXB0eSI6NCwidm90ZV9hZGRyZXNzIjpbMTMyLDM2LDEzOCw2OSwxNDgsMTAwLDIzOCwxOTMsMTYyLDMwLDEyNywxOTksMTgzLDI2LDUsNjEsMTUwLDY4LDIzMywxODcsMTQxLDE2NCwxMzMsNTksMTQzLDEzNSw0NCwyMTUsMTkzLDIxNCwxNzksMzYsMTkxLDI1LDM0LDEzMCwxNTIsNDgsMTAwLDEwOCwyMzQsMjIzLDE4Miw4OCwyMTEsMjIyLDAsMTU0XX0sIjB4NjFkZDQ4MWExMTRhMmU3NjFjNTU0YjY0MTc0MmM5NzM4Njc4OTlkMyI6eyJpbmRleDpvbWl0ZW1wdHkiOjUsInZvdGVfYWRkcmVzcyI6WzEzOCwxMjgsMTUwLDEyNSw1NywyMjgsNiwxNjAsMTY5LDEwMCw0NSw2NSwyMzMsMCwxMjIsMzksMjUyLDE3LDgwLDE2MiwxMDMsMjA5LDY3LDE2OSwyNDcsMTM0LDIwNSw0Myw5NCwyMzYsMTg5LDIwNCw2NCw1NCwzOSw1NSw1LDM0LDkxLDE0OSwxMDksOTQsNDcsMTQzLDk0LDE4NSw5MywzN119LCIweDY4NWIxZGVkODAxMzc4NWQ2NjIzY2MxOGQyMTQzMjBiNmJiNjQ3NTkiOnsiaW5kZXg6b21pdGVtcHR5Ijo2LCJ2b3RlX2FkZHJlc3MiOlsxMzgsOTYsMjQ4LDQyLDEyMywyMDcsMTE2LDE4MCwyMDMsNSw1OSwxNTUsMjU0LDEzMSwyMDgsMjM3LDIsMTY4LDc4LDE4NywxNiwxMzQsOTMsMjUzLDIxNiwyMjYsMTEwLDExNyw1MywxOTYsNTgsMjgsMjA0LDIxMCwxMDQsMjMyLDk2LDI0NSwyLDMzLDEwNyw1NSwxNTcsMjUyLDE1MywxMTMsMjExLDg4XX0sIjB4NzBmNjU3MTY0ZTViNzU2ODliNjRiN2ZkMWZhMjc1ZjMzNGYyOGUxOCI6eyJpbmRleDpvbWl0ZW1wdHkiOjcsInZvdGVfYWRkcmVzcyI6WzE1MCwxNjIsMTA2LDI1MCwxOCwxNDksMjE4LDEyOSw2NSwxMzMsMTQ3LDE4OSwxOCwxMjksNjgsOTksMjE3LDI0NiwyMjgsOTIsNTQsMTYwLDIyOCwxMjYsMTgwLDIwNSw2Miw5MSwxMDYsMjQyLDE1Niw2NSwyMjYsMTYzLDE2NSw5OSwxMDAsNDgsMjEsOTAsNzAsMTEwLDMzLDEwMSwxMzMsMTc1LDU5LDE2N119LCIweDcyYjYxYzYwMTQzNDJkOTE0NDcwZWM3YWMyOTc1YmUzNDU3OTZjMmIiOnsiaW5kZXg6b21pdGVtcHR5Ijo4LCJ2b3RlX2FkZHJlc3MiOlsxMjksMjE5LDQsMzQsMTY1LDI1Myw4LDIyOCwxMywxNzcsMjUyLDM1LDEwNCwyMTAsMzYsOTQsNzUsMjQsMTc3LDIwOCwxODQsOTIsMTQ2LDI2LDE3MCwxNzUsMjEwLDIyNyw2NSwxMTgsMTQsNDEsMjUyLDk3LDYyLDIyMSw1NywyNDcsMTgsODQsOTcsNzgsMzIsODUsMTk1LDQwLDEyMiw4MV19LCIweDdhZTJmNWI5ZTM4NmNkMWI1MGE0NTUwNjk2ZDk1N2NiNDkwMGYwM2EiOnsiaW5kZXg6b21pdGVtcHR5Ijo5LCJ2b3RlX2FkZHJlc3MiOlsxODQsNzksMTMxLDI1NSw0NSwyNDQsNjUsMTQ3LDczLDEwMywxNDcsMTg0LDcxLDI0Niw3OCwxNTcsMTA5LDE3NywxNzksMTQ5LDU0LDEzMCwxODcsMTQ5LDIzNywyMDgsMTUwLDIzNSwzMCwxMDUsMTg3LDIxMSw4NywxOTQsMCwxNTMsNDQsMTY3LDEyOCw4MCwyMDgsMjAzLDIyNSwxMjgsMjA3LDE3MCwxLDE0Ml19LCIweDhiNmM4ZmQ5M2Q2ZjRjZWE0MmJiYjM0NWRiYzZmMGRmZGI1YmVjNzMiOnsiaW5kZXg6b21pdGVtcHR5IjoxMCwidm90ZV9hZGRyZXNzIjpbMTY4LDE2Miw4Nyw3LDc4LDEzMCwxODQsMTI5LDIwNywxNjAsMTEwLDI0MywyMzUsNzgsMjU0LDIwMiw2LDEyLDM3LDQ5LDUzLDE1NCwxODksMTQsMTcxLDEzOCwyNDEsMjI3LDIzNywyNTAsMzIsMzcsMjUyLDE2NCwxMDAsMTcyLDE1Niw2MywyMDksMzUsMjQ2LDE5NCw3NCwxMywxMjAsMTM0LDE0OCwxMzNdfSwiMHhhNmY3OWI2MDM1OWYxNDFkZjkwYTBjNzQ1MTI1YjEzMWNhYWZmZDEyIjp7ImluZGV4Om9taXRlbXB0eSI6MTEsInZvdGVfYWRkcmVzcyI6WzE4MywxMTQsMjI1LDEyOCwyNTEsMjQzLDEzOCw1LDI4LDE1MSwyMTgsMTg4LDEzOCwxNzAsMSwzOCwxNjIsNTEsMTY5LDIzMiw0MCwyMDUsMTc1LDIwNCwxMTYsMzQsMTk2LDE4NywzMSw2NCw0OCwxNjUsMTA3LDE2MywxMDAsMTk3LDY1LDMsMjQyLDEwNywxNzMsMTQ1LDgwLDEzOSw4MiwzMiwxODMsNjVdfSwiMHhiMjE4YzVkNmFmMWY5NzlhYzQyYmM2OGQ5OGE1YTBkNzk2YzZhYjAxIjp7ImluZGV4Om9taXRlbXB0eSI6MTIsInZvdGVfYWRkcmVzcyI6WzE4Miw4OSwxNzMsMTUsMTg5LDE1OSw4MSw4OCwxNDcsMjUzLDIxNSw2NCwxNzgsMTU1LDE2MCwxMTksNDUsMTg5LDIzMywxODAsOTksODksMzMsMjIxLDE0NSwxODksNDEsOTksMTYwLDI1MiwxMzMsOTQsNDksMjQ2LDUxLDE0Myw2OSwxNzgsMTcsMTk2LDIzMywyMjIsMjE5LDEyNyw0NiwxNzYsMTU3LDIzMV19LCIweGI0ZGQ2NmQ3YzJjN2U1N2Y2MjgyMTAxODcxOTJmYjg5ZDRiOTlkZDQiOnsiaW5kZXg6b21pdGVtcHR5IjoxMywidm90ZV9hZGRyZXNzIjpbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdfSwiMHhiZTgwN2RkZGIwNzQ2MzljZDlmYTYxYjQ3Njc2YzA2NGZjNTBkNjJjIjp7ImluZGV4Om9taXRlbXB0eSI6MTQsInZvdGVfYWRkcmVzcyI6WzE3NywyNDIsMTk5LDIxLDExOSwyMjIsMjQzLDIwLDc5LDE3MSwyMzUsMTE3LDE2OCwxNjEsMjAwLDIwMyw5MSw4MSwyMDksMjA5LDE4MCwxNjAsOTQsMjM2LDEwMywxNTIsMTM5LDEzNCwxMzMsMCwxMzksMTcwLDIzLDY5LDE1OCwxOTYsMzcsMjE5LDE3NCwxODgsMTMzLDQ3LDczLDEwOSwyMDEsMzMsMTUwLDIwNV19LCIweGNjOGU2ZDAwYzE3ZWI0MzEzNTBjNmM1MGQ4YjhmMDUxNzZiOTBiMTEiOnsiaW5kZXg6b21pdGVtcHR5IjoxNSwidm90ZV9hZGRyZXNzIjpbMTc5LDE2MywyMTIsMjU0LDE4NCwzNywxNzQsMTUxLDIsMTEzLDIxLDEwMiwyMjMsOTMsMTkxLDU2LDIzMiw0MiwyMjEsNzcsMjA5LDE4MSwxMTUsMTg1LDkzLDM2LDEwMiwyNTAsMTAxLDEsMjA0LDE4NCwzMCwxNTcsMzgsMTYzLDgyLDE4NSw5Nyw4MCwyMDQsMTkxLDEyMywxMDUsMTI3LDIwOCwxNjQsMjVdfSwiMHhjZTJmZDc1NDRlMGIyY2M5NDY5MmQ0YTcwNGRlYmVmN2JjYjYxMzI4Ijp7ImluZGV4Om9taXRlbXB0eSI6MTYsInZvdGVfYWRkcmVzcyI6WzE4Miw3NCwxOTAsMzcsOTcsNzYsMTU2LDI1Myw1MCwyMjgsODYsMTgwLDIxMywzMywyNDIsMTU2LDEzMSw4NywyNDQsMTc1LDcwLDYsMTUxLDEzMCwxNTAsMjAxLDE5MCwxNDcsNzMsNjQsMTE0LDE3Miw1LDI1MCwxMzQsMjI3LDIxMCwxMjQsMjAwLDIxNCwxMTAsMTAxLDAsMTUsMTM5LDE2Myw2MywxODddfSwiMHhlMmQzYTczOWVmZmNkM2E5OTM4N2QwMTVlMjYwZWVmYWM3MmViZWExIjp7ImluZGV4Om9taXRlbXB0eSI6MTcsInZvdGVfYWRkcmVzcyI6WzE0OSwxMDgsNzEsMTMsMjIzLDI0NCwxNDAsMTgwLDE0NywwLDMyLDExLDk1LDEzMSw3MywxMjcsNTgsNjAsMjAzLDU4LDIzNSwxMzEsMTk3LDIzNywyMTcsMTI5LDEzMywxMDUsMywxNDIsOTcsMjA5LDE1MSwyNCw3OSw3NCwxNjYsMTQ3LDE1OCwxNjUsMjMzLDE0NSwzMCw2MiwxNTIsMTcyLDEwOSwzM119LCIweGU5YWUzMjYxYTQ3NWEyN2JiMTAyOGYxNDBiYzJhN2M4NDMzMThhZmQiOnsiaW5kZXg6b21pdGVtcHR5IjoxOCwidm90ZV9hZGRyZXNzIjpbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdfSwiMHhlYTBhNmUzYzUxMWJiZDEwZjQ1MTllY2UzN2RjMjQ4ODdlMTFiNTVkIjp7ImluZGV4Om9taXRlbXB0eSI6MTksInZvdGVfYWRkcmVzcyI6WzE3OCwyMTIsMTk4LDQwLDYwLDY4LDE2MSwxOTksMTg5LDgwLDU4LDE3MSwxNjcsMTAyLDExMCwxNTksMTIsMTMxLDE0LDE1LDI0MCwyMiwxOTMsMTk5LDgwLDE2NSwyMjgsMTM1LDg3LDE2NywxOSwyMDgsMTMxLDEwNywyOCwxNzEsMjUzLDkyLDQwLDI3LDI5LDIyNywxODMsMTI1LDI4LDI1LDMzLDEzMV19LCIweGVlMjI2Mzc5ZGI4M2NmZmM2ODE0OTU3MzBjMTFmZGRlNzliYTRjMGMiOnsiaW5kZXg6b21pdGVtcHR5IjoyMCwidm90ZV9hZGRyZXNzIjpbMTc0LDEyMywxOTgsMjUwLDE2MywyNDAsMjA0LDYyLDk2LDE0NywxODIsNTEsMjUzLDEyNiwyMjgsMjQ4LDEwNSwxMTIsMTQ2LDEwNSw4OCwyMDgsMTgzLDIzNiwxMjgsNjcsMTI3LDE0NywxMDYsMjA3LDMzLDQzLDEyMCwyNDAsMjA1LDksOTUsNjksMTAxLDI1NSwyNDEsNjgsMjUzLDY5LDE0MSwzNSw1OCw5MV19LCIweGVmMDI3NGUzMTgxMGM5ZGYwMmY5OGZhZmRlMGY4NDFmNGU2NmExY2QiOnsiaW5kZXg6b21pdGVtcHR5IjoyMSwidm90ZV9hZGRyZXNzIjpbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdfX0sInJlY2VudHMiOnsiMzEyNjg1MjAiOiIweDNmMzQ5YmJhZmVjMTU1MTgxOWI4YmUxZWZlYTJmYzQ2Y2E3NDlhYTEiLCIzMTI2ODUyMSI6IjB4NjFkZDQ4MWExMTRhMmU3NjFjNTU0YjY0MTc0MmM5NzM4Njc4OTlkMyIsIjMxMjY4NTIyIjoiMHg2ODViMWRlZDgwMTM3ODVkNjYyM2NjMThkMjE0MzIwYjZiYjY0NzU5IiwiMzEyNjg1MjMiOiIweDcwZjY1NzE2NGU1Yjc1Njg5YjY0YjdmZDFmYTI3NWYzMzRmMjhlMTgiLCIzMTI2ODUyNCI6IjB4NzJiNjFjNjAxNDM0MmQ5MTQ0NzBlYzdhYzI5NzViZTM0NTc5NmMyYiIsIjMxMjY4NTI1IjoiMHg3YWUyZjViOWUzODZjZDFiNTBhNDU1MDY5NmQ5NTdjYjQ5MDBmMDNhIiwiMzEyNjg1MjYiOiIweDhiNmM4ZmQ5M2Q2ZjRjZWE0MmJiYjM0NWRiYzZmMGRmZGI1YmVjNzMiLCIzMTI2ODUyNyI6IjB4YTZmNzliNjAzNTlmMTQxZGY5MGEwYzc0NTEyNWIxMzFjYWFmZmQxMiIsIjMxMjY4NTI4IjoiMHhiMjE4YzVkNmFmMWY5NzlhYzQyYmM2OGQ5OGE1YTBkNzk2YzZhYjAxIiwiMzEyNjg1MjkiOiIweGI0ZGQ2NmQ3YzJjN2U1N2Y2MjgyMTAxODcxOTJmYjg5ZDRiOTlkZDQiLCIzMTI2ODUzMCI6IjB4YmU4MDdkZGRiMDc0NjM5Y2Q5ZmE2MWI0NzY3NmMwNjRmYzUwZDYyYyJ9LCJyZWNlbnRfZm9ya19oYXNoZXMiOnsiMzEyNjg1MTAiOiJiMTlkZjRhMiIsIjMxMjY4NTExIjoiYjE5ZGY0YTIiLCIzMTI2ODUxMiI6ImIxOWRmNGEyIiwiMzEyNjg1MTMiOiJiMTlkZjRhMiIsIjMxMjY4NTE0IjoiYjE5ZGY0YTIiLCIzMTI2ODUxNSI6ImIxOWRmNGEyIiwiMzEyNjg1MTYiOiJiMTlkZjRhMiIsIjMxMjY4NTE3IjoiYjE5ZGY0YTIiLCIzMTI2ODUxOCI6ImIxOWRmNGEyIiwiMzEyNjg1MTkiOiJiMTlkZjRhMiIsIjMxMjY4NTIwIjoiYjE5ZGY0YTIiLCIzMTI2ODUyMSI6ImIxOWRmNGEyIiwiMzEyNjg1MjIiOiJiMTlkZjRhMiIsIjMxMjY4NTIzIjoiYjE5ZGY0YTIiLCIzMTI2ODUyNCI6ImIxOWRmNGEyIiwiMzEyNjg1MjUiOiJiMTlkZjRhMiIsIjMxMjY4NTI2IjoiYjE5ZGY0YTIiLCIzMTI2ODUyNyI6ImIxOWRmNGEyIiwiMzEyNjg1MjgiOiJiMTlkZjRhMiIsIjMxMjY4NTI5IjoiYjE5ZGY0YTIiLCIzMTI2ODUzMCI6ImIxOWRmNGEyIn0sImF0dGVzdGF0aW9uOm9taXRlbXB0eSI6eyJTb3VyY2VOdW1iZXIiOjMxMjY4NTI4LCJTb3VyY2VIYXNoIjoiMHg1NTc4MGUwMmMyYTE0MjFkZWZmODhmYzIzMmRmMzZiM2EwNjdmNmQ0ZDVkYjhmZGFjYTI4YjQxYmNmNjg0YmZiIiwiVGFyZ2V0TnVtYmVyIjozMTI2ODUyOSwiVGFyZ2V0SGFzaCI6IjB4OTg4ODA1MjYzMTZlMDU3ZWFiOTA4MWE3OWViNDJjYTZjYjhlN2E3YzA4MDZkMTIyYTlhMmY1OGViNTQ3YzcwNSJ9fQ==" - }, - "finality_at_block": { - "number": 31268532, - "hash": "0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7", - "td": 62131333 - } - } -]`) - historySegmentsInBSCChapel = unmarshalHisSegments(` -[ - { - "index": 0, - "start_at_block": { - "number": 0, - "hash": "0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34", - "td": 0 - }, - "finality_at_block": { - "number": 0, - "hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "td": 0 - } - }, - { - "index": 1, - "start_at_block": { - "number": 31268530, - "hash": "0x2ab32e1541202ac43f3dc9ff80b998002ad9130ecc24c40a1f00a8e45dc1f786", - "td": 62348266, - "consensus_data": "eyJudW1iZXIiOjMxMjY4NTMwLCJoYXNoIjoiMHgyYWIzMmUxNTQxMjAyYWM0M2YzZGM5ZmY4MGI5OTgwMDJhZDkxMzBlY2MyNGM0MGExZjAwYThlNDVkYzFmNzg2IiwidmFsaWRhdG9ycyI6eyIweDEyODQyMTRiOWI5Yzg1NTQ5YWIzZDJiOTcyZGYwZGVlZjY2YWMyYzkiOnsiaW5kZXg6b21pdGVtcHR5IjoxLCJ2b3RlX2FkZHJlc3MiOlsxNDIsMTMwLDE0Nyw3NiwxNjksMTE2LDI1MywyMDUsMTUxLDI0Myw0OCwxNTcsMjMzLDEwMywyMTEsMjAxLDE5Niw2MywxNjcsMTcsMTY4LDIxNCwxMTUsMTc1LDkzLDExNyw3MCw4OCw2OCwxOTEsMTM3LDEwNSwyMDAsMjA5LDE0OCwxNDEsMTQ0LDU1LDcyLDE3MiwxMjMsMTM5LDIzLDMyLDI1MCwxMDAsMjI5LDEyXX0sIjB4MzU1NTJjMTY3MDRkMjE0MzQ3ZjI5ZmE3N2Y3N2RhNmQ3NWQ3Yzc1MiI6eyJpbmRleDpvbWl0ZW1wdHkiOjIsInZvdGVfYWRkcmVzcyI6WzE4Myw2NiwxNzMsNzIsODUsMTg2LDIyNyw0OCw2NiwxMDcsMTMwLDYyLDExNiw0NSwxNjMsMzEsMTI5LDEwOCwyMDAsNTksMTkzLDEwOSwxMDUsMTY5LDE5LDc1LDIyNCwyMDcsMTgwLDE2MSwyMDksMTI2LDE5NSw3OSwyNyw5MSw1MCwyMTMsMTk0LDQsNjQsMTg0LDgzLDEwNywzMCwxMzYsMjQwLDI0Ml19LCIweDk4MGE3NWVjZDEzMDllYTEyZmEyZWQ4N2E4NzQ0ZmJmYzliODYzZDUiOnsiaW5kZXg6b21pdGVtcHR5IjozLCJ2b3RlX2FkZHJlc3MiOlsxMzcsMywxMjIsMTU0LDIwNiw1OSw4OSwxLDEwMSwyMzQsMjgsMTIsOTAsMTk5LDQzLDI0NiwwLDE4MywyMDAsMTQwLDMwLDY3LDk1LDY1LDE0Nyw0NCwxNyw1MCwxNzAsMjI1LDE5MSwxNjAsMTg3LDEwNCwyMjgsMTA3LDE1MCwyMDQsMTc3LDQ0LDUyLDIxLDIyOCwyMTYsNDIsMjQ3LDIzLDIxNl19LCIweGEyOTU5ZDNmOTVlYWU1ZGM3ZDcwMTQ0Y2UxYjczYjQwM2I3ZWI2ZTAiOnsiaW5kZXg6b21pdGVtcHR5Ijo0LCJ2b3RlX2FkZHJlc3MiOlsxODUsMTE1LDE5NCwyMTEsMTMyLDEzNSwyMjksMTQzLDIxNCwyMjUsNjksNzMsMjcsMTcsMCwxMjgsMjUxLDIwLDE3MiwxNDUsOTAsNCwxNywyNTIsMTIwLDI0MSwxNTgsOSwxNjMsMTUzLDIyMSwyMzgsMTMsMzIsMTk4LDU4LDExNywyMTYsMjQ5LDQ4LDI0MSwxMDUsNjksNjgsMTczLDQ1LDE5MiwyN119LCIweGI3MWIyMTRjYjg4NTUwMDg0NDM2NWU5NWNkOTk0MmM3Mjc2ZTdmZDgiOnsiaW5kZXg6b21pdGVtcHR5Ijo1LCJ2b3RlX2FkZHJlc3MiOlsxNjIsMTE3LDE0LDE5OCwyMjEsMjM3LDYxLDIwNSwxOTQsMjQzLDgxLDEyMCwzNSwxNiwxNzYsMjM0LDIyMCw3LDEyNSwxODEsMTU0LDE4OCwxNjAsMjQwLDIwNSwzOCwxMTksMTEwLDQ2LDEyMiwyMDMsMTU5LDU5LDIwNiw2NCwxNzcsMjUwLDgyLDMzLDI1MywyMSw5NywzNCwxMDgsOTgsOTksMjA0LDk1XX0sIjB4ZjQ3NGNmMDNjY2VmZjI4YWJjNjVjOWNiYWU1OTRmNzI1YzgwZTEyZCI6eyJpbmRleDpvbWl0ZW1wdHkiOjYsInZvdGVfYWRkcmVzcyI6WzE1MCwyMDEsMTg0LDEwOCw1MiwwLDIyOSw0MSwxOTEsMjI1LDEzMiw1LDExMCwzNywxMjQsNywxNDgsMTEsMTgyLDEwMCw5OSwxMTEsMTA0LDE1OCwxNDEsMzIsMzksMjAwLDUyLDEwNCwzMSwxNDMsMTM1LDEzOSwxMTUsNjgsODIsOTcsMyw3OCwxNDgsMTA3LDE3OCwyMTcsMSwxODAsMTg0LDEyMF19fSwicmVjZW50cyI6eyIzMTI2ODUyNyI6IjB4MzU1NTJjMTY3MDRkMjE0MzQ3ZjI5ZmE3N2Y3N2RhNmQ3NWQ3Yzc1MiIsIjMxMjY4NTI4IjoiMHg5ODBhNzVlY2QxMzA5ZWExMmZhMmVkODdhODc0NGZiZmM5Yjg2M2Q1IiwiMzEyNjg1MjkiOiIweGEyOTU5ZDNmOTVlYWU1ZGM3ZDcwMTQ0Y2UxYjczYjQwM2I3ZWI2ZTAiLCIzMTI2ODUzMCI6IjB4YjcxYjIxNGNiODg1NTAwODQ0MzY1ZTk1Y2Q5OTQyYzcyNzZlN2ZkOCJ9LCJyZWNlbnRfZm9ya19oYXNoZXMiOnsiMzEyNjg1MjUiOiJkYzU1OTA1YyIsIjMxMjY4NTI2IjoiZGM1NTkwNWMiLCIzMTI2ODUyNyI6ImRjNTU5MDVjIiwiMzEyNjg1MjgiOiJkYzU1OTA1YyIsIjMxMjY4NTI5IjoiZGM1NTkwNWMiLCIzMTI2ODUzMCI6ImRjNTU5MDVjIn0sImF0dGVzdGF0aW9uOm9taXRlbXB0eSI6eyJTb3VyY2VOdW1iZXIiOjMxMjY4NTI4LCJTb3VyY2VIYXNoIjoiMHgxMzZjNWI0YzZmODdmOWVkYzQ0NDI5NTkzNzY3YTNhOTg5MWJiM2MxNTZiNzM5OWRlYzRmNjIyMDcwOWQwYjU1IiwiVGFyZ2V0TnVtYmVyIjozMTI2ODUyOSwiVGFyZ2V0SGFzaCI6IjB4YzQyODQxNjYzODBhYzk0OGQzMzhmYzU1ZGI2ZWEyY2E4NWViMDllZDdkYTAwM2QzYTVhNDEzNzMyMjlhZDkwZCJ9fQ==" - }, - "finality_at_block": { - "number": 31268532, - "hash": "0x59203b593d2e4c213e65f68db2c19309380416a93592aa8f923d59aebc481c28", - "td": 62348270 - } - }, - { - "index": 2, - "start_at_block": { - "number": 33860530, - "hash": "0x252e966e2420ecb2c5c51da62f147ac89004943e2b76c343bb1b2d8465f29a29", - "td": 67529251, - "consensus_data": "eyJudW1iZXIiOjMzODYwNTMwLCJoYXNoIjoiMHgyNTJlOTY2ZTI0MjBlY2IyYzVjNTFkYTYyZjE0N2FjODkwMDQ5NDNlMmI3NmMzNDNiYjFiMmQ4NDY1ZjI5YTI5IiwidmFsaWRhdG9ycyI6eyIweDEyODQyMTRiOWI5Yzg1NTQ5YWIzZDJiOTcyZGYwZGVlZjY2YWMyYzkiOnsiaW5kZXg6b21pdGVtcHR5IjoxLCJ2b3RlX2FkZHJlc3MiOlsxNDIsMTMwLDE0Nyw3NiwxNjksMTE2LDI1MywyMDUsMTUxLDI0Myw0OCwxNTcsMjMzLDEwMywyMTEsMjAxLDE5Niw2MywxNjcsMTcsMTY4LDIxNCwxMTUsMTc1LDkzLDExNyw3MCw4OCw2OCwxOTEsMTM3LDEwNSwyMDAsMjA5LDE0OCwxNDEsMTQ0LDU1LDcyLDE3MiwxMjMsMTM5LDIzLDMyLDI1MCwxMDAsMjI5LDEyXX0sIjB4MzU1NTJjMTY3MDRkMjE0MzQ3ZjI5ZmE3N2Y3N2RhNmQ3NWQ3Yzc1MiI6eyJpbmRleDpvbWl0ZW1wdHkiOjIsInZvdGVfYWRkcmVzcyI6WzE4Myw2NiwxNzMsNzIsODUsMTg2LDIyNyw0OCw2NiwxMDcsMTMwLDYyLDExNiw0NSwxNjMsMzEsMTI5LDEwOCwyMDAsNTksMTkzLDEwOSwxMDUsMTY5LDE5LDc1LDIyNCwyMDcsMTgwLDE2MSwyMDksMTI2LDE5NSw3OSwyNyw5MSw1MCwyMTMsMTk0LDQsNjQsMTg0LDgzLDEwNywzMCwxMzYsMjQwLDI0Ml19LCIweDQ3Nzg4Mzg2ZDBlZDZjNzQ4ZTAzYTUzMTYwYjRiMzBlZDM3NDhjYzUiOnsiaW5kZXg6b21pdGVtcHR5IjozLCJ2b3RlX2FkZHJlc3MiOlswLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF19LCIweDk4MGE3NWVjZDEzMDllYTEyZmEyZWQ4N2E4NzQ0ZmJmYzliODYzZDUiOnsiaW5kZXg6b21pdGVtcHR5Ijo0LCJ2b3RlX2FkZHJlc3MiOlsxMzcsMywxMjIsMTU0LDIwNiw1OSw4OSwxLDEwMSwyMzQsMjgsMTIsOTAsMTk5LDQzLDI0NiwwLDE4MywyMDAsMTQwLDMwLDY3LDk1LDY1LDE0Nyw0NCwxNyw1MCwxNzAsMjI1LDE5MSwxNjAsMTg3LDEwNCwyMjgsMTA3LDE1MCwyMDQsMTc3LDQ0LDUyLDIxLDIyOCwyMTYsNDIsMjQ3LDIzLDIxNl19LCIweGEyOTU5ZDNmOTVlYWU1ZGM3ZDcwMTQ0Y2UxYjczYjQwM2I3ZWI2ZTAiOnsiaW5kZXg6b21pdGVtcHR5Ijo1LCJ2b3RlX2FkZHJlc3MiOlsxODUsMTE1LDE5NCwyMTEsMTMyLDEzNSwyMjksMTQzLDIxNCwyMjUsNjksNzMsMjcsMTcsMCwxMjgsMjUxLDIwLDE3MiwxNDUsOTAsNCwxNywyNTIsMTIwLDI0MSwxNTgsOSwxNjMsMTUzLDIyMSwyMzgsMTMsMzIsMTk4LDU4LDExNywyMTYsMjQ5LDQ4LDI0MSwxMDUsNjksNjgsMTczLDQ1LDE5MiwyN119LCIweGI3MWIyMTRjYjg4NTUwMDg0NDM2NWU5NWNkOTk0MmM3Mjc2ZTdmZDgiOnsiaW5kZXg6b21pdGVtcHR5Ijo2LCJ2b3RlX2FkZHJlc3MiOlsxNjIsMTE3LDE0LDE5OCwyMjEsMjM3LDYxLDIwNSwxOTQsMjQzLDgxLDEyMCwzNSwxNiwxNzYsMjM0LDIyMCw3LDEyNSwxODEsMTU0LDE4OCwxNjAsMjQwLDIwNSwzOCwxMTksMTEwLDQ2LDEyMiwyMDMsMTU5LDU5LDIwNiw2NCwxNzcsMjUwLDgyLDMzLDI1MywyMSw5NywzNCwxMDgsOTgsOTksMjA0LDk1XX0sIjB4ZjQ3NGNmMDNjY2VmZjI4YWJjNjVjOWNiYWU1OTRmNzI1YzgwZTEyZCI6eyJpbmRleDpvbWl0ZW1wdHkiOjcsInZvdGVfYWRkcmVzcyI6WzE1MCwyMDEsMTg0LDEwOCw1MiwwLDIyOSw0MSwxOTEsMjI1LDEzMiw1LDExMCwzNywxMjQsNywxNDgsMTEsMTgyLDEwMCw5OSwxMTEsMTA0LDE1OCwxNDEsMzIsMzksMjAwLDUyLDEwNCwzMSwxNDMsMTM1LDEzOSwxMTUsNjgsODIsOTcsMyw3OCwxNDgsMTA3LDE3OCwyMTcsMSwxODAsMTg0LDEyMF19fSwicmVjZW50cyI6eyIzMzg2MDUyNyI6IjB4MzU1NTJjMTY3MDRkMjE0MzQ3ZjI5ZmE3N2Y3N2RhNmQ3NWQ3Yzc1MiIsIjMzODYwNTI4IjoiMHg0Nzc4ODM4NmQwZWQ2Yzc0OGUwM2E1MzE2MGI0YjMwZWQzNzQ4Y2M1IiwiMzM4NjA1MjkiOiIweDk4MGE3NWVjZDEzMDllYTEyZmEyZWQ4N2E4NzQ0ZmJmYzliODYzZDUiLCIzMzg2MDUzMCI6IjB4YTI5NTlkM2Y5NWVhZTVkYzdkNzAxNDRjZTFiNzNiNDAzYjdlYjZlMCJ9LCJyZWNlbnRfZm9ya19oYXNoZXMiOnsiMzM4NjA1MjQiOiJkYzU1OTA1YyIsIjMzODYwNTI1IjoiZGM1NTkwNWMiLCIzMzg2MDUyNiI6ImRjNTU5MDVjIiwiMzM4NjA1MjciOiJkYzU1OTA1YyIsIjMzODYwNTI4IjoiZGM1NTkwNWMiLCIzMzg2MDUyOSI6ImRjNTU5MDVjIiwiMzM4NjA1MzAiOiJkYzU1OTA1YyJ9LCJhdHRlc3RhdGlvbjpvbWl0ZW1wdHkiOnsiU291cmNlTnVtYmVyIjozMzg2MDUyOCwiU291cmNlSGFzaCI6IjB4MGUwNmFhZmMzODU2ZWE2ZDg3OTA1MGJlMWIwNGQ0MjgwNDc1OTkyNDRkZDY2OTE5NzdiMDkwZTA1ZDM0ZTNjZSIsIlRhcmdldE51bWJlciI6MzM4NjA1MjksIlRhcmdldEhhc2giOiIweGFlYzc4ZDlhZjRiYjk0Y2VmNjFiMmU1MDg2OWQwYTVjNzMzZGFiNzI3ZDE1NDcwYjkyMzA2ZmNmNThjMTEzMmUifX0=" - }, - "finality_at_block": { - "number": 33860532, - "hash": "0x424e526d901ae91897340655c81db7de16428a3322df4fa712693bda83572f8f", - "td": 67529255 - } - } -]`) - historySegmentsInBSCRialto = []HisSegment{ - { - Index: 0, - StartAtBlock: HisBlockInfo{ - Number: 0, - Hash: RialtoGenesisHash, - }, - }, - } + historySegmentsInBSCMainnet []HistorySegment + historySegmentsInBSCChapel []HistorySegment ) -type HisBlockInfo struct { - Number uint64 `json:"number"` - Hash common.Hash `json:"hash"` - TD uint64 `json:"td"` - ConsensusData []byte `json:"consensus_data,omitempty"` // add consensus data, like parlia snapshot -} - -func (b *HisBlockInfo) Equals(c *HisBlockInfo) bool { - if b == nil || c == nil { - return b == c - } - if b.Number != c.Number { - return false - } - if b.Hash != c.Hash { - return false - } - if b.TD != c.TD { - return false - } - if !bytes.Equal(b.ConsensusData, c.ConsensusData) { - return false - } - return true -} - -type HisSegment struct { - Index uint64 `json:"index"` // segment index number - StartAtBlock HisBlockInfo `json:"start_at_block"` // target segment start from here - FinalityAtBlock HisBlockInfo `json:"finality_at_block"` // the StartAtBlock finality's block - // TODO(0xbundler): if need add more finality evidence? like signature? +type HistorySegment struct { + Index uint64 `json:"index"` // segment index number + ReGenesisNumber uint64 `json:"re_genesis_number"` // new history segment start at a finality block number, called ReGenesisNumber + ReGenesisHash common.Hash `json:"re_genesis_hash"` // new history segment start at a finality block hash, called ReGenesisHash + TD uint64 `json:"td"` // the ReGenesisBlock's TD + ConsensusData []byte `json:"consensus_data,omitempty"` // the ReGenesisBlock's consensus data } -func (s *HisSegment) String() string { - return fmt.Sprintf("[Index: %v, StartAt: %v, FinalityAt: %v]", s.Index, s.StartAtBlock, s.FinalityAtBlock) +func (s *HistorySegment) String() string { + return fmt.Sprintf("[Index: %v, ReGenesisNumber: %v, ReGenesisHash: %v, TD: %v]", s.Index, s.ReGenesisNumber, s.ReGenesisNumber, s.TD) } -func (s *HisSegment) MatchBlock(h common.Hash, n uint64) bool { - if s.StartAtBlock.Number == n && s.StartAtBlock.Hash == h { +func (s *HistorySegment) MatchBlock(h common.Hash, n uint64) bool { + if s.ReGenesisNumber == n && s.ReGenesisHash == h { return true } return false } -func (s *HisSegment) Equals(compared *HisSegment) bool { +func (s *HistorySegment) Equals(compared *HistorySegment) bool { if s == nil || compared == nil { return s == compared } if s.Index != compared.Index { return false } - if !s.StartAtBlock.Equals(&compared.StartAtBlock) { + if !s.MatchBlock(compared.ReGenesisHash, compared.ReGenesisNumber) { return false } - if !s.FinalityAtBlock.Equals(&compared.FinalityAtBlock) { + if s.TD != compared.TD { + return false + } + if !bytes.Equal(s.ConsensusData, compared.ConsensusData) { return false } return true @@ -166,7 +63,7 @@ type HistorySegmentConfig struct { Genesis common.Hash // specific chain genesis, it may use hard-code config } -func (cfg *HistorySegmentConfig) LoadCustomSegments() ([]HisSegment, error) { +func (cfg *HistorySegmentConfig) LoadCustomSegments() ([]HistorySegment, error) { if _, err := os.Stat(cfg.CustomPath); err != nil { return nil, err } @@ -174,7 +71,7 @@ func (cfg *HistorySegmentConfig) LoadCustomSegments() ([]HisSegment, error) { if err != nil { return nil, err } - var ret []HisSegment + var ret []HistorySegment if err = json.Unmarshal(enc, &ret); err != nil { return nil, err } @@ -182,7 +79,7 @@ func (cfg *HistorySegmentConfig) LoadCustomSegments() ([]HisSegment, error) { } type HistorySegmentManager struct { - segments []HisSegment + segments []HistorySegment cfg *HistorySegmentConfig } @@ -193,18 +90,18 @@ func NewHistorySegmentManager(cfg *HistorySegmentConfig) (*HistorySegmentManager // if genesis is one of the hard code history segment, just ignore input custom file var ( - segments []HisSegment + segments []HistorySegment err error ) switch cfg.Genesis { case BSCGenesisHash: segments = historySegmentsInBSCMainnet - // TODO(0xbundler): temporary got testing - //case ChapelGenesisHash: - // segments = historySegmentsInBSCChapel - //case RialtoGenesisHash: - // segments = historySegmentsInBSCRialto - default: + case ChapelGenesisHash: + segments = historySegmentsInBSCChapel + } + + // try load from config files + if len(segments) == 0 { segments, err = cfg.LoadCustomSegments() if err != nil { return nil, err @@ -219,24 +116,21 @@ func NewHistorySegmentManager(cfg *HistorySegmentConfig) (*HistorySegmentManager }, nil } -func ValidateHisSegments(genesis common.Hash, segments []HisSegment) error { +func ValidateHisSegments(genesis common.Hash, segments []HistorySegment) error { if len(segments) == 0 { return errors.New("history segment length cannot be 0") } - expectSeg0 := HisSegment{ - Index: 0, - StartAtBlock: HisBlockInfo{ - Number: 0, - Hash: genesis, - }, + expectSeg0 := HistorySegment{ + Index: 0, + ReGenesisNumber: 0, + ReGenesisHash: genesis, } if !segments[0].Equals(&expectSeg0) { return fmt.Errorf("wrong segement0 start block, it must be genesis, expect: %v, actual: %v", expectSeg0, segments[0]) } for i := 1; i < len(segments); i++ { if segments[i].Index != uint64(i) || - segments[i].StartAtBlock.Number <= segments[i-1].StartAtBlock.Number || - segments[i].StartAtBlock.Number+2 > segments[i].FinalityAtBlock.Number { + segments[i].ReGenesisNumber <= segments[i-1].ReGenesisNumber { return fmt.Errorf("wrong segement, index: %v, segment: %v", i, segments[i]) } } @@ -245,16 +139,16 @@ func ValidateHisSegments(genesis common.Hash, segments []HisSegment) error { } // HisSegments return all history segments -func (m *HistorySegmentManager) HisSegments() []HisSegment { +func (m *HistorySegmentManager) HisSegments() []HistorySegment { return m.segments } // CurSegment return which segment include this block -func (m *HistorySegmentManager) CurSegment(num uint64) HisSegment { +func (m *HistorySegmentManager) CurSegment(num uint64) HistorySegment { segments := m.HisSegments() i := len(segments) - 1 for i >= 0 { - if segments[i].StartAtBlock.Number <= num { + if segments[i].ReGenesisNumber <= num { break } i-- @@ -264,22 +158,22 @@ func (m *HistorySegmentManager) CurSegment(num uint64) HisSegment { // LastSegment return the current's last segment, because the latest 2 segments is available, // so user could keep current & prev segment -func (m *HistorySegmentManager) LastSegment(cur HisSegment) (HisSegment, bool) { +func (m *HistorySegmentManager) LastSegment(cur HistorySegment) (HistorySegment, bool) { segments := m.HisSegments() if cur.Index == 0 || cur.Index >= uint64(len(segments)) { - return HisSegment{}, false + return HistorySegment{}, false } return segments[cur.Index-1], true } // LastSegmentByNumber return the current's last segment -func (m *HistorySegmentManager) LastSegmentByNumber(num uint64) (HisSegment, bool) { +func (m *HistorySegmentManager) LastSegmentByNumber(num uint64) (HistorySegment, bool) { cur := m.CurSegment(num) return m.LastSegment(cur) } -func unmarshalHisSegments(enc string) []HisSegment { - var ret []HisSegment +func unmarshalHisSegments(enc string) []HistorySegment { + var ret []HistorySegment err := json.Unmarshal([]byte(enc), &ret) if err != nil { panic(err) diff --git a/params/history_segment_test.go b/params/history_segment_test.go index b3fe5d621f..ac14783587 100644 --- a/params/history_segment_test.go +++ b/params/history_segment_test.go @@ -10,35 +10,21 @@ import ( ) var ( - historySegmentsInTest = []HisSegment{ + historySegmentsInTest = []HistorySegment{ { - Index: 0, - StartAtBlock: HisBlockInfo{ - Number: 0, - Hash: common.Hash{}, - }, + Index: 0, + ReGenesisNumber: 0, + ReGenesisHash: common.Hash{}, }, { - Index: 1, - StartAtBlock: HisBlockInfo{ - Number: BoundStartBlock, - Hash: common.HexToHash("0xdb8a505f19ef04cb21ae79e3cb641963ffc44f3666e6fde499be55a72b6c7865"), - }, - FinalityAtBlock: HisBlockInfo{ - Number: 31268532, - Hash: common.HexToHash("0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7"), - }, + Index: 1, + ReGenesisNumber: BoundStartBlock, + ReGenesisHash: common.HexToHash("0xdb8a505f19ef04cb21ae79e3cb641963ffc44f3666e6fde499be55a72b6c7865"), }, { - Index: 2, - StartAtBlock: HisBlockInfo{ - Number: 33860530, - Hash: common.HexToHash("0xbf6d408bce0d531c41b00410e1c567e46b359db6e14d842cd8c8325039dff498"), - }, - FinalityAtBlock: HisBlockInfo{ - Number: 33860532, - Hash: common.HexToHash("0xb22bf5eb6fe8ed39894d32b148fdedd91bd11497e7744e6c84c6b104aa577a15"), - }, + Index: 2, + ReGenesisNumber: 33860530, + ReGenesisHash: common.HexToHash("0xbf6d408bce0d531c41b00410e1c567e46b359db6e14d842cd8c8325039dff498"), }, } testGenesis = common.HexToHash("0x50b168d3ba07cc77c13a5469b9a1aad8752ba725ff989b76bc7df89dc936e866") @@ -76,74 +62,74 @@ func TestNewHisSegmentManager_HardCode(t *testing.T) { func TestHisSegmentManager_Validate(t *testing.T) { tests := []struct { genesis common.Hash - segments []HisSegment + segments []HistorySegment err bool }{ { genesis: testGenesis, - segments: []HisSegment{ + segments: []HistorySegment{ { - Index: 1, - StartAtBlock: HisBlockInfo{ - Number: 1, - Hash: common.Hash{}, - }, + Index: 1, + ReGenesisNumber: 1, + ReGenesisHash: common.Hash{}, }, }, err: true, }, { genesis: testGenesis, - segments: []HisSegment{ + segments: []HistorySegment{ + { + Index: 0, + ReGenesisNumber: 0, + ReGenesisHash: testGenesis, + }, + }, + }, + { + genesis: testGenesis, + segments: []HistorySegment{ { - Index: 0, - StartAtBlock: HisBlockInfo{ - Number: 0, - Hash: testGenesis, - }, + Index: 0, + ReGenesisNumber: 0, + ReGenesisHash: testGenesis, + }, + { + Index: 1, + ReGenesisNumber: 0, + ReGenesisHash: common.HexToHash("0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7"), }, }, + err: true, }, { genesis: testGenesis, - segments: []HisSegment{ + segments: []HistorySegment{ { - Index: 0, - StartAtBlock: HisBlockInfo{ - Number: 0, - Hash: testGenesis, - }, + Index: 0, + ReGenesisNumber: 0, + ReGenesisHash: testGenesis, }, { - Index: 1, - StartAtBlock: HisBlockInfo{ - Number: 1, - Hash: common.HexToHash("0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7"), - }, + Index: 0, + ReGenesisNumber: 1, + ReGenesisHash: common.HexToHash("0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7"), }, }, err: true, }, { genesis: testGenesis, - segments: []HisSegment{ + segments: []HistorySegment{ { - Index: 0, - StartAtBlock: HisBlockInfo{ - Number: 0, - Hash: testGenesis, - }, + Index: 0, + ReGenesisNumber: 0, + ReGenesisHash: testGenesis, }, { - Index: 1, - StartAtBlock: HisBlockInfo{ - Number: 1, - Hash: common.HexToHash("0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7"), - }, - FinalityAtBlock: HisBlockInfo{ - Number: 3, - Hash: common.HexToHash("0xb22bf5eb6fe8ed39894d32b148fdedd91bd11497e7744e6c84c6b104aa577a15"), - }, + Index: 1, + ReGenesisNumber: 1, + ReGenesisHash: common.HexToHash("0xaa1b4e4d251289d21da95e66cf9b57f641b2dbc8031a2bb145ae58ee7ade03e7"), }, }, }, @@ -179,7 +165,7 @@ func TestIndexSegment(t *testing.T) { assert.Equal(t, segments[2], hsm.CurSegment(BoundStartBlock+HistorySegmentLength*2)) var ( - prev HisSegment + prev HistorySegment ok bool ) _, ok = hsm.LastSegment(segments[0]) @@ -190,7 +176,7 @@ func TestIndexSegment(t *testing.T) { prev, ok = hsm.LastSegment(segments[2]) assert.Equal(t, true, ok) assert.Equal(t, segments[1], prev) - _, ok = hsm.LastSegment(HisSegment{ + _, ok = hsm.LastSegment(HistorySegment{ Index: uint64(len(segments)), }) assert.Equal(t, false, ok) From dbe87c149d38d40aaa1c6445f3bd568be2d3e799 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Fri, 1 Dec 2023 00:13:07 +0800 Subject: [PATCH 14/22] sync: make history segment more flexible in snap sync; --- cmd/geth/chaincmd.go | 20 ++++++++--- consensus/consensus.go | 2 +- consensus/parlia/parlia.go | 59 +++++++++++++++++++++++-------- consensus/parlia/snapshot.go | 2 ++ core/blockchain.go | 6 ++-- core/blockchain_reader.go | 11 ++++-- core/genesis.go | 3 +- core/rawdb/history_segment.go | 33 +++++++++++++++++- core/vote/vote_pool_test.go | 4 +-- eth/backend.go | 20 +++++++---- eth/downloader/downloader.go | 52 +++++++++++++-------------- eth/sync_test.go | 36 +++++++++++++++---- params/history_segment.go | 64 +++++++++++++++++++++++++--------- params/history_segment_test.go | 8 ++--- 14 files changed, 228 insertions(+), 92 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index bddd15f892..4a327537fd 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -719,11 +719,15 @@ func exportSegment(ctx *cli.Context) error { defer db.Close() genesisHash := rawdb.ReadCanonicalHash(db, 0) + td := rawdb.ReadTd(db, genesisHash, 0) chainConfig, engine, headerChain, err := simpleHeaderChain(db, genesisHash) if err != nil { return err } latest := headerChain.CurrentHeader() + if _, ok := engine.(consensus.PoSA); !ok { + return errors.New("current chain is not POSA consensus, cannot generate history segment") + } if !chainConfig.IsLuban(latest.Number) { return errors.New("current chain is not enable Luban hard fork, cannot generate history segment") } @@ -763,10 +767,15 @@ func exportSegment(ctx *cli.Context) error { Index: 0, ReGenesisNumber: 0, ReGenesisHash: genesisHash, + TD: td.Uint64(), }, } // try find finalized block in every segment boundary for num := boundStartBlock; num <= target; num += historySegmentLength { + // align the segment start at parlia's epoch + if chainConfig.Parlia != nil { + num -= num % chainConfig.Parlia.Epoch + } var fs, ft *types.Header for next := num + 1; next <= target; next++ { fs = headerChain.GetHeaderByNumber(next) @@ -799,11 +808,11 @@ func exportSegment(ctx *cli.Context) error { if err != nil { return err } - segment.ConsensusData = enc + segment.ConsensusData = hexutil.Encode(enc) } segments = append(segments, segment) } - if err = params.ValidateHisSegments(genesisHash, segments); err != nil { + if err = params.ValidateHisSegments(params.NewHistoryBlock(0, genesisHash, td.Uint64()), segments); err != nil { return err } output, err := json.MarshalIndent(segments, "", " ") @@ -813,7 +822,7 @@ func exportSegment(ctx *cli.Context) error { log.Info("Generate History Segment done", "count", len(segments), "elapsed", common.PrettyDuration(time.Since(start))) out := ctx.String(utils.HistorySegOutputFlag.Name) - outFile, err := os.OpenFile(out, os.O_CREATE|os.O_RDWR, 0644) + outFile, err := os.OpenFile(out, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0644) if err != nil { return err } @@ -834,13 +843,14 @@ func pruneHistorySegments(ctx *cli.Context) error { defer db.Close() genesisHash := rawdb.ReadCanonicalHash(db, 0) + td := rawdb.ReadTd(db, genesisHash, 0) _, _, headerChain, err := simpleHeaderChain(db, genesisHash) if err != nil { return err } cfg := ¶ms.HistorySegmentConfig{ CustomPath: "", - Genesis: genesisHash, + Genesis: params.NewHistoryBlock(0, genesisHash, td.Uint64()), } if ctx.IsSet(utils.HistorySegCustomFlag.Name) { cfg.CustomPath = ctx.String(utils.HistorySegCustomFlag.Name) @@ -864,7 +874,7 @@ func pruneHistorySegments(ctx *cli.Context) error { } pruneTail := lastSegment.ReGenesisNumber - log.Info("The older history will be pruned", "lastSegment", &lastSegment, "curSegment", &curSegment, "pruneTail", pruneTail) + log.Info("The older history will be pruned", "lastSegment", lastSegment, "curSegment", curSegment, "pruneTail", pruneTail) if err = rawdb.PruneTxLookupToTail(db, pruneTail); err != nil { return err } diff --git a/consensus/consensus.go b/consensus/consensus.go index 8beecc6175..5cbeaab42b 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -155,5 +155,5 @@ type PoSA interface { VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool GetConsensusData(chain ChainHeaderReader, header *types.Header) ([]byte, error) - SetupLastSegment(segment *params.HistorySegment) + SetupHistorySegment(hsm *params.HistorySegmentManager) } diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 8185852bac..dfd56ee718 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -11,6 +11,7 @@ import ( "math" "math/big" "math/rand" + "runtime/debug" "sort" "strings" "sync" @@ -233,7 +234,7 @@ type Parlia struct { fakeDiff bool // Skip difficulty verifications // history segment, it provides history segment's consensus data to prevent generate snap from older headers - lastSegment *params.HistorySegment + hsm *params.HistorySegmentManager } // New creates a Parlia consensus engine. @@ -290,8 +291,8 @@ func New( return c } -func (p *Parlia) SetupLastSegment(segment *params.HistorySegment) { - p.lastSegment = segment +func (p *Parlia) SetupHistorySegment(hsm *params.HistorySegmentManager) { + p.hsm = hsm } func (p *Parlia) IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) { @@ -417,6 +418,7 @@ func (p *Parlia) getParent(chain consensus.ChainHeaderReader, header *types.Head } if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { + log.Info("cannot find ancestor, FindAncientHeader", "number", number, "stack", string(debug.Stack())) return nil, consensus.ErrUnknownAncestor } return parent, nil @@ -539,6 +541,7 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise signersBytes := getValidatorBytesFromHeader(header, p.chainConfig, p.config) if !isEpoch && len(signersBytes) != 0 { + log.Error("validate header err", "number", header.Number, "hash", header.Hash(), "chainconfig", p.chainConfig, "config", p.config, "bytes", len(signersBytes)) return errExtraValidators } if isEpoch && len(signersBytes) == 0 { @@ -686,17 +689,9 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash } } // check history consensus data, load snapshot - if p.lastSegment != nil && p.lastSegment.MatchBlock(hash, number) { - var tmp Snapshot - err := json.Unmarshal(p.lastSegment.ConsensusData, &tmp) - if err == nil { - tmp.config = p.config - tmp.sigCache = p.signatures - tmp.ethAPI = p.ethAPI - snap = &tmp - break - } - log.Error("Try load snapshot from history segment, wrong encode", "number", number, "hash", hash, "err", err) + if s, ok := p.findSnapFromHistorySegment(hash, number); ok { + snap = s + break } // If we're at the genesis, snapshot the initial state. Alternatively if we have @@ -732,6 +727,7 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash // If we have explicit parents, pick from there (enforced) header = parents[len(parents)-1] if header.Hash() != hash || header.Number.Uint64() != number { + log.Info("cannot find ancestor, FindAncientHeader", "number", number, "stack", string(debug.Stack())) return nil, consensus.ErrUnknownAncestor } parents = parents[:len(parents)-1] @@ -739,6 +735,7 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash // No explicit parents (or no more left), reach out to the database header = chain.GetHeader(hash, number) if header == nil { + log.Info("cannot find ancestor, FindAncientHeader", "number", number, "stack", string(debug.Stack())) return nil, consensus.ErrUnknownAncestor } } @@ -772,6 +769,36 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash return snap, err } +func (p *Parlia) findSnapFromHistorySegment(hash common.Hash, number uint64) (*Snapshot, bool) { + if p.hsm == nil { + return nil, false + } + segment := p.hsm.CurSegment(number + 1) + if segment.ReGenesisNumber != number+1 { + return nil, false + } + var tmp Snapshot + enc, err := hexutil.Decode(segment.ConsensusData) + if err != nil { + log.Warn("Try load snapshot from history segment, wrong hex", "number", number, "hash", hash, "err", err) + return nil, false + } + err = json.Unmarshal(enc, &tmp) + if err != nil { + log.Warn("Try load snapshot from history segment, wrong encode", "number", number, "hash", hash, "err", err) + return nil, false + } + if tmp.Number != number || tmp.Hash != hash { + return nil, false + } + + tmp.config = p.config + tmp.sigCache = p.signatures + tmp.ethAPI = p.ethAPI + log.Info("found history segment snapshot", "number", number, "hash", hash, "segment", segment) + return &tmp, true +} + // VerifyUncles implements consensus.Engine, always returning an error for any // uncles as this consensus mechanism doesn't permit uncles. func (p *Parlia) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { @@ -973,6 +1000,7 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header // Ensure the timestamp has the correct delay parent := chain.GetHeader(header.ParentHash, number-1) if parent == nil { + log.Info("cannot find ancestor, FindAncientHeader", "number", number, "stack", string(debug.Stack())) return consensus.ErrUnknownAncestor } header.Time = p.blockTimeForRamanujanFork(snap, header, parent) @@ -1533,9 +1561,10 @@ func (p *Parlia) Close() error { return nil } +// GetConsensusData load the header's last snapshot for history segment func (p *Parlia) GetConsensusData(chain consensus.ChainHeaderReader, header *types.Header) ([]byte, error) { number := header.Number.Uint64() - snap, err := p.snapshot(chain, number, header.Hash(), nil) + snap, err := p.snapshot(chain, number-1, header.ParentHash, nil) if err != nil { return nil, err } diff --git a/consensus/parlia/snapshot.go b/consensus/parlia/snapshot.go index ddfb1811fc..0957b9eb55 100644 --- a/consensus/parlia/snapshot.go +++ b/consensus/parlia/snapshot.go @@ -22,6 +22,7 @@ import ( "encoding/json" "errors" "fmt" + "runtime/debug" "sort" lru "github.com/hashicorp/golang-lru" @@ -271,6 +272,7 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea if number > 0 && number%s.config.Epoch == uint64(len(snap.Validators)/2) { checkpointHeader := FindAncientHeader(header, uint64(len(snap.Validators)/2), chain, parents) if checkpointHeader == nil { + log.Info("cannot find ancestor, FindAncientHeader", "number", number, "stack", string(debug.Stack())) return nil, consensus.ErrUnknownAncestor } diff --git a/core/blockchain.go b/core/blockchain.go index 9ab44ec719..f36f7d398e 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -299,7 +299,7 @@ type BlockChain struct { pipeCommit bool // history segment - lastSegment *params.HistorySegment + hsm *params.HistorySegmentManager // monitor doubleSignMonitor *monitor.DoubleSignMonitor @@ -560,8 +560,8 @@ func (bc *BlockChain) GetVMConfig() *vm.Config { return &bc.vmConfig } -func (bc *BlockChain) SetupHistorySegment(lastSegment *params.HistorySegment) { - bc.lastSegment = lastSegment +func (bc *BlockChain) SetupHistorySegment(hsm *params.HistorySegmentManager) { + bc.hsm = hsm } func (bc *BlockChain) cacheReceipts(hash common.Hash, receipts types.Receipts, block *types.Block) { diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index a59397ffcb..b3363a8982 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -449,8 +449,15 @@ func (bc *BlockChain) SubscribeFinalizedHeaderEvent(ch chan<- FinalizedHeaderEve return bc.scope.Track(bc.finalizedHeaderFeed.Subscribe(ch)) } -func (bc *BlockChain) LastHistorySegment() *params.HistorySegment { - return bc.lastSegment +func (bc *BlockChain) LastHistorySegment(num uint64) *params.HistorySegment { + if bc.hsm == nil { + return nil + } + segment, ok := bc.hsm.LastSegmentByNumber(num) + if !ok { + return nil + } + return segment } func (bc *BlockChain) WriteCanonicalHeaders(headers []*types.Header, tds []uint64) error { diff --git a/core/genesis.go b/core/genesis.go index 47f316c258..dd73d53b56 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -328,7 +328,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen log.Info("Writing default BSC mainnet genesis block") genesis = DefaultBSCGenesisBlock() } else { - log.Info("Writing custom genesis block") + log.Info("Writing custom genesis block", "config", genesis.Config) } block, err := genesis.Commit(db, triedb) if err != nil { @@ -421,6 +421,7 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, } storedcfg := rawdb.ReadChainConfig(db, stored) if storedcfg != nil { + log.Info("found chain config", "hash", stored, "cfg", storedcfg) return storedcfg, stored, nil } } diff --git a/core/rawdb/history_segment.go b/core/rawdb/history_segment.go index 616c330e84..92d5399662 100644 --- a/core/rawdb/history_segment.go +++ b/core/rawdb/history_segment.go @@ -2,6 +2,7 @@ package rawdb import ( "bytes" + "errors" "fmt" "math/big" "time" @@ -13,6 +14,10 @@ import ( "github.com/ethereum/go-ethereum/log" ) +var ( + rangeCompactionThreshold = 100000 +) + // PruneTxLookupToTail it will iterator tx look up and delete to tail func PruneTxLookupToTail(db ethdb.KeyValueStore, tail uint64) error { indexTail := ReadTxIndexTail(db) @@ -24,6 +29,7 @@ func PruneTxLookupToTail(db ethdb.KeyValueStore, tail uint64) error { start = time.Now() logged = time.Now() txlookups stat + count = 0 batch = db.NewBatch() iter = db.NewIterator(txLookupPrefix, nil) @@ -53,17 +59,42 @@ func PruneTxLookupToTail(db ethdb.KeyValueStore, tail uint64) error { log.Info("PruneTxLookupToTail", "count", txlookups.Count(), "size", txlookups.Size(), "elapsed", common.PrettyDuration(time.Since(start))) logged = time.Now() } + count++ } WriteTxIndexTail(batch, tail) if err := batch.Write(); err != nil { return err } log.Info("PruneTxLookupToTail finish", "count", txlookups.Count(), "size", txlookups.Size(), "elapsed", common.PrettyDuration(time.Since(start))) + + // Start compactions, will remove the deleted data from the disk immediately. + // Note for small pruning, the compaction is skipped. + if count >= rangeCompactionThreshold { + cstart := time.Now() + for b := 0x00; b <= 0xf0; b += 0x10 { + var ( + start = []byte{byte(b)} + end = []byte{byte(b + 0x10)} + ) + if b == 0xf0 { + end = nil + } + log.Info("Compacting database", "range", fmt.Sprintf("%#x-%#x", start, end), "elapsed", common.PrettyDuration(time.Since(cstart))) + if err := db.Compact(start, end); err != nil { + log.Error("Database compaction failed", "error", err) + return err + } + } + log.Info("Database compaction finished", "elapsed", common.PrettyDuration(time.Since(cstart))) + } return nil } -func AvailableHistorySegment(db ethdb.Reader, segments ...params.HistorySegment) error { +func AvailableHistorySegment(db ethdb.Reader, segments ...*params.HistorySegment) error { for _, s := range segments { + if s == nil { + return errors.New("found nil segment") + } hash := ReadCanonicalHash(db, s.ReGenesisNumber) if hash != s.ReGenesisHash { return fmt.Errorf("cannot find segment StartAtBlock, seg: %v", s) diff --git a/core/vote/vote_pool_test.go b/core/vote/vote_pool_test.go index 69695a0048..4f014889f3 100644 --- a/core/vote/vote_pool_test.go +++ b/core/vote/vote_pool_test.go @@ -114,10 +114,10 @@ func (m *mockInvalidPOSA) GetConsensusData(chain consensus.ChainHeaderReader, he return nil, nil } -func (m *mockPOSA) SetupLastSegment(segment *params.HistorySegment) { +func (m *mockPOSA) SetupHistorySegment(hsm *params.HistorySegmentManager) { } -func (m *mockInvalidPOSA) SetupLastSegment(segment *params.HistorySegment) { +func (m *mockInvalidPOSA) SetupHistorySegment(hsm *params.HistorySegmentManager) { } func (pool *VotePool) verifyStructureSizeOfVotePool(receivedVotes, curVotes, futureVotes, curVotesPq, futureVotesPq int) bool { diff --git a/eth/backend.go b/eth/backend.go index 7337a91c87..bae24fe778 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -210,14 +210,18 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if err != nil { return nil, err } - var lastSegment *params.HistorySegment + var ( + hsm *params.HistorySegmentManager + lastSegment *params.HistorySegment + ) if config.HistorySegmentEnable { - _, lastSegment, err = GetHistorySegmentAndLastSegment(chainDb, genesisHash, config.HistorySegmentCustomFile) + hsm, lastSegment, err = GetHistorySegmentAndLastSegment(chainDb, genesisHash, config.HistorySegmentCustomFile) if err != nil { return nil, err } if p, ok := eth.engine.(consensus.PoSA); ok { - p.SetupLastSegment(lastSegment) + log.Info("setup consensus engine history segment", "lastSegment", lastSegment) + p.SetupHistorySegment(hsm) } } @@ -278,11 +282,12 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } bcOps = append(bcOps, func(bc *core.BlockChain) (*core.BlockChain, error) { // if enable history segment, try prune ancient data when restart - if config.HistorySegmentEnable && lastSegment != nil { + if config.HistorySegmentEnable { if err = truncateAncientTail(chainDb, lastSegment); err != nil { return nil, err } - bc.SetupHistorySegment(lastSegment) + bc.SetupHistorySegment(hsm) + log.Info("setup blockchain history segment", "lastSegment", lastSegment) } return bc, nil }) @@ -403,9 +408,10 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } func GetHistorySegmentAndLastSegment(db ethdb.Database, genesisHash common.Hash, CustomPath string) (*params.HistorySegmentManager, *params.HistorySegment, error) { + td := rawdb.ReadTd(db, genesisHash, 0) hsm, err := params.NewHistorySegmentManager(¶ms.HistorySegmentConfig{ CustomPath: CustomPath, - Genesis: genesisHash, + Genesis: params.NewHistoryBlock(0, genesisHash, td.Uint64()), }) if err != nil { return nil, nil, err @@ -423,7 +429,7 @@ func GetHistorySegmentAndLastSegment(db ethdb.Database, genesisHash common.Hash, if err = rawdb.AvailableHistorySegment(db, lastSegment); err != nil { return nil, nil, err } - return hsm, &lastSegment, nil + return hsm, lastSegment, nil } func truncateAncientTail(db ethdb.Database, lastSegment *params.HistorySegment) error { diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 7519f5d129..cf81369419 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -150,6 +150,9 @@ type Downloader struct { syncStartBlock uint64 // Head snap block when Geth was started syncStartTime time.Time // Time instance when chain sync started syncLogTime time.Time // Time instance when status was last reported + + // history segment feature + lastSegment *params.HistorySegment } // LightChain encapsulates functions required to synchronise a light chain. @@ -209,7 +212,7 @@ type BlockChain interface { TrieDB() *trie.Database // LastHistorySegment get last history segment - LastHistorySegment() *params.HistorySegment + LastHistorySegment(num uint64) *params.HistorySegment // WriteHeaders just write header into db, it an unsafe interface, just for history segment WriteCanonicalHeaders([]*types.Header, []uint64) error @@ -493,19 +496,18 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * // If the remote peer is lagging behind, no need to sync with it, drop the peer. remoteHeight := remoteHeader.Number.Uint64() + // if enable history segment, override lastSegment + lastSegment := d.blockchain.LastHistorySegment(remoteHeight) + if lastSegment != nil { + d.lastSegment = lastSegment + } + var localHeight uint64 switch mode { case FullSync: localHeight = d.blockchain.CurrentBlock().Number.Uint64() case SnapSync: localHeight = d.blockchain.CurrentSnapBlock().Number.Uint64() - // if enable history segment, ensure local height >= lastSegment height - if d.blockchain.LastHistorySegment() != nil { - lastSegment := d.blockchain.LastHistorySegment() - if localHeight < lastSegment.ReGenesisNumber { - localHeight = lastSegment.ReGenesisNumber - } - } default: localHeight = d.lightchain.CurrentHeader().Number.Uint64() } @@ -514,6 +516,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * if err != nil { return err } + log.Info("sync from peer", "local", localHeight, "remote", remoteHeight, "origin", origin, "peer", p.peer) if localHeight >= remoteHeight { // if remoteHeader does not exist in local chain, will move on to insert it as a side chain. @@ -832,6 +835,11 @@ func (d *Downloader) findAncestor(p *peerConnection, localHeight uint64, remoteH } } + // try to find ancestor from history segment + if localHeight == 0 && mode == SnapSync && d.lastSegment != nil { + return d.findAncestorFromHistorySegment(p, remoteHeight) + } + ancestor, err := d.findAncestorSpanSearch(p, mode, remoteHeight, localHeight, floor) if err == nil { return ancestor, nil @@ -848,13 +856,6 @@ func (d *Downloader) findAncestor(p *peerConnection, localHeight uint64, remoteH if err != nil { return 0, err } - - if ancestor == 0 && mode == SnapSync { - ancestor, err = d.findAncestorFromHistorySegment(p, remoteHeight) - if err != nil { - return 0, err - } - } return ancestor, nil } @@ -951,11 +952,6 @@ func (d *Downloader) findAncestorBinarySearch(p *peerConnection, mode SyncMode, known = d.blockchain.HasBlock(h, n) case SnapSync: known = d.blockchain.HasFastBlock(h, n) - // if enable history segment, check in last segment - if d.blockchain.LastHistorySegment() != nil && !known { - lastSegment := d.blockchain.LastHistorySegment() - known = lastSegment.MatchBlock(h, n) - } default: known = d.lightchain.HasHeader(h, n) } @@ -1756,12 +1752,11 @@ func (d *Downloader) reportSnapSyncProgress(force bool) { } func (d *Downloader) findAncestorFromHistorySegment(p *peerConnection, remoteHeight uint64) (uint64, error) { - lastSegment := d.blockchain.LastHistorySegment() - if lastSegment == nil { + if d.lastSegment == nil || d.lastSegment.ReGenesisNumber == 0 { return 0, nil } - expect := lastSegment.ReGenesisNumber + expect := d.lastSegment.ReGenesisNumber if expect > remoteHeight { return 0, nil } @@ -1777,10 +1772,13 @@ func (d *Downloader) findAncestorFromHistorySegment(p *peerConnection, remoteHei // check if it matches local last segment h := hashes[0] n := headers[0].Number.Uint64() - if lastSegment.MatchBlock(h, n) && headers[0].Hash() == h { - // just write header, td, because it's snap sync, just sync history is enough - if err = d.blockchain.WriteCanonicalHeaders(headers, []uint64{lastSegment.TD}); err != nil { - return 0, err + if d.lastSegment.MatchBlock(h, n) { + if !d.blockchain.HasHeader(h, n) { + // just write header, td, because it's snap sync, just sync history is enough + if err = d.blockchain.WriteCanonicalHeaders(headers, []uint64{d.lastSegment.TD}); err != nil { + return 0, err + } + log.Info("sync history segment header to local", "number", n, "hash", h, "segment", d.lastSegment) } return n, nil } diff --git a/eth/sync_test.go b/eth/sync_test.go index e32249e3a8..39905418f7 100644 --- a/eth/sync_test.go +++ b/eth/sync_test.go @@ -112,13 +112,35 @@ func TestSnapSyncWithHistorySegment(t *testing.T) { // Create an empty handler and ensure it's in snap sync mode empty := newTestHandlerWithBlocks(0, func(bc *core.BlockChain) (*core.BlockChain, error) { - header := full.chain.GetHeaderByNumber(500) - bc.SetupHistorySegment(¶ms.HistorySegment{ - Index: 1, - ReGenesisNumber: header.Number.Uint64(), - ReGenesisHash: header.Hash(), - TD: full.chain.GetTd(header.Hash(), header.Number.Uint64()).Uint64(), + h0 := full.chain.GetHeaderByNumber(0) + h1 := full.chain.GetHeaderByNumber(500) + h2 := full.chain.GetHeaderByNumber(1000) + h0Hash := h0.Hash() + h0TD := full.chain.GetTd(h0Hash, h0.Number.Uint64()).Uint64() + hsm, err := params.NewHistorySegmentManagerWithSegments(params.NewHistoryBlock(h0.Number.Uint64(), h0Hash, h0TD), []params.HistorySegment{ + { + Index: 0, + ReGenesisNumber: h0.Number.Uint64(), + ReGenesisHash: h0Hash, + TD: h0TD, + }, + { + Index: 1, + ReGenesisNumber: h1.Number.Uint64(), + ReGenesisHash: h1.Hash(), + TD: full.chain.GetTd(h1.Hash(), h1.Number.Uint64()).Uint64(), + }, + { + Index: 2, + ReGenesisNumber: h2.Number.Uint64(), + ReGenesisHash: h2.Hash(), + TD: full.chain.GetTd(h2.Hash(), h2.Number.Uint64()).Uint64(), + }, }) + if err != nil { + t.Fatalf("cannot init HistorySegmentManager, err: %v", err) + } + bc.SetupHistorySegment(hsm) return bc, nil }) if !empty.handler.snapSync.Load() { @@ -172,7 +194,7 @@ func TestSnapSyncWithHistorySegment(t *testing.T) { t.Fatalf("snap sync not disabled after successful synchronisation") } assert.Nil(t, empty.chain.GetHeaderByNumber(1), 1) - assert.Nil(t, empty.chain.GetHeaderByNumber(251), 251) + assert.Nil(t, empty.chain.GetHeaderByNumber(499), 499) assert.NotNil(t, empty.chain.GetHeaderByNumber(500), 500) assert.NotNil(t, empty.chain.GetHeaderByNumber(1024), 1024) } diff --git a/params/history_segment.go b/params/history_segment.go index 57a958aa3a..a317826cf9 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -1,17 +1,17 @@ package params import ( - "bytes" "encoding/json" "errors" "fmt" "os" + "strings" "github.com/ethereum/go-ethereum/common" ) const ( - BoundStartBlock uint64 = 31268530 // The starting block height of the first segment, was produced on Aug-29-2023 + BoundStartBlock uint64 = 31268600 // The starting block height of the first segment, was produced on Aug-29-2023 HistorySegmentLength uint64 = 2592000 // Assume 1 block for every 3 second, 2,592,000 blocks will be produced in 90 days. ) @@ -20,12 +20,26 @@ var ( historySegmentsInBSCChapel []HistorySegment ) +type HistoryBlock struct { + Number uint64 + hash common.Hash + TD uint64 +} + +func NewHistoryBlock(num uint64, hash common.Hash, td uint64) HistoryBlock { + return HistoryBlock{ + Number: num, + hash: hash, + TD: td, + } +} + type HistorySegment struct { Index uint64 `json:"index"` // segment index number ReGenesisNumber uint64 `json:"re_genesis_number"` // new history segment start at a finality block number, called ReGenesisNumber ReGenesisHash common.Hash `json:"re_genesis_hash"` // new history segment start at a finality block hash, called ReGenesisHash TD uint64 `json:"td"` // the ReGenesisBlock's TD - ConsensusData []byte `json:"consensus_data,omitempty"` // the ReGenesisBlock's consensus data + ConsensusData string `json:"consensus_data,omitempty"` // the ReGenesisBlock's consensus data } func (s *HistorySegment) String() string { @@ -52,15 +66,15 @@ func (s *HistorySegment) Equals(compared *HistorySegment) bool { if s.TD != compared.TD { return false } - if !bytes.Equal(s.ConsensusData, compared.ConsensusData) { + if !strings.EqualFold(s.ConsensusData, compared.ConsensusData) { return false } return true } type HistorySegmentConfig struct { - CustomPath string // custom HistorySegments file path, need read from the file - Genesis common.Hash // specific chain genesis, it may use hard-code config + CustomPath string // custom HistorySegments file path, need read from the file + Genesis HistoryBlock // specific chain genesis, it may use hard-code config } func (cfg *HistorySegmentConfig) LoadCustomSegments() ([]HistorySegment, error) { @@ -93,7 +107,7 @@ func NewHistorySegmentManager(cfg *HistorySegmentConfig) (*HistorySegmentManager segments []HistorySegment err error ) - switch cfg.Genesis { + switch cfg.Genesis.hash { case BSCGenesisHash: segments = historySegmentsInBSCMainnet case ChapelGenesisHash: @@ -104,7 +118,7 @@ func NewHistorySegmentManager(cfg *HistorySegmentConfig) (*HistorySegmentManager if len(segments) == 0 { segments, err = cfg.LoadCustomSegments() if err != nil { - return nil, err + return nil, fmt.Errorf("LoadCustomSegments err %v", err) } } if err = ValidateHisSegments(cfg.Genesis, segments); err != nil { @@ -116,14 +130,27 @@ func NewHistorySegmentManager(cfg *HistorySegmentConfig) (*HistorySegmentManager }, nil } -func ValidateHisSegments(genesis common.Hash, segments []HistorySegment) error { +func NewHistorySegmentManagerWithSegments(genesis HistoryBlock, segments []HistorySegment) (*HistorySegmentManager, error) { + if err := ValidateHisSegments(genesis, segments); err != nil { + return nil, err + } + return &HistorySegmentManager{ + segments: segments, + cfg: &HistorySegmentConfig{ + Genesis: genesis, + }, + }, nil +} + +func ValidateHisSegments(genesis HistoryBlock, segments []HistorySegment) error { if len(segments) == 0 { return errors.New("history segment length cannot be 0") } expectSeg0 := HistorySegment{ Index: 0, - ReGenesisNumber: 0, - ReGenesisHash: genesis, + ReGenesisNumber: genesis.Number, + ReGenesisHash: genesis.hash, + TD: genesis.TD, } if !segments[0].Equals(&expectSeg0) { return fmt.Errorf("wrong segement0 start block, it must be genesis, expect: %v, actual: %v", expectSeg0, segments[0]) @@ -144,7 +171,7 @@ func (m *HistorySegmentManager) HisSegments() []HistorySegment { } // CurSegment return which segment include this block -func (m *HistorySegmentManager) CurSegment(num uint64) HistorySegment { +func (m *HistorySegmentManager) CurSegment(num uint64) *HistorySegment { segments := m.HisSegments() i := len(segments) - 1 for i >= 0 { @@ -153,21 +180,24 @@ func (m *HistorySegmentManager) CurSegment(num uint64) HistorySegment { } i-- } - return segments[i] + return &segments[i] } // LastSegment return the current's last segment, because the latest 2 segments is available, // so user could keep current & prev segment -func (m *HistorySegmentManager) LastSegment(cur HistorySegment) (HistorySegment, bool) { +func (m *HistorySegmentManager) LastSegment(cur *HistorySegment) (*HistorySegment, bool) { + if cur == nil { + return nil, false + } segments := m.HisSegments() if cur.Index == 0 || cur.Index >= uint64(len(segments)) { - return HistorySegment{}, false + return nil, false } - return segments[cur.Index-1], true + return &segments[cur.Index-1], true } // LastSegmentByNumber return the current's last segment -func (m *HistorySegmentManager) LastSegmentByNumber(num uint64) (HistorySegment, bool) { +func (m *HistorySegmentManager) LastSegmentByNumber(num uint64) (*HistorySegment, bool) { cur := m.CurSegment(num) return m.LastSegment(cur) } diff --git a/params/history_segment_test.go b/params/history_segment_test.go index ac14783587..bddd16373c 100644 --- a/params/history_segment_test.go +++ b/params/history_segment_test.go @@ -37,19 +37,19 @@ func TestNewHisSegmentManager_HardCode(t *testing.T) { { cfg: &HistorySegmentConfig{ CustomPath: "", - Genesis: BSCGenesisHash, + Genesis: NewHistoryBlock(0, BSCGenesisHash, 0), }, }, { cfg: &HistorySegmentConfig{ CustomPath: "", - Genesis: ChapelGenesisHash, + Genesis: NewHistoryBlock(0, ChapelGenesisHash, 0), }, }, { cfg: &HistorySegmentConfig{ CustomPath: "", - Genesis: RialtoGenesisHash, + Genesis: NewHistoryBlock(0, RialtoGenesisHash, 0), }, }, } @@ -135,7 +135,7 @@ func TestHisSegmentManager_Validate(t *testing.T) { }, } for i, item := range tests { - err := ValidateHisSegments(item.genesis, item.segments) + err := ValidateHisSegments(NewHistoryBlock(0, item.genesis, 0), item.segments) if item.err { assert.Error(t, err, i) continue From ecdefc720cb92e8173668bbecbc20a9ac95ae983 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Thu, 7 Dec 2023 22:25:26 +0800 Subject: [PATCH 15/22] freezer: support reset ancient head+tail; --- consensus/parlia/parlia.go | 8 +-- consensus/parlia/snapshot.go | 2 - core/blockchain_reader.go | 4 ++ core/genesis.go | 3 +- core/rawdb/database.go | 4 ++ core/rawdb/freezer.go | 29 ++++++++++ core/rawdb/freezer_resettable.go | 7 +++ core/rawdb/freezer_table.go | 51 +++++++++++++++++ core/rawdb/freezer_table_test.go | 97 ++++++++++++++++++++++++++++++++ core/rawdb/prunedfreezer.go | 4 ++ core/rawdb/table.go | 4 ++ eth/backend.go | 5 +- eth/downloader/downloader.go | 16 +++++- ethdb/database.go | 3 + ethdb/remotedb/remotedb.go | 4 ++ params/history_segment.go | 2 +- params/history_segment_test.go | 10 ++-- 17 files changed, 230 insertions(+), 23 deletions(-) diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index dfd56ee718..97daf5f69c 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -11,7 +11,6 @@ import ( "math" "math/big" "math/rand" - "runtime/debug" "sort" "strings" "sync" @@ -418,7 +417,6 @@ func (p *Parlia) getParent(chain consensus.ChainHeaderReader, header *types.Head } if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { - log.Info("cannot find ancestor, FindAncientHeader", "number", number, "stack", string(debug.Stack())) return nil, consensus.ErrUnknownAncestor } return parent, nil @@ -541,7 +539,6 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise signersBytes := getValidatorBytesFromHeader(header, p.chainConfig, p.config) if !isEpoch && len(signersBytes) != 0 { - log.Error("validate header err", "number", header.Number, "hash", header.Hash(), "chainconfig", p.chainConfig, "config", p.config, "bytes", len(signersBytes)) return errExtraValidators } if isEpoch && len(signersBytes) == 0 { @@ -727,7 +724,6 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash // If we have explicit parents, pick from there (enforced) header = parents[len(parents)-1] if header.Hash() != hash || header.Number.Uint64() != number { - log.Info("cannot find ancestor, FindAncientHeader", "number", number, "stack", string(debug.Stack())) return nil, consensus.ErrUnknownAncestor } parents = parents[:len(parents)-1] @@ -735,7 +731,6 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash // No explicit parents (or no more left), reach out to the database header = chain.GetHeader(hash, number) if header == nil { - log.Info("cannot find ancestor, FindAncientHeader", "number", number, "stack", string(debug.Stack())) return nil, consensus.ErrUnknownAncestor } } @@ -795,7 +790,7 @@ func (p *Parlia) findSnapFromHistorySegment(hash common.Hash, number uint64) (*S tmp.config = p.config tmp.sigCache = p.signatures tmp.ethAPI = p.ethAPI - log.Info("found history segment snapshot", "number", number, "hash", hash, "segment", segment) + log.Debug("found history segment snapshot", "number", number, "hash", hash, "segment", segment) return &tmp, true } @@ -1000,7 +995,6 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header // Ensure the timestamp has the correct delay parent := chain.GetHeader(header.ParentHash, number-1) if parent == nil { - log.Info("cannot find ancestor, FindAncientHeader", "number", number, "stack", string(debug.Stack())) return consensus.ErrUnknownAncestor } header.Time = p.blockTimeForRamanujanFork(snap, header, parent) diff --git a/consensus/parlia/snapshot.go b/consensus/parlia/snapshot.go index 0957b9eb55..ddfb1811fc 100644 --- a/consensus/parlia/snapshot.go +++ b/consensus/parlia/snapshot.go @@ -22,7 +22,6 @@ import ( "encoding/json" "errors" "fmt" - "runtime/debug" "sort" lru "github.com/hashicorp/golang-lru" @@ -272,7 +271,6 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea if number > 0 && number%s.config.Epoch == uint64(len(snap.Validators)/2) { checkpointHeader := FindAncientHeader(header, uint64(len(snap.Validators)/2), chain, parents) if checkpointHeader == nil { - log.Info("cannot find ancestor, FindAncientHeader", "number", number, "stack", string(debug.Stack())) return nil, consensus.ErrUnknownAncestor } diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index b3363a8982..5b9a16ef8e 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -470,3 +470,7 @@ func (bc *BlockChain) WriteCanonicalHeaders(headers []*types.Header, tds []uint6 } return nil } + +func (bc *BlockChain) FreezerDBReset(tail, head uint64) error { + return bc.db.AncientReset(tail, head) +} diff --git a/core/genesis.go b/core/genesis.go index dd73d53b56..47f316c258 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -328,7 +328,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen log.Info("Writing default BSC mainnet genesis block") genesis = DefaultBSCGenesisBlock() } else { - log.Info("Writing custom genesis block", "config", genesis.Config) + log.Info("Writing custom genesis block") } block, err := genesis.Commit(db, triedb) if err != nil { @@ -421,7 +421,6 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, } storedcfg := rawdb.ReadChainConfig(db, stored) if storedcfg != nil { - log.Info("found chain config", "hash", stored, "cfg", storedcfg) return storedcfg, stored, nil } } diff --git a/core/rawdb/database.go b/core/rawdb/database.go index a3d7d5ec2c..0166b40067 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -201,6 +201,10 @@ func (db *nofreezedb) AncientDatadir() (string, error) { return "", errNotSupported } +func (db *nofreezedb) AncientReset(tail, head uint64) error { + return errNotSupported +} + // NewDatabase creates a high level database on top of a given key-value data // store without a freezer moving immutable chain segments into cold storage. func NewDatabase(db ethdb.KeyValueStore) ethdb.Database { diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index 0a7bbe436a..a55e00d536 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -598,3 +598,32 @@ func (f *Freezer) MigrateTable(kind string, convert convertLegacyFn) error { } return nil } + +func (f *Freezer) AncientReset(tail, head uint64) error { + if f.readonly { + return errReadOnly + } + f.writeLock.Lock() + defer f.writeLock.Unlock() + + for i := range f.tables { + nt, err := f.tables[i].resetItems(tail, head) + if err != nil { + return err + } + f.tables[i] = nt + } + + if err := f.repair(); err != nil { + for _, table := range f.tables { + table.Close() + } + return err + } + + f.frozen.Add(f.offset) + f.tail.Add(f.offset) + f.writeBatch = newFreezerBatch(f) + log.Info("Ancient database reset", "tail", f.tail.Load(), "frozen", f.frozen.Load()) + return nil +} diff --git a/core/rawdb/freezer_resettable.go b/core/rawdb/freezer_resettable.go index 326ad5be96..55a27f5316 100644 --- a/core/rawdb/freezer_resettable.go +++ b/core/rawdb/freezer_resettable.go @@ -204,6 +204,13 @@ func (f *ResettableFreezer) TruncateTail(tail uint64) (uint64, error) { return f.freezer.TruncateTail(tail) } +func (f *ResettableFreezer) AncientReset(tail, head uint64) error { + f.lock.RLock() + defer f.lock.RUnlock() + + return f.freezer.AncientReset(tail, head) +} + // Sync flushes all data tables to disk. func (f *ResettableFreezer) Sync() error { f.lock.RLock() diff --git a/core/rawdb/freezer_table.go b/core/rawdb/freezer_table.go index 5f1fc7133e..2e7af37abd 100644 --- a/core/rawdb/freezer_table.go +++ b/core/rawdb/freezer_table.go @@ -575,6 +575,57 @@ func (t *freezerTable) truncateTail(items uint64) error { return nil } +// resetItems reset freezer table head & tail +func (t *freezerTable) resetItems(tail, head uint64) (*freezerTable, error) { + if t.readonly { + return nil, errors.New("resetItems in readonly mode") + } + itemHidden := t.itemHidden.Load() + items := t.items.Load() + if tail != head && (itemHidden > tail || items < head) { + return nil, errors.New("cannot reset to non-exist range") + } + + var err error + if tail != head { + if err = t.truncateHead(head); err != nil { + return nil, err + } + if err = t.truncateTail(tail); err != nil { + return nil, err + } + return t, nil + } + + // if tail == head, it means table reset to 0 item + t.releaseFilesAfter(t.tailId-1, true) + t.head.Close() + os.Remove(t.head.Name()) + t.index.Close() + os.Remove(t.index.Name()) + t.meta.Close() + os.Remove(t.meta.Name()) + + var idxName string + if t.noCompression { + idxName = fmt.Sprintf("%s.ridx", t.name) // raw index file + } else { + idxName = fmt.Sprintf("%s.cidx", t.name) // compressed index file + } + index, err := openFreezerFileForAppend(filepath.Join(t.path, idxName)) + if err != nil { + return nil, err + } + tailIndex := indexEntry{ + offset: uint32(tail), + } + if _, err = index.Write(tailIndex.append(nil)); err != nil { + return nil, err + } + + return newFreezerTable(t.path, t.name, t.noCompression, t.readonly) +} + // Close closes all opened files. func (t *freezerTable) Close() error { t.lock.Lock() diff --git a/core/rawdb/freezer_table_test.go b/core/rawdb/freezer_table_test.go index f2d3773dd9..a6fd1861ab 100644 --- a/core/rawdb/freezer_table_test.go +++ b/core/rawdb/freezer_table_test.go @@ -27,6 +27,8 @@ import ( "testing" "testing/quick" + "github.com/stretchr/testify/assert" + "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum/metrics" "github.com/stretchr/testify/require" @@ -1337,3 +1339,98 @@ func TestRandom(t *testing.T) { t.Fatal(err) } } + +func TestResetItems(t *testing.T) { + t.Parallel() + rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() + fname := fmt.Sprintf("truncate-tail-%d", rand.Uint64()) + + // Fill table + f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false) + if err != nil { + t.Fatal(err) + } + + // Write 7 x 20 bytes, splitting out into four files + batch := f.newBatch(0) + require.NoError(t, batch.AppendRaw(0, getChunk(20, 0xFF))) + require.NoError(t, batch.AppendRaw(1, getChunk(20, 0xEE))) + require.NoError(t, batch.AppendRaw(2, getChunk(20, 0xdd))) + require.NoError(t, batch.AppendRaw(3, getChunk(20, 0xcc))) + require.NoError(t, batch.AppendRaw(4, getChunk(20, 0xbb))) + require.NoError(t, batch.AppendRaw(5, getChunk(20, 0xaa))) + require.NoError(t, batch.AppendRaw(6, getChunk(20, 0x11))) + require.NoError(t, batch.commit()) + + // nothing to do, all the items should still be there. + f, err = f.resetItems(0, 7) + assert.NoError(t, err) + fmt.Println(f.dumpIndexString(0, 1000)) + checkRetrieve(t, f, map[uint64][]byte{ + 0: getChunk(20, 0xFF), + 1: getChunk(20, 0xEE), + 2: getChunk(20, 0xdd), + 3: getChunk(20, 0xcc), + 4: getChunk(20, 0xbb), + 5: getChunk(20, 0xaa), + 6: getChunk(20, 0x11), + }) + + f, err = f.resetItems(1, 5) + assert.NoError(t, err) + _, err = f.resetItems(0, 5) + assert.Error(t, err) + _, err = f.resetItems(1, 6) + assert.Error(t, err) + + fmt.Println(f.dumpIndexString(0, 1000)) + checkRetrieveError(t, f, map[uint64]error{ + 0: errOutOfBounds, + }) + checkRetrieve(t, f, map[uint64][]byte{ + 1: getChunk(20, 0xEE), + 2: getChunk(20, 0xdd), + 3: getChunk(20, 0xcc), + 4: getChunk(20, 0xbb), + }) + + f, err = f.resetItems(4, 4) + assert.NoError(t, err) + checkRetrieveError(t, f, map[uint64]error{ + 4: errOutOfBounds, + }) + + batch = f.newBatch(0) + require.Error(t, batch.AppendRaw(0, getChunk(20, 0xa0))) + require.NoError(t, batch.AppendRaw(4, getChunk(20, 0xa4))) + require.NoError(t, batch.AppendRaw(5, getChunk(20, 0xa5))) + require.NoError(t, batch.commit()) + fmt.Println(f.dumpIndexString(0, 1000)) + + // Reopen the table, the deletion information should be persisted as well + f.Close() + f, err = newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false) + if err != nil { + t.Fatal(err) + } + fmt.Println(f.dumpIndexString(0, 1000)) + checkRetrieveError(t, f, map[uint64]error{ + 0: errOutOfBounds, + }) + checkRetrieve(t, f, map[uint64][]byte{ + 4: getChunk(20, 0xa4), + 5: getChunk(20, 0xa5), + }) + + // truncate all, the entire freezer should be deleted + f.truncateTail(6) + checkRetrieveError(t, f, map[uint64]error{ + 0: errOutOfBounds, + 1: errOutOfBounds, + 2: errOutOfBounds, + 3: errOutOfBounds, + 4: errOutOfBounds, + 5: errOutOfBounds, + 6: errOutOfBounds, + }) +} diff --git a/core/rawdb/prunedfreezer.go b/core/rawdb/prunedfreezer.go index ffc6647816..9f3541bc6f 100644 --- a/core/rawdb/prunedfreezer.go +++ b/core/rawdb/prunedfreezer.go @@ -188,6 +188,10 @@ func (f *prunedfreezer) TruncateTail(tail uint64) (uint64, error) { return 0, errNotSupported } +func (f *prunedfreezer) AncientReset(tail, head uint64) error { + return errNotSupported +} + // Sync flushes meta data tables to disk. func (f *prunedfreezer) Sync() error { WriteFrozenOfAncientFreezer(f.db, atomic.LoadUint64(&f.frozen)) diff --git a/core/rawdb/table.go b/core/rawdb/table.go index 23730aeb6a..79ab96b728 100644 --- a/core/rawdb/table.go +++ b/core/rawdb/table.go @@ -117,6 +117,10 @@ func (t *table) TruncateTail(items uint64) (uint64, error) { return t.db.TruncateTail(items) } +func (t *table) AncientReset(tail, head uint64) error { + return t.db.AncientReset(tail, head) +} + // Sync is a noop passthrough that just forwards the request to the underlying // database. func (t *table) Sync() error { diff --git a/eth/backend.go b/eth/backend.go index bae24fe778..2affaf7857 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -220,7 +220,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { return nil, err } if p, ok := eth.engine.(consensus.PoSA); ok { - log.Info("setup consensus engine history segment", "lastSegment", lastSegment) p.SetupHistorySegment(hsm) } } @@ -287,7 +286,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { return nil, err } bc.SetupHistorySegment(hsm) - log.Info("setup blockchain history segment", "lastSegment", lastSegment) } return bc, nil }) @@ -427,7 +425,8 @@ func GetHistorySegmentAndLastSegment(db ethdb.Database, genesisHash common.Hash, // check segment if match hard code if err = rawdb.AvailableHistorySegment(db, lastSegment); err != nil { - return nil, nil, err + log.Warn("there is no available history to prune", "head", latestHeader.Number) + return hsm, nil, nil } return hsm, lastSegment, nil } diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index cf81369419..370441eb46 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -214,8 +214,11 @@ type BlockChain interface { // LastHistorySegment get last history segment LastHistorySegment(num uint64) *params.HistorySegment - // WriteHeaders just write header into db, it an unsafe interface, just for history segment + // WriteCanonicalHeaders just write header into db, it an unsafe interface, just for history segment WriteCanonicalHeaders([]*types.Header, []uint64) error + + // FreezerDBReset reset freezer db to target tail & head + FreezerDBReset(tail, head uint64) error } type DownloadOption func(downloader *Downloader) *Downloader @@ -516,7 +519,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * if err != nil { return err } - log.Info("sync from peer", "local", localHeight, "remote", remoteHeight, "origin", origin, "peer", p.peer) + log.Debug("sync from peer", "local", localHeight, "remote", remoteHeight, "origin", origin, "peer", p.peer) if localHeight >= remoteHeight { // if remoteHeader does not exist in local chain, will move on to insert it as a side chain. @@ -592,6 +595,13 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * return err } } + + // if enable history segment, force reset freezer tail + if d.lastSegment != nil && localHeight == 0 { + if err := d.blockchain.FreezerDBReset(origin, origin); err != nil { + return err + } + } } // Initiate the sync using a concurrent header and content retrieval algorithm d.queue.Prepare(origin+1, mode) @@ -1778,7 +1788,7 @@ func (d *Downloader) findAncestorFromHistorySegment(p *peerConnection, remoteHei if err = d.blockchain.WriteCanonicalHeaders(headers, []uint64{d.lastSegment.TD}); err != nil { return 0, err } - log.Info("sync history segment header to local", "number", n, "hash", h, "segment", d.lastSegment) + log.Debug("sync history segment header to local", "number", n, "hash", h, "segment", d.lastSegment) } return n, nil } diff --git a/ethdb/database.go b/ethdb/database.go index 5af19e3478..83c4ae905e 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -136,6 +136,9 @@ type AncientWriter interface { // The second argument is a function that takes a raw entry and returns it // in the newest format. MigrateTable(string, func([]byte) ([]byte, error)) error + + // AncientReset reset ancient items + AncientReset(tail, head uint64) error } // AncientWriteOp is given to the function argument of ModifyAncients. diff --git a/ethdb/remotedb/remotedb.go b/ethdb/remotedb/remotedb.go index babb625d88..a13a0bc901 100644 --- a/ethdb/remotedb/remotedb.go +++ b/ethdb/remotedb/remotedb.go @@ -122,6 +122,10 @@ func (db *Database) TruncateTail(n uint64) (uint64, error) { panic("not supported") } +func (db *Database) AncientReset(tail, head uint64) error { + panic("not supported") +} + func (db *Database) Sync() error { return nil } diff --git a/params/history_segment.go b/params/history_segment.go index a317826cf9..bc51998cbc 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -43,7 +43,7 @@ type HistorySegment struct { } func (s *HistorySegment) String() string { - return fmt.Sprintf("[Index: %v, ReGenesisNumber: %v, ReGenesisHash: %v, TD: %v]", s.Index, s.ReGenesisNumber, s.ReGenesisNumber, s.TD) + return fmt.Sprintf("{Index: %v, ReGenesisNumber: %v, ReGenesisHash: %v, TD: %v}", s.Index, s.ReGenesisNumber, s.ReGenesisHash, s.TD) } func (s *HistorySegment) MatchBlock(h common.Hash, n uint64) bool { diff --git a/params/history_segment_test.go b/params/history_segment_test.go index bddd16373c..d1be7d3904 100644 --- a/params/history_segment_test.go +++ b/params/history_segment_test.go @@ -165,18 +165,18 @@ func TestIndexSegment(t *testing.T) { assert.Equal(t, segments[2], hsm.CurSegment(BoundStartBlock+HistorySegmentLength*2)) var ( - prev HistorySegment + prev *HistorySegment ok bool ) - _, ok = hsm.LastSegment(segments[0]) + _, ok = hsm.LastSegment(&segments[0]) assert.Equal(t, false, ok) - prev, ok = hsm.LastSegment(segments[1]) + prev, ok = hsm.LastSegment(&segments[1]) assert.Equal(t, true, ok) assert.Equal(t, segments[0], prev) - prev, ok = hsm.LastSegment(segments[2]) + prev, ok = hsm.LastSegment(&segments[2]) assert.Equal(t, true, ok) assert.Equal(t, segments[1], prev) - _, ok = hsm.LastSegment(HistorySegment{ + _, ok = hsm.LastSegment(&HistorySegment{ Index: uint64(len(segments)), }) assert.Equal(t, false, ok) From 924639cefdace017a134e745ade1a382cb456992 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Fri, 8 Dec 2023 15:10:34 +0800 Subject: [PATCH 16/22] historysegment: add testnet&mainnet hard code; --- cmd/geth/chaincmd.go | 34 +++++++++----------- cmd/geth/main.go | 2 +- cmd/utils/flags.go | 6 ++-- core/rawdb/database.go | 2 +- core/rawdb/prunedfreezer.go | 2 +- eth/backend.go | 6 ++-- eth/ethconfig/config.go | 2 +- eth/ethconfig/gen_config.go | 10 +++--- params/history_segment.go | 57 ++++++++++++++++++++++++++++------ params/history_segment_test.go | 38 ++++++++++------------- 10 files changed, 93 insertions(+), 66 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 4a327537fd..2e3bfc9989 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -726,29 +726,28 @@ func exportSegment(ctx *cli.Context) error { } latest := headerChain.CurrentHeader() if _, ok := engine.(consensus.PoSA); !ok { - return errors.New("current chain is not POSA consensus, cannot generate history segment") + return errors.New("cannot generate history segment because consensus engine is not PoSA") } if !chainConfig.IsLuban(latest.Number) { - return errors.New("current chain is not enable Luban hard fork, cannot generate history segment") + return errors.New("luban hard fork is not enabled , cannot generate history segment") } var ( boundStartBlock = params.BoundStartBlock historySegmentLength = params.HistorySegmentLength ) - // TODO(0xbundler): for testing - //switch genesisHash { - //case params.BSCGenesisHash, params.ChapelGenesisHash, params.RialtoGenesisHash: - // boundStartBlock = params.BoundStartBlock - // historySegmentLength = params.HistorySegmentLength - //default: - if ctx.IsSet(utils.BoundStartBlockFlag.Name) { - boundStartBlock = ctx.Uint64(utils.BoundStartBlockFlag.Name) - } - if ctx.IsSet(utils.HistorySegmentLengthFlag.Name) { - historySegmentLength = ctx.Uint64(utils.HistorySegmentLengthFlag.Name) - } - //} + switch genesisHash { + case params.BSCGenesisHash, params.ChapelGenesisHash, params.RialtoGenesisHash: + boundStartBlock = params.BoundStartBlock + historySegmentLength = params.HistorySegmentLength + default: + if ctx.IsSet(utils.BoundStartBlockFlag.Name) { + boundStartBlock = ctx.Uint64(utils.BoundStartBlockFlag.Name) + } + if ctx.IsSet(utils.HistorySegmentLengthFlag.Name) { + historySegmentLength = ctx.Uint64(utils.HistorySegmentLengthFlag.Name) + } + } if boundStartBlock == 0 || historySegmentLength == 0 { return fmt.Errorf("wrong params, boundStartBlock: %v, historySegmentLength: %v", boundStartBlock, historySegmentLength) } @@ -812,7 +811,7 @@ func exportSegment(ctx *cli.Context) error { } segments = append(segments, segment) } - if err = params.ValidateHisSegments(params.NewHistoryBlock(0, genesisHash, td.Uint64()), segments); err != nil { + if err = params.ValidateHistorySegments(params.NewHistoryBlock(0, genesisHash, td.Uint64()), segments); err != nil { return err } output, err := json.MarshalIndent(segments, "", " ") @@ -903,9 +902,6 @@ func simpleHeaderChain(db ethdb.Database, genesisHash common.Hash) (*params.Chai if err != nil { return nil, nil, nil, err } - if _, ok := engine.(consensus.PoSA); !ok { - return nil, nil, nil, errors.New("current chain is not POSA, cannot generate history segment") - } headerChain, err := core.NewHeaderChain(db, chainConfig, engine, func() bool { return true }) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index c2d09f9d93..7bbdce12f3 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -170,7 +170,7 @@ var ( utils.BLSPasswordFileFlag, utils.BLSWalletDirFlag, utils.VoteJournalDirFlag, - utils.HistorySegEnableFlag, + utils.HistorySegEnabledFlag, utils.HistorySegCustomFlag, }, utils.NetworkFlags, utils.DatabasePathFlags) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index cdbe49a1a1..843c338f7c 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1129,7 +1129,7 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server. } // History segment - HistorySegEnableFlag = &cli.BoolFlag{ + HistorySegEnabledFlag = &cli.BoolFlag{ Name: "history-segment", Usage: "Enable history segment feature, it will auto prune history segments by hard-code segment hash", Value: false, @@ -2182,8 +2182,8 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } // parse History Segment flags - if ctx.IsSet(HistorySegEnableFlag.Name) { - cfg.HistorySegmentEnable = ctx.Bool(HistorySegEnableFlag.Name) + if ctx.IsSet(HistorySegEnabledFlag.Name) { + cfg.HistorySegmentEnabled = ctx.Bool(HistorySegEnabledFlag.Name) } if ctx.IsSet(HistorySegCustomFlag.Name) { cfg.HistorySegmentCustomFile = ctx.String(HistorySegCustomFlag.Name) diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 0166b40067..36b453a69d 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -202,7 +202,7 @@ func (db *nofreezedb) AncientDatadir() (string, error) { } func (db *nofreezedb) AncientReset(tail, head uint64) error { - return errNotSupported + return nil } // NewDatabase creates a high level database on top of a given key-value data diff --git a/core/rawdb/prunedfreezer.go b/core/rawdb/prunedfreezer.go index 9f3541bc6f..9cb3978c1a 100644 --- a/core/rawdb/prunedfreezer.go +++ b/core/rawdb/prunedfreezer.go @@ -189,7 +189,7 @@ func (f *prunedfreezer) TruncateTail(tail uint64) (uint64, error) { } func (f *prunedfreezer) AncientReset(tail, head uint64) error { - return errNotSupported + return nil } // Sync flushes meta data tables to disk. diff --git a/eth/backend.go b/eth/backend.go index 2affaf7857..3eb4e0f9e5 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -214,7 +214,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { hsm *params.HistorySegmentManager lastSegment *params.HistorySegment ) - if config.HistorySegmentEnable { + if config.HistorySegmentEnabled { hsm, lastSegment, err = GetHistorySegmentAndLastSegment(chainDb, genesisHash, config.HistorySegmentCustomFile) if err != nil { return nil, err @@ -276,12 +276,12 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { txLookupLimit := &config.TransactionHistory // if enable HistorySegment, just skip txLookupLimit params, // may cause regenerate tx index, but it will also generate new block index - if config.HistorySegmentEnable { + if config.HistorySegmentEnabled { txLookupLimit = nil } bcOps = append(bcOps, func(bc *core.BlockChain) (*core.BlockChain, error) { // if enable history segment, try prune ancient data when restart - if config.HistorySegmentEnable { + if config.HistorySegmentEnabled { if err = truncateAncientTail(chainDb, lastSegment); err != nil { return nil, err } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 8488af5f41..b4f7e5c3f3 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -205,7 +205,7 @@ type Config struct { OverrideVerkle *uint64 `toml:",omitempty"` // History Segment - HistorySegmentEnable bool `toml:",omitempty"` + HistorySegmentEnabled bool `toml:",omitempty"` HistorySegmentCustomFile string `toml:",omitempty"` } diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index 61137241eb..7426d5bcd7 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -73,7 +73,7 @@ func (c Config) MarshalTOML() (interface{}, error) { OverrideKepler *uint64 `toml:",omitempty"` OverrideCancun *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"` - HistorySegmentEnable bool `toml:",omitempty"` + HistorySegmentEnabled bool `toml:",omitempty"` HistorySegmentCustomFile string `toml:",omitempty"` } var enc Config @@ -133,7 +133,7 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.OverrideKepler = c.OverrideKepler enc.OverrideCancun = c.OverrideCancun enc.OverrideVerkle = c.OverrideVerkle - enc.HistorySegmentEnable = c.HistorySegmentEnable + enc.HistorySegmentEnabled = c.HistorySegmentEnabled enc.HistorySegmentCustomFile = c.HistorySegmentCustomFile return &enc, nil } @@ -197,7 +197,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { OverrideKepler *uint64 `toml:",omitempty"` OverrideCancun *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"` - HistorySegmentEnable *bool `toml:",omitempty"` + HistorySegmentEnabled *bool `toml:",omitempty"` HistorySegmentCustomFile *string `toml:",omitempty"` } var dec Config @@ -372,8 +372,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.OverrideVerkle != nil { c.OverrideVerkle = dec.OverrideVerkle } - if dec.HistorySegmentEnable != nil { - c.HistorySegmentEnable = *dec.HistorySegmentEnable + if dec.HistorySegmentEnabled != nil { + c.HistorySegmentEnabled = *dec.HistorySegmentEnabled } if dec.HistorySegmentCustomFile != nil { c.HistorySegmentCustomFile = *dec.HistorySegmentCustomFile diff --git a/params/history_segment.go b/params/history_segment.go index bc51998cbc..27f75cdcec 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -16,8 +16,45 @@ const ( ) var ( - historySegmentsInBSCMainnet []HistorySegment - historySegmentsInBSCChapel []HistorySegment + historySegmentsInBSCMainnet = unmarshalHistorySegments(` +[ + { + "index": 0, + "re_genesis_number": 0, + "re_genesis_hash": "0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b", + "td": 1 + }, + { + "index": 1, + "re_genesis_number": 31268600, + "re_genesis_hash": "0x49bd8a17d31797ced6b466d91900cdd17a4c39cc685dc28ffd290196f417952c", + "td": 62131469, + "consensus_data": "0x7b226e756d626572223a33313236383539392c2268617368223a22307865663261363935356334383638373035623361376439323930313639376265613265303932366238313634386138373838393765386533333639383231306234222c2276616c696461746f7273223a7b22307830626163343932333836383632616433646634623636366263303936623035303562623639346461223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3137362c3139302c3139352c37322c3130342c32362c3234372c3130322c3131372c32382c3138342c35372c38372c3131302c3135362c38312c39302c392c3230302c3139312c3235302c34382c3136342c39382c3135302c3230342c3139372c3130322c31382c37332c31342c3138302c3132382c3230382c35392c3234392c37322c3232352c302c352c3138372c3230342c342c33332c3234392c31312c36312c37385d7d2c22307832343635313736633436316166623331366562633737336336316661656538356136353135646161223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3133382c3134362c35332c3130302c3139382c3235352c3231312c3132372c3137382c3235342c3135392c31372c3134322c3234382c3132382c3134362c3233322c3131382c34342c3132322c3232312c3138312c33382c3137312c3132362c3137372c3233312c3131342c3138362c3233392c3133332c32342c33312c3133372c34342c3131352c32372c3232342c3139332c3133372c32362c38302c3233302c3137362c39382c39382c3230302c32325d7d2c22307832643463343037626265343934333865643835396665393635623134306463663161616237316139223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b3134372c3139332c3234372c3234362c3134362c3135372c33312c3232362c3136312c3132332c37382c32302c39372c37382c3234392c3235322c39312c3232302c3131332c36312c3130322c34392c3231342c3131372c36342c36332c3139302c3233392c3137322c38352c39372c32372c3234362c31382c3131322c31312c32372c3130312c3234342c3131362c37322c39372c3138342c31312c31352c3132352c3130362c3137365d7d2c22307833663334396262616665633135353138313962386265316566656132666334366361373439616131223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3133322c33362c3133382c36392c3134382c3130302c3233382c3139332c3136322c33302c3132372c3139392c3138332c32362c352c36312c3135302c36382c3233332c3138372c3134312c3136342c3133332c35392c3134332c3133352c34342c3231352c3139332c3231342c3137392c33362c3139312c32352c33342c3133302c3135322c34382c3130302c3130382c3233342c3232332c3138322c38382c3231312c3232322c302c3135345d7d2c22307836316464343831613131346132653736316335353462363431373432633937333836373839396433223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3133382c3132382c3135302c3132352c35372c3232382c362c3136302c3136392c3130302c34352c36352c3233332c302c3132322c33392c3235322c31372c38302c3136322c3130332c3230392c36372c3136392c3234372c3133342c3230352c34332c39342c3233362c3138392c3230342c36342c35342c33392c35352c352c33342c39312c3134392c3130392c39342c34372c3134332c39342c3138352c39332c33375d7d2c22307836383562316465643830313337383564363632336363313864323134333230623662623634373539223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3133382c39362c3234382c34322c3132332c3230372c3131362c3138302c3230332c352c35392c3135352c3235342c3133312c3230382c3233372c322c3136382c37382c3138372c31362c3133342c39332c3235332c3231362c3232362c3131302c3131372c35332c3139362c35382c32382c3230342c3231302c3130342c3233322c39362c3234352c322c33332c3130372c35352c3135372c3235322c3135332c3131332c3231312c38385d7d2c22307837306636353731363465356237353638396236346237666431666132373566333334663238653138223a7b22696e6465783a6f6d6974656d707479223a372c22766f74655f61646472657373223a5b3135302c3136322c3130362c3235302c31382c3134392c3231382c3132392c36352c3133332c3134372c3138392c31382c3132392c36382c39392c3231372c3234362c3232382c39322c35342c3136302c3232382c3132362c3138302c3230352c36322c39312c3130362c3234322c3135362c36352c3232362c3136332c3136352c39392c3130302c34382c32312c39302c37302c3131302c33332c3130312c3133332c3137352c35392c3136375d7d2c22307837326236316336303134333432643931343437306563376163323937356265333435373936633262223a7b22696e6465783a6f6d6974656d707479223a382c22766f74655f61646472657373223a5b3132392c3231392c342c33342c3136352c3235332c382c3232382c31332c3137372c3235322c33352c3130342c3231302c33362c39342c37352c32342c3137372c3230382c3138342c39322c3134362c32362c3137302c3137352c3231302c3232372c36352c3131382c31342c34312c3235322c39372c36322c3232312c35372c3234372c31382c38342c39372c37382c33322c38352c3139352c34302c3132322c38315d7d2c22307837616532663562396533383663643162353061343535303639366439353763623439303066303361223a7b22696e6465783a6f6d6974656d707479223a392c22766f74655f61646472657373223a5b3138342c37392c3133312c3235352c34352c3234342c36352c3134372c37332c3130332c3134372c3138342c37312c3234362c37382c3135372c3130392c3137372c3137392c3134392c35342c3133302c3138372c3134392c3233372c3230382c3135302c3233352c33302c3130352c3138372c3231312c38372c3139342c302c3135332c34342c3136372c3132382c38302c3230382c3230332c3232352c3132382c3230372c3137302c312c3134325d7d2c22307838623663386664393364366634636561343262626233343564626336663064666462356265633733223a7b22696e6465783a6f6d6974656d707479223a31302c22766f74655f61646472657373223a5b3136382c3136322c38372c372c37382c3133302c3138342c3132392c3230372c3136302c3131302c3234332c3233352c37382c3235342c3230322c362c31322c33372c34392c35332c3135342c3138392c31342c3137312c3133382c3234312c3232372c3233372c3235302c33322c33372c3235322c3136342c3130302c3137322c3135362c36332c3230392c33352c3234362c3139342c37342c31332c3132302c3133342c3134382c3133335d7d2c22307861366637396236303335396631343164663930613063373435313235623133316361616666643132223a7b22696e6465783a6f6d6974656d707479223a31312c22766f74655f61646472657373223a5b3138332c3131342c3232352c3132382c3235312c3234332c3133382c352c32382c3135312c3231382c3138382c3133382c3137302c312c33382c3136322c35312c3136392c3233322c34302c3230352c3137352c3230342c3131362c33342c3139362c3138372c33312c36342c34382c3136352c3130372c3136332c3130302c3139372c36352c332c3234322c3130372c3137332c3134352c38302c3133392c38322c33322c3138332c36355d7d2c22307862323138633564366166316639373961633432626336386439386135613064373936633661623031223a7b22696e6465783a6f6d6974656d707479223a31322c22766f74655f61646472657373223a5b3138322c38392c3137332c31352c3138392c3135392c38312c38382c3134372c3235332c3231352c36342c3137382c3135352c3136302c3131392c34352c3138392c3233332c3138302c39392c38392c33332c3232312c3134352c3138392c34312c39392c3136302c3235322c3133332c39342c34392c3234362c35312c3134332c36392c3137382c31372c3139362c3233332c3232322c3231392c3132372c34362c3137362c3135372c3233315d7d2c22307862346464363664376332633765353766363238323130313837313932666238396434623939646434223a7b22696e6465783a6f6d6974656d707479223a31332c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307862653830376464646230373436333963643966613631623437363736633036346663353064363263223a7b22696e6465783a6f6d6974656d707479223a31342c22766f74655f61646472657373223a5b3137372c3234322c3139392c32312c3131392c3232322c3234332c32302c37392c3137312c3233352c3131372c3136382c3136312c3230302c3230332c39312c38312c3230392c3230392c3138302c3136302c39342c3233362c3130332c3135322c3133392c3133342c3133332c302c3133392c3137302c32332c36392c3135382c3139362c33372c3231392c3137342c3138382c3133332c34372c37332c3130392c3230312c33332c3135302c3230355d7d2c22307863633865366430306331376562343331333530633663353064386238663035313736623930623131223a7b22696e6465783a6f6d6974656d707479223a31352c22766f74655f61646472657373223a5b3137392c3136332c3231322c3235342c3138342c33372c3137342c3135312c322c3131332c32312c3130322c3232332c39332c3139312c35362c3233322c34322c3232312c37372c3230392c3138312c3131352c3138352c39332c33362c3130322c3235302c3130312c312c3230342c3138342c33302c3135372c33382c3136332c38322c3138352c39372c38302c3230342c3139312c3132332c3130352c3132372c3230382c3136342c32355d7d2c22307863653266643735343465306232636339343639326434613730346465626566376263623631333238223a7b22696e6465783a6f6d6974656d707479223a31362c22766f74655f61646472657373223a5b3138322c37342c3139302c33372c39372c37362c3135362c3235332c35302c3232382c38362c3138302c3231332c33332c3234322c3135362c3133312c38372c3234342c3137352c37302c362c3135312c3133302c3135302c3230312c3139302c3134372c37332c36342c3131342c3137322c352c3235302c3133342c3232372c3231302c3132342c3230302c3231342c3131302c3130312c302c31352c3133392c3136332c36332c3138375d7d2c22307865326433613733396566666364336139393338376430313565323630656566616337326562656131223a7b22696e6465783a6f6d6974656d707479223a31372c22766f74655f61646472657373223a5b3134392c3130382c37312c31332c3232332c3234342c3134302c3138302c3134372c302c33322c31312c39352c3133312c37332c3132372c35382c36302c3230332c35382c3233352c3133312c3139372c3233372c3231372c3132392c3133332c3130352c332c3134322c39372c3230392c3135312c32342c37392c37342c3136362c3134372c3135382c3136352c3233332c3134352c33302c36322c3135322c3137322c3130392c33335d7d2c22307865396165333236316134373561323762623130323866313430626332613763383433333138616664223a7b22696e6465783a6f6d6974656d707479223a31382c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307865613061366533633531316262643130663435313965636533376463323438383765313162353564223a7b22696e6465783a6f6d6974656d707479223a31392c22766f74655f61646472657373223a5b3137382c3231322c3139382c34302c36302c36382c3136312c3139392c3138392c38302c35382c3137312c3136372c3130322c3131302c3135392c31322c3133312c31342c31352c3234302c32322c3139332c3139392c38302c3136352c3232382c3133352c38372c3136372c31392c3230382c3133312c3130372c32382c3137312c3235332c39322c34302c32372c32392c3232372c3138332c3132352c32382c32352c33332c3133315d7d2c22307865653232363337396462383363666663363831343935373330633131666464653739626134633063223a7b22696e6465783a6f6d6974656d707479223a32302c22766f74655f61646472657373223a5b3137342c3132332c3139382c3235302c3136332c3234302c3230342c36322c39362c3134372c3138322c35312c3235332c3132362c3232382c3234382c3130352c3131322c3134362c3130352c38382c3230382c3138332c3233362c3132382c36372c3132372c3134372c3130362c3230372c33332c34332c3132302c3234302c3230352c392c39352c36392c3130312c3235352c3234312c36382c3235332c36392c3134312c33352c35382c39315d7d2c22307865663032373465333138313063396466303266393866616664653066383431663465363661316364223a7b22696e6465783a6f6d6974656d707479223a32312c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d7d2c22726563656e7473223a7b223331323638353839223a22307838623663386664393364366634636561343262626233343564626336663064666462356265633733222c223331323638353930223a22307861366637396236303335396631343164663930613063373435313235623133316361616666643132222c223331323638353931223a22307862323138633564366166316639373961633432626336386439386135613064373936633661623031222c223331323638353932223a22307862346464363664376332633765353766363238323130313837313932666238396434623939646434222c223331323638353933223a22307862653830376464646230373436333963643966613631623437363736633036346663353064363263222c223331323638353934223a22307863633865366430306331376562343331333530633663353064386238663035313736623930623131222c223331323638353935223a22307863653266643735343465306232636339343639326434613730346465626566376263623631333238222c223331323638353936223a22307865326433613733396566666364336139393338376430313565323630656566616337326562656131222c223331323638353937223a22307865396165333236316134373561323762623130323866313430626332613763383433333138616664222c223331323638353938223a22307865613061366533633531316262643130663435313965636533376463323438383765313162353564222c223331323638353939223a22307865653232363337396462383363666663363831343935373330633131666464653739626134633063227d2c22726563656e745f666f726b5f686173686573223a7b223331323638353739223a226231396466346132222c223331323638353830223a226231396466346132222c223331323638353831223a226231396466346132222c223331323638353832223a226231396466346132222c223331323638353833223a226231396466346132222c223331323638353834223a226231396466346132222c223331323638353835223a226231396466346132222c223331323638353836223a226231396466346132222c223331323638353837223a226231396466346132222c223331323638353838223a226231396466346132222c223331323638353839223a226231396466346132222c223331323638353930223a226231396466346132222c223331323638353931223a226231396466346132222c223331323638353932223a226231396466346132222c223331323638353933223a226231396466346132222c223331323638353934223a226231396466346132222c223331323638353935223a226231396466346132222c223331323638353936223a226231396466346132222c223331323638353937223a226231396466346132222c223331323638353938223a226231396466346132222c223331323638353939223a226231396466346132227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33313236383539372c22536f7572636548617368223a22307863653762343062643836353463306339653961653131373063393839666531353138323562356235306163313063313838326539383331366164643362343833222c225461726765744e756d626572223a33313236383539382c2254617267657448617368223a22307837323335343633626530633139623361626461366666653766393035633936613861643632616565393663616239396465613937303531626433346564313366227d7d" + } +]`) + historySegmentsInBSCChapel = unmarshalHistorySegments(` +[ + { + "index": 0, + "re_genesis_number": 0, + "re_genesis_hash": "0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34", + "td": 1 + }, + { + "index": 1, + "re_genesis_number": 31268600, + "re_genesis_hash": "0x5faa1dcf2140c2fbaf9b713c74e34485d38218df6fc1797b19704d7c964d6943", + "td": 62348406, + "consensus_data": "0x7b226e756d626572223a33313236383539392c2268617368223a22307833336138623166303962626164356663623636323565333866353162663936656162313461383937636636366331633731306336366631383039323634353666222c2276616c696461746f7273223a7b22307831323834323134623962396338353534396162336432623937326466306465656636366163326339223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3134322c3133302c3134372c37362c3136392c3131362c3235332c3230352c3135312c3234332c34382c3135372c3233332c3130332c3231312c3230312c3139362c36332c3136372c31372c3136382c3231342c3131352c3137352c39332c3131372c37302c38382c36382c3139312c3133372c3130352c3230302c3230392c3134382c3134312c3134342c35352c37322c3137322c3132332c3133392c32332c33322c3235302c3130302c3232392c31325d7d2c22307833353535326331363730346432313433343766323966613737663737646136643735643763373532223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3138332c36362c3137332c37322c38352c3138362c3232372c34382c36362c3130372c3133302c36322c3131362c34352c3136332c33312c3132392c3130382c3230302c35392c3139332c3130392c3130352c3136392c31392c37352c3232342c3230372c3138302c3136312c3230392c3132362c3139352c37392c32372c39312c35302c3231332c3139342c342c36342c3138342c38332c3130372c33302c3133362c3234302c3234325d7d2c22307839383061373565636431333039656131326661326564383761383734346662666339623836336435223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b3133372c332c3132322c3135342c3230362c35392c38392c312c3130312c3233342c32382c31322c39302c3139392c34332c3234362c302c3138332c3230302c3134302c33302c36372c39352c36352c3134372c34342c31372c35302c3137302c3232352c3139312c3136302c3138372c3130342c3232382c3130372c3135302c3230342c3137372c34342c35322c32312c3232382c3231362c34322c3234372c32332c3231365d7d2c22307861323935396433663935656165356463376437303134346365316237336234303362376562366530223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3138352c3131352c3139342c3231312c3133322c3133352c3232392c3134332c3231342c3232352c36392c37332c32372c31372c302c3132382c3235312c32302c3137322c3134352c39302c342c31372c3235322c3132302c3234312c3135382c392c3136332c3135332c3232312c3233382c31332c33322c3139382c35382c3131372c3231362c3234392c34382c3234312c3130352c36392c36382c3137332c34352c3139322c32375d7d2c22307862373162323134636238383535303038343433363565393563643939343263373237366537666438223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3136322c3131372c31342c3139382c3232312c3233372c36312c3230352c3139342c3234332c38312c3132302c33352c31362c3137362c3233342c3232302c372c3132352c3138312c3135342c3138382c3136302c3234302c3230352c33382c3131392c3131302c34362c3132322c3230332c3135392c35392c3230362c36342c3137372c3235302c38322c33332c3235332c32312c39372c33342c3130382c39382c39392c3230342c39355d7d2c22307866343734636630336363656666323861626336356339636261653539346637323563383065313264223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3135302c3230312c3138342c3130382c35322c302c3232392c34312c3139312c3232352c3133322c352c3131302c33372c3132342c372c3134382c31312c3138322c3130302c39392c3131312c3130342c3135382c3134312c33322c33392c3230302c35322c3130342c33312c3134332c3133352c3133392c3131352c36382c38322c39372c332c37382c3134382c3130372c3137382c3231372c312c3138302c3138342c3132305d7d7d2c22726563656e7473223a7b223331323638353936223a22307862373162323134636238383535303038343433363565393563643939343263373237366537666438222c223331323638353937223a22307866343734636630336363656666323861626336356339636261653539346637323563383065313264222c223331323638353938223a22307831323834323134623962396338353534396162336432623937326466306465656636366163326339222c223331323638353939223a22307833353535326331363730346432313433343766323966613737663737646136643735643763373532227d2c22726563656e745f666f726b5f686173686573223a7b223331323638353934223a226463353539303563222c223331323638353935223a226463353539303563222c223331323638353936223a226463353539303563222c223331323638353937223a226463353539303563222c223331323638353938223a226463353539303563222c223331323638353939223a226463353539303563227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33313236383539372c22536f7572636548617368223a22307832656632326232643862366338616439303233616361336162393431313632616163313530336664666133323664303832333038373933636365346466353939222c225461726765744e756d626572223a33313236383539382c2254617267657448617368223a22307830643166383737333736613335393232616233366331613231346561663038353335663439656135613866336531316532373637326535386665326533666136227d7d" + }, + { + "index": 2, + "re_genesis_number": 33860600, + "re_genesis_hash": "0x4e5acd6301c45368469f3d0b59e3a0551cea55cfabb0d53b38f48bf463786621", + "td": 67529391, + "consensus_data": "0x7b226e756d626572223a33333836303539392c2268617368223a22307835383131616633393632353831303633656636393935346666613832326566616439333631636432336663303965653639666632343162313961336336373364222c2276616c696461746f7273223a7b22307831323834323134623962396338353534396162336432623937326466306465656636366163326339223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3134322c3133302c3134372c37362c3136392c3131362c3235332c3230352c3135312c3234332c34382c3135372c3233332c3130332c3231312c3230312c3139362c36332c3136372c31372c3136382c3231342c3131352c3137352c39332c3131372c37302c38382c36382c3139312c3133372c3130352c3230302c3230392c3134382c3134312c3134342c35352c37322c3137322c3132332c3133392c32332c33322c3235302c3130302c3232392c31325d7d2c22307833353535326331363730346432313433343766323966613737663737646136643735643763373532223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3138332c36362c3137332c37322c38352c3138362c3232372c34382c36362c3130372c3133302c36322c3131362c34352c3136332c33312c3132392c3130382c3230302c35392c3139332c3130392c3130352c3136392c31392c37352c3232342c3230372c3138302c3136312c3230392c3132362c3139352c37392c32372c39312c35302c3231332c3139342c342c36342c3138342c38332c3130372c33302c3133362c3234302c3234325d7d2c22307834373738383338366430656436633734386530336135333136306234623330656433373438636335223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307839383061373565636431333039656131326661326564383761383734346662666339623836336435223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3133372c332c3132322c3135342c3230362c35392c38392c312c3130312c3233342c32382c31322c39302c3139392c34332c3234362c302c3138332c3230302c3134302c33302c36372c39352c36352c3134372c34342c31372c35302c3137302c3232352c3139312c3136302c3138372c3130342c3232382c3130372c3135302c3230342c3137372c34342c35322c32312c3232382c3231362c34322c3234372c32332c3231365d7d2c22307861323935396433663935656165356463376437303134346365316237336234303362376562366530223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3138352c3131352c3139342c3231312c3133322c3133352c3232392c3134332c3231342c3232352c36392c37332c32372c31372c302c3132382c3235312c32302c3137322c3134352c39302c342c31372c3235322c3132302c3234312c3135382c392c3136332c3135332c3232312c3233382c31332c33322c3139382c35382c3131372c3231362c3234392c34382c3234312c3130352c36392c36382c3137332c34352c3139322c32375d7d2c22307862373162323134636238383535303038343433363565393563643939343263373237366537666438223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3136322c3131372c31342c3139382c3232312c3233372c36312c3230352c3139342c3234332c38312c3132302c33352c31362c3137362c3233342c3232302c372c3132352c3138312c3135342c3138382c3136302c3234302c3230352c33382c3131392c3131302c34362c3132322c3230332c3135392c35392c3230362c36342c3137372c3235302c38322c33332c3235332c32312c39372c33342c3130382c39382c39392c3230342c39355d7d2c22307866343734636630336363656666323861626336356339636261653539346637323563383065313264223a7b22696e6465783a6f6d6974656d707479223a372c22766f74655f61646472657373223a5b3135302c3230312c3138342c3130382c35322c302c3232392c34312c3139312c3232352c3133322c352c3131302c33372c3132342c372c3134382c31312c3138322c3130302c39392c3131312c3130342c3135382c3134312c33322c33392c3230302c35322c3130342c33312c3134332c3133352c3133392c3131352c36382c38322c39372c332c37382c3134382c3130372c3137382c3231372c312c3138302c3138342c3132305d7d7d2c22726563656e7473223a7b223333383630353936223a22307831323834323134623962396338353534396162336432623937326466306465656636366163326339222c223333383630353937223a22307833353535326331363730346432313433343766323966613737663737646136643735643763373532222c223333383630353938223a22307834373738383338366430656436633734386530336135333136306234623330656433373438636335222c223333383630353939223a22307839383061373565636431333039656131326661326564383761383734346662666339623836336435227d2c22726563656e745f666f726b5f686173686573223a7b223333383630353933223a226463353539303563222c223333383630353934223a226463353539303563222c223333383630353935223a226463353539303563222c223333383630353936223a226463353539303563222c223333383630353937223a226463353539303563222c223333383630353938223a226463353539303563222c223333383630353939223a226463353539303563227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33333836303539372c22536f7572636548617368223a22307839326661356163363435376339656333383830306130666431633362333861366137373833633432343363306130613435643937343539623263613030363538222c225461726765744e756d626572223a33333836303539382c2254617267657448617368223a22307836356464343461663939336263663737326462393139356666643265646432653965313733366432363162353534386330376264306166376439363334396432227d7d" + } +]`) ) type HistoryBlock struct { @@ -121,7 +158,7 @@ func NewHistorySegmentManager(cfg *HistorySegmentConfig) (*HistorySegmentManager return nil, fmt.Errorf("LoadCustomSegments err %v", err) } } - if err = ValidateHisSegments(cfg.Genesis, segments); err != nil { + if err = ValidateHistorySegments(cfg.Genesis, segments); err != nil { return nil, err } return &HistorySegmentManager{ @@ -131,7 +168,7 @@ func NewHistorySegmentManager(cfg *HistorySegmentConfig) (*HistorySegmentManager } func NewHistorySegmentManagerWithSegments(genesis HistoryBlock, segments []HistorySegment) (*HistorySegmentManager, error) { - if err := ValidateHisSegments(genesis, segments); err != nil { + if err := ValidateHistorySegments(genesis, segments); err != nil { return nil, err } return &HistorySegmentManager{ @@ -142,7 +179,7 @@ func NewHistorySegmentManagerWithSegments(genesis HistoryBlock, segments []Histo }, nil } -func ValidateHisSegments(genesis HistoryBlock, segments []HistorySegment) error { +func ValidateHistorySegments(genesis HistoryBlock, segments []HistorySegment) error { if len(segments) == 0 { return errors.New("history segment length cannot be 0") } @@ -165,14 +202,14 @@ func ValidateHisSegments(genesis HistoryBlock, segments []HistorySegment) error return nil } -// HisSegments return all history segments -func (m *HistorySegmentManager) HisSegments() []HistorySegment { +// HistorySegments return all history segments +func (m *HistorySegmentManager) HistorySegments() []HistorySegment { return m.segments } // CurSegment return which segment include this block func (m *HistorySegmentManager) CurSegment(num uint64) *HistorySegment { - segments := m.HisSegments() + segments := m.HistorySegments() i := len(segments) - 1 for i >= 0 { if segments[i].ReGenesisNumber <= num { @@ -189,7 +226,7 @@ func (m *HistorySegmentManager) LastSegment(cur *HistorySegment) (*HistorySegmen if cur == nil { return nil, false } - segments := m.HisSegments() + segments := m.HistorySegments() if cur.Index == 0 || cur.Index >= uint64(len(segments)) { return nil, false } @@ -202,7 +239,7 @@ func (m *HistorySegmentManager) LastSegmentByNumber(num uint64) (*HistorySegment return m.LastSegment(cur) } -func unmarshalHisSegments(enc string) []HistorySegment { +func unmarshalHistorySegments(enc string) []HistorySegment { var ret []HistorySegment err := json.Unmarshal([]byte(enc), &ret) if err != nil { diff --git a/params/history_segment_test.go b/params/history_segment_test.go index d1be7d3904..5d870609da 100644 --- a/params/history_segment_test.go +++ b/params/history_segment_test.go @@ -23,33 +23,27 @@ var ( }, { Index: 2, - ReGenesisNumber: 33860530, + ReGenesisNumber: BoundStartBlock + HistorySegmentLength, ReGenesisHash: common.HexToHash("0xbf6d408bce0d531c41b00410e1c567e46b359db6e14d842cd8c8325039dff498"), }, } testGenesis = common.HexToHash("0x50b168d3ba07cc77c13a5469b9a1aad8752ba725ff989b76bc7df89dc936e866") ) -func TestNewHisSegmentManager_HardCode(t *testing.T) { +func TestNewHistorySegmentManager_HardCode(t *testing.T) { tests := []struct { cfg *HistorySegmentConfig }{ { cfg: &HistorySegmentConfig{ CustomPath: "", - Genesis: NewHistoryBlock(0, BSCGenesisHash, 0), + Genesis: NewHistoryBlock(0, BSCGenesisHash, 1), }, }, { cfg: &HistorySegmentConfig{ CustomPath: "", - Genesis: NewHistoryBlock(0, ChapelGenesisHash, 0), - }, - }, - { - cfg: &HistorySegmentConfig{ - CustomPath: "", - Genesis: NewHistoryBlock(0, RialtoGenesisHash, 0), + Genesis: NewHistoryBlock(0, ChapelGenesisHash, 1), }, }, } @@ -59,7 +53,7 @@ func TestNewHisSegmentManager_HardCode(t *testing.T) { } } -func TestHisSegmentManager_Validate(t *testing.T) { +func TestHistorySegmentManager_Validate(t *testing.T) { tests := []struct { genesis common.Hash segments []HistorySegment @@ -135,7 +129,7 @@ func TestHisSegmentManager_Validate(t *testing.T) { }, } for i, item := range tests { - err := ValidateHisSegments(NewHistoryBlock(0, item.genesis, 0), item.segments) + err := ValidateHistorySegments(NewHistoryBlock(0, item.genesis, 0), item.segments) if item.err { assert.Error(t, err, i) continue @@ -144,11 +138,11 @@ func TestHisSegmentManager_Validate(t *testing.T) { } } -func TestUnmarshalHisSegments(t *testing.T) { +func TestUnmarshalHistorySegments(t *testing.T) { enc, err := json.MarshalIndent(historySegmentsInTest, "", " ") assert.NoError(t, err) //t.Log(string(enc)) - segments := unmarshalHisSegments(string(enc)) + segments := unmarshalHistorySegments(string(enc)) assert.Equal(t, historySegmentsInTest, segments) } @@ -157,12 +151,12 @@ func TestIndexSegment(t *testing.T) { hsm := HistorySegmentManager{ segments: historySegmentsInTest, } - assert.Equal(t, segments[0], hsm.CurSegment(0)) - assert.Equal(t, segments[0], hsm.CurSegment(BoundStartBlock-1)) - assert.Equal(t, segments[1], hsm.CurSegment(BoundStartBlock)) - assert.Equal(t, segments[1], hsm.CurSegment(BoundStartBlock+HistorySegmentLength-1)) - assert.Equal(t, segments[2], hsm.CurSegment(BoundStartBlock+HistorySegmentLength)) - assert.Equal(t, segments[2], hsm.CurSegment(BoundStartBlock+HistorySegmentLength*2)) + assert.Equal(t, &segments[0], hsm.CurSegment(0)) + assert.Equal(t, &segments[0], hsm.CurSegment(BoundStartBlock-1)) + assert.Equal(t, &segments[1], hsm.CurSegment(BoundStartBlock)) + assert.Equal(t, &segments[1], hsm.CurSegment(BoundStartBlock+HistorySegmentLength-1)) + assert.Equal(t, &segments[2], hsm.CurSegment(BoundStartBlock+HistorySegmentLength)) + assert.Equal(t, &segments[2], hsm.CurSegment(BoundStartBlock+HistorySegmentLength*2)) var ( prev *HistorySegment @@ -172,10 +166,10 @@ func TestIndexSegment(t *testing.T) { assert.Equal(t, false, ok) prev, ok = hsm.LastSegment(&segments[1]) assert.Equal(t, true, ok) - assert.Equal(t, segments[0], prev) + assert.Equal(t, &segments[0], prev) prev, ok = hsm.LastSegment(&segments[2]) assert.Equal(t, true, ok) - assert.Equal(t, segments[1], prev) + assert.Equal(t, &segments[1], prev) _, ok = hsm.LastSegment(&HistorySegment{ Index: uint64(len(segments)), }) From 78adfc7a96c20d6fd8f56df13a78db74e4b99b81 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Mon, 18 Dec 2023 17:59:50 +0800 Subject: [PATCH 17/22] freezerdb: fix migrate ancient data err when sync from history segment; chainindexer: fix index bloombits err when sync from history segment; --- core/blockchain_reader.go | 14 +++-- core/chain_indexer.go | 5 ++ core/rawdb/database.go | 10 ++-- eth/backend.go | 3 + eth/downloader/downloader.go | 72 ++++++++++++++++++++---- eth/downloader/fetchers.go | 95 ++++++++++++++++++++++++++++++++ params/history_segment.go | 47 ---------------- params/history_segment_config.go | 56 +++++++++++++++++++ 8 files changed, 234 insertions(+), 68 deletions(-) create mode 100644 params/history_segment_config.go diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index 5b9a16ef8e..a74ee533a1 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -460,13 +460,19 @@ func (bc *BlockChain) LastHistorySegment(num uint64) *params.HistorySegment { return segment } -func (bc *BlockChain) WriteCanonicalHeaders(headers []*types.Header, tds []uint64) error { +func (bc *BlockChain) WriteCanonicalBlockAndReceipt(headers []*types.Header, tds []uint64, bodies []*types.Body, receipts [][]*types.Receipt) error { + batch := bc.db.NewBatch() for i, header := range headers { h := header.Hash() n := header.Number.Uint64() - rawdb.WriteTd(bc.db, h, n, new(big.Int).SetUint64(tds[i])) - rawdb.WriteHeader(bc.db, header) - rawdb.WriteCanonicalHash(bc.db, h, n) + rawdb.WriteTd(batch, h, n, new(big.Int).SetUint64(tds[i])) + rawdb.WriteHeader(batch, header) + rawdb.WriteBody(batch, h, n, bodies[i]) + rawdb.WriteReceipts(batch, h, n, receipts[i]) + rawdb.WriteCanonicalHash(batch, h, n) + } + if err := batch.Write(); err != nil { + return err } return nil } diff --git a/core/chain_indexer.go b/core/chain_indexer.go index f5fce72588..dd1c4a5278 100644 --- a/core/chain_indexer.go +++ b/core/chain_indexer.go @@ -521,3 +521,8 @@ func (c *ChainIndexer) removeSectionHead(section uint64) { c.indexDb.Delete(append([]byte("shead"), data[:]...)) } + +// GetSection calculate section from head number +func (c *ChainIndexer) GetSection(head uint64) uint64 { + return (head + 1) / c.sectionSize +} diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 36b453a69d..fc08e2a9f3 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -588,11 +588,6 @@ func AncientInspect(db ethdb.Database) error { log.Info("Inspect ancient prune situation...") offset := counter(ReadOffSetOfCurrentAncientFreezer(db)) - // if tail is not 0, just overwrite it - tail, _ := db.Tail() - if tail > 0 { - offset = counter(tail) - } // Get number of ancient rows inside the freezer. ancients := counter(0) if count, err := db.ItemAmountInAncient(); err != nil { @@ -607,6 +602,11 @@ func AncientInspect(db ethdb.Database) error { } else { endNumber = offset + ancients - 1 } + // if tail is not 0, just overwrite it + tail, _ := db.Tail() + if tail > 0 { + offset = counter(tail) + } stats = [][]string{ {"Offset/StartBlockNumber", "Offset/StartBlockNumber of ancientDB", offset.String()}, {"Amount of remained items in AncientStore", "Remaining items of ancientDB", ancients.String()}, diff --git a/eth/backend.go b/eth/backend.go index 3eb4e0f9e5..7fef1398fd 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -222,6 +222,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if p, ok := eth.engine.(consensus.PoSA); ok { p.SetupHistorySegment(hsm) } + if lastSegment != nil { + eth.bloomIndexer.AddCheckpoint(eth.bloomIndexer.GetSection(lastSegment.ReGenesisNumber), lastSegment.ReGenesisHash) + } } bcVersion := rawdb.ReadDatabaseVersion(chainDb) diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 370441eb46..11e0caea30 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -214,8 +214,8 @@ type BlockChain interface { // LastHistorySegment get last history segment LastHistorySegment(num uint64) *params.HistorySegment - // WriteCanonicalHeaders just write header into db, it an unsafe interface, just for history segment - WriteCanonicalHeaders([]*types.Header, []uint64) error + // WriteCanonicalBlockAndReceipt just write header into db, it an unsafe interface, just for history segment + WriteCanonicalBlockAndReceipt([]*types.Header, []uint64, []*types.Body, [][]*types.Receipt) error // FreezerDBReset reset freezer db to target tail & head FreezerDBReset(tail, head uint64) error @@ -1779,18 +1779,66 @@ func (d *Downloader) findAncestorFromHistorySegment(p *peerConnection, remoteHei return 0, fmt.Errorf("%w: multiple headers (%d) for single request", errBadPeer, len(headers)) } - // check if it matches local last segment + // check if it matches local previous segment h := hashes[0] n := headers[0].Number.Uint64() - if d.lastSegment.MatchBlock(h, n) { - if !d.blockchain.HasHeader(h, n) { - // just write header, td, because it's snap sync, just sync history is enough - if err = d.blockchain.WriteCanonicalHeaders(headers, []uint64{d.lastSegment.TD}); err != nil { - return 0, err - } - log.Debug("sync history segment header to local", "number", n, "hash", h, "segment", d.lastSegment) - } + if !d.lastSegment.MatchBlock(h, n) { + return 0, nil + } + + if d.blockchain.HasHeader(h, n) { return n, nil } - return 0, nil + + body, receipts, err := d.fetchBodyAndReceiptsByHeader(p, headers[0], hashes[0]) + if err != nil { + return 0, err + } + // just write header, td, because it's snap sync, just sync history is enough + if err = d.blockchain.WriteCanonicalBlockAndReceipt(headers, []uint64{d.lastSegment.TD}, []*types.Body{body}, [][]*types.Receipt{receipts}); err != nil { + return 0, err + } + log.Debug("sync history segment header to local", "number", n, "hash", h, "segment", d.lastSegment) + return n, nil +} + +func (d *Downloader) fetchBodyAndReceiptsByHeader(p *peerConnection, header *types.Header, h common.Hash) (*types.Body, []*types.Receipt, error) { + // download ancient data + bodies, bodyHashset, err := d.fetchBodiesByHashes(p, []common.Hash{h}) + if err != nil { + return nil, nil, err + } + if len(bodies) != 1 { + return nil, nil, fmt.Errorf("%w: multiple bodies (%d) for single request", errBadPeer, len(bodies)) + } + if header.TxHash != bodyHashset[0][0] { + return nil, nil, fmt.Errorf("%w: fetch body with wrong TxHash %v, expect %v", errBadPeer, bodyHashset[0][0], header.TxHash) + } + if header.UncleHash != bodyHashset[1][0] { + return nil, nil, fmt.Errorf("%w: fetch body with wrong UncleHash %v, expect %v", errBadPeer, bodyHashset[0][1], header.UncleHash) + } + if header.WithdrawalsHash == nil { + if bodies[0].Withdrawals != nil { + return nil, nil, fmt.Errorf("%w: fetch body with wrong Withdrawals %v, expect %v", errBadPeer, len(bodies[0].Withdrawals), header.WithdrawalsHash) + } + } else { + if bodies[0].Withdrawals == nil { + return nil, nil, fmt.Errorf("%w: fetch body with wrong Withdrawals %v, expect %v", errBadPeer, len(bodies[0].Withdrawals), *header.WithdrawalsHash) + } + if bodyHashset[2][0] != *header.WithdrawalsHash { + return nil, nil, fmt.Errorf("%w: fetch body with wrong Withdrawals %v, expect %v", errBadPeer, bodyHashset[2][0], *header.WithdrawalsHash) + } + } + + receipts, receiptHashes, err := d.fetchReceiptsByHashes(p, []common.Hash{h}) + if err != nil { + return nil, nil, err + } + if len(receipts) != 1 { + return nil, nil, fmt.Errorf("%w: multiple receipts (%d) for single request", errBadPeer, len(receipts)) + } + if header.ReceiptHash != receiptHashes[0] { + return nil, nil, fmt.Errorf("%w: fetch receipts with wrong ReceiptHash %v, expect %v", errBadPeer, receiptHashes[0], header.ReceiptHash) + } + return bodies[0], receipts[0], nil } diff --git a/eth/downloader/fetchers.go b/eth/downloader/fetchers.go index 021e8c4f9b..1ce1c22187 100644 --- a/eth/downloader/fetchers.go +++ b/eth/downloader/fetchers.go @@ -113,3 +113,98 @@ func (d *Downloader) fetchHeadersByNumber(p *peerConnection, number uint64, amou return *res.Res.(*eth.BlockHeadersPacket), res.Meta.([]common.Hash), nil } } + +// fetchBodiesByHashes is a blocking version of Peer.RequestBodies +func (d *Downloader) fetchBodiesByHashes(p *peerConnection, hashes []common.Hash) ([]*types.Body, [][]common.Hash, error) { + // Create the response sink and send the network request + start := time.Now() + resCh := make(chan *eth.Response) + + req, err := p.peer.RequestBodies(hashes, resCh) + if err != nil { + return nil, nil, err + } + defer req.Close() + + // Wait until the response arrives, the request is cancelled or times out + ttl := d.peers.rates.TargetTimeout() + + timeoutTimer := time.NewTimer(ttl) + defer timeoutTimer.Stop() + + select { + case <-d.cancelCh: + return nil, nil, errCanceled + + case <-timeoutTimer.C: + // Header retrieval timed out, update the metrics + p.log.Debug("Header request timed out", "elapsed", ttl) + headerTimeoutMeter.Mark(1) + + return nil, nil, errTimeout + + case res := <-resCh: + // Headers successfully retrieved, update the metrics + headerReqTimer.Update(time.Since(start)) + headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockBodiesPacket)))) + + // Don't reject the packet even if it turns out to be bad, downloader will + // disconnect the peer on its own terms. Simply delivery the headers to + // be processed by the caller + res.Done <- nil + packets := *res.Res.(*eth.BlockBodiesPacket) + bodies := make([]*types.Body, len(packets)) + for i, p := range packets { + bodies[i] = &types.Body{ + Transactions: p.Transactions, + Uncles: p.Uncles, + Withdrawals: p.Withdrawals, + } + } + hashsets := res.Meta.([][]common.Hash) // {txs hashes, uncle hashes, withdrawal hashes} + return bodies, hashsets, nil + } +} + +// fetchReceiptsByHashes is a blocking version of Peer.RequestReceipts +func (d *Downloader) fetchReceiptsByHashes(p *peerConnection, hashes []common.Hash) ([][]*types.Receipt, []common.Hash, error) { + // Create the response sink and send the network request + start := time.Now() + resCh := make(chan *eth.Response) + + req, err := p.peer.RequestReceipts(hashes, resCh) + if err != nil { + return nil, nil, err + } + defer req.Close() + + // Wait until the response arrives, the request is cancelled or times out + ttl := d.peers.rates.TargetTimeout() + + timeoutTimer := time.NewTimer(ttl) + defer timeoutTimer.Stop() + + select { + case <-d.cancelCh: + return nil, nil, errCanceled + + case <-timeoutTimer.C: + // Header retrieval timed out, update the metrics + p.log.Debug("Header request timed out", "elapsed", ttl) + headerTimeoutMeter.Mark(1) + + return nil, nil, errTimeout + + case res := <-resCh: + // Headers successfully retrieved, update the metrics + headerReqTimer.Update(time.Since(start)) + headerInMeter.Mark(int64(len(*res.Res.(*eth.ReceiptsPacket)))) + + // Don't reject the packet even if it turns out to be bad, downloader will + // disconnect the peer on its own terms. Simply delivery the headers to + // be processed by the caller + res.Done <- nil + hashes := res.Meta.([]common.Hash) // {receipt hashes} + return *res.Res.(*eth.ReceiptsPacket), hashes, nil + } +} diff --git a/params/history_segment.go b/params/history_segment.go index 27f75cdcec..baa2fe8b58 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -10,53 +10,6 @@ import ( "github.com/ethereum/go-ethereum/common" ) -const ( - BoundStartBlock uint64 = 31268600 // The starting block height of the first segment, was produced on Aug-29-2023 - HistorySegmentLength uint64 = 2592000 // Assume 1 block for every 3 second, 2,592,000 blocks will be produced in 90 days. -) - -var ( - historySegmentsInBSCMainnet = unmarshalHistorySegments(` -[ - { - "index": 0, - "re_genesis_number": 0, - "re_genesis_hash": "0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b", - "td": 1 - }, - { - "index": 1, - "re_genesis_number": 31268600, - "re_genesis_hash": "0x49bd8a17d31797ced6b466d91900cdd17a4c39cc685dc28ffd290196f417952c", - "td": 62131469, - "consensus_data": "0x7b226e756d626572223a33313236383539392c2268617368223a22307865663261363935356334383638373035623361376439323930313639376265613265303932366238313634386138373838393765386533333639383231306234222c2276616c696461746f7273223a7b22307830626163343932333836383632616433646634623636366263303936623035303562623639346461223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3137362c3139302c3139352c37322c3130342c32362c3234372c3130322c3131372c32382c3138342c35372c38372c3131302c3135362c38312c39302c392c3230302c3139312c3235302c34382c3136342c39382c3135302c3230342c3139372c3130322c31382c37332c31342c3138302c3132382c3230382c35392c3234392c37322c3232352c302c352c3138372c3230342c342c33332c3234392c31312c36312c37385d7d2c22307832343635313736633436316166623331366562633737336336316661656538356136353135646161223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3133382c3134362c35332c3130302c3139382c3235352c3231312c3132372c3137382c3235342c3135392c31372c3134322c3234382c3132382c3134362c3233322c3131382c34342c3132322c3232312c3138312c33382c3137312c3132362c3137372c3233312c3131342c3138362c3233392c3133332c32342c33312c3133372c34342c3131352c32372c3232342c3139332c3133372c32362c38302c3233302c3137362c39382c39382c3230302c32325d7d2c22307832643463343037626265343934333865643835396665393635623134306463663161616237316139223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b3134372c3139332c3234372c3234362c3134362c3135372c33312c3232362c3136312c3132332c37382c32302c39372c37382c3234392c3235322c39312c3232302c3131332c36312c3130322c34392c3231342c3131372c36342c36332c3139302c3233392c3137322c38352c39372c32372c3234362c31382c3131322c31312c32372c3130312c3234342c3131362c37322c39372c3138342c31312c31352c3132352c3130362c3137365d7d2c22307833663334396262616665633135353138313962386265316566656132666334366361373439616131223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3133322c33362c3133382c36392c3134382c3130302c3233382c3139332c3136322c33302c3132372c3139392c3138332c32362c352c36312c3135302c36382c3233332c3138372c3134312c3136342c3133332c35392c3134332c3133352c34342c3231352c3139332c3231342c3137392c33362c3139312c32352c33342c3133302c3135322c34382c3130302c3130382c3233342c3232332c3138322c38382c3231312c3232322c302c3135345d7d2c22307836316464343831613131346132653736316335353462363431373432633937333836373839396433223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3133382c3132382c3135302c3132352c35372c3232382c362c3136302c3136392c3130302c34352c36352c3233332c302c3132322c33392c3235322c31372c38302c3136322c3130332c3230392c36372c3136392c3234372c3133342c3230352c34332c39342c3233362c3138392c3230342c36342c35342c33392c35352c352c33342c39312c3134392c3130392c39342c34372c3134332c39342c3138352c39332c33375d7d2c22307836383562316465643830313337383564363632336363313864323134333230623662623634373539223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3133382c39362c3234382c34322c3132332c3230372c3131362c3138302c3230332c352c35392c3135352c3235342c3133312c3230382c3233372c322c3136382c37382c3138372c31362c3133342c39332c3235332c3231362c3232362c3131302c3131372c35332c3139362c35382c32382c3230342c3231302c3130342c3233322c39362c3234352c322c33332c3130372c35352c3135372c3235322c3135332c3131332c3231312c38385d7d2c22307837306636353731363465356237353638396236346237666431666132373566333334663238653138223a7b22696e6465783a6f6d6974656d707479223a372c22766f74655f61646472657373223a5b3135302c3136322c3130362c3235302c31382c3134392c3231382c3132392c36352c3133332c3134372c3138392c31382c3132392c36382c39392c3231372c3234362c3232382c39322c35342c3136302c3232382c3132362c3138302c3230352c36322c39312c3130362c3234322c3135362c36352c3232362c3136332c3136352c39392c3130302c34382c32312c39302c37302c3131302c33332c3130312c3133332c3137352c35392c3136375d7d2c22307837326236316336303134333432643931343437306563376163323937356265333435373936633262223a7b22696e6465783a6f6d6974656d707479223a382c22766f74655f61646472657373223a5b3132392c3231392c342c33342c3136352c3235332c382c3232382c31332c3137372c3235322c33352c3130342c3231302c33362c39342c37352c32342c3137372c3230382c3138342c39322c3134362c32362c3137302c3137352c3231302c3232372c36352c3131382c31342c34312c3235322c39372c36322c3232312c35372c3234372c31382c38342c39372c37382c33322c38352c3139352c34302c3132322c38315d7d2c22307837616532663562396533383663643162353061343535303639366439353763623439303066303361223a7b22696e6465783a6f6d6974656d707479223a392c22766f74655f61646472657373223a5b3138342c37392c3133312c3235352c34352c3234342c36352c3134372c37332c3130332c3134372c3138342c37312c3234362c37382c3135372c3130392c3137372c3137392c3134392c35342c3133302c3138372c3134392c3233372c3230382c3135302c3233352c33302c3130352c3138372c3231312c38372c3139342c302c3135332c34342c3136372c3132382c38302c3230382c3230332c3232352c3132382c3230372c3137302c312c3134325d7d2c22307838623663386664393364366634636561343262626233343564626336663064666462356265633733223a7b22696e6465783a6f6d6974656d707479223a31302c22766f74655f61646472657373223a5b3136382c3136322c38372c372c37382c3133302c3138342c3132392c3230372c3136302c3131302c3234332c3233352c37382c3235342c3230322c362c31322c33372c34392c35332c3135342c3138392c31342c3137312c3133382c3234312c3232372c3233372c3235302c33322c33372c3235322c3136342c3130302c3137322c3135362c36332c3230392c33352c3234362c3139342c37342c31332c3132302c3133342c3134382c3133335d7d2c22307861366637396236303335396631343164663930613063373435313235623133316361616666643132223a7b22696e6465783a6f6d6974656d707479223a31312c22766f74655f61646472657373223a5b3138332c3131342c3232352c3132382c3235312c3234332c3133382c352c32382c3135312c3231382c3138382c3133382c3137302c312c33382c3136322c35312c3136392c3233322c34302c3230352c3137352c3230342c3131362c33342c3139362c3138372c33312c36342c34382c3136352c3130372c3136332c3130302c3139372c36352c332c3234322c3130372c3137332c3134352c38302c3133392c38322c33322c3138332c36355d7d2c22307862323138633564366166316639373961633432626336386439386135613064373936633661623031223a7b22696e6465783a6f6d6974656d707479223a31322c22766f74655f61646472657373223a5b3138322c38392c3137332c31352c3138392c3135392c38312c38382c3134372c3235332c3231352c36342c3137382c3135352c3136302c3131392c34352c3138392c3233332c3138302c39392c38392c33332c3232312c3134352c3138392c34312c39392c3136302c3235322c3133332c39342c34392c3234362c35312c3134332c36392c3137382c31372c3139362c3233332c3232322c3231392c3132372c34362c3137362c3135372c3233315d7d2c22307862346464363664376332633765353766363238323130313837313932666238396434623939646434223a7b22696e6465783a6f6d6974656d707479223a31332c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307862653830376464646230373436333963643966613631623437363736633036346663353064363263223a7b22696e6465783a6f6d6974656d707479223a31342c22766f74655f61646472657373223a5b3137372c3234322c3139392c32312c3131392c3232322c3234332c32302c37392c3137312c3233352c3131372c3136382c3136312c3230302c3230332c39312c38312c3230392c3230392c3138302c3136302c39342c3233362c3130332c3135322c3133392c3133342c3133332c302c3133392c3137302c32332c36392c3135382c3139362c33372c3231392c3137342c3138382c3133332c34372c37332c3130392c3230312c33332c3135302c3230355d7d2c22307863633865366430306331376562343331333530633663353064386238663035313736623930623131223a7b22696e6465783a6f6d6974656d707479223a31352c22766f74655f61646472657373223a5b3137392c3136332c3231322c3235342c3138342c33372c3137342c3135312c322c3131332c32312c3130322c3232332c39332c3139312c35362c3233322c34322c3232312c37372c3230392c3138312c3131352c3138352c39332c33362c3130322c3235302c3130312c312c3230342c3138342c33302c3135372c33382c3136332c38322c3138352c39372c38302c3230342c3139312c3132332c3130352c3132372c3230382c3136342c32355d7d2c22307863653266643735343465306232636339343639326434613730346465626566376263623631333238223a7b22696e6465783a6f6d6974656d707479223a31362c22766f74655f61646472657373223a5b3138322c37342c3139302c33372c39372c37362c3135362c3235332c35302c3232382c38362c3138302c3231332c33332c3234322c3135362c3133312c38372c3234342c3137352c37302c362c3135312c3133302c3135302c3230312c3139302c3134372c37332c36342c3131342c3137322c352c3235302c3133342c3232372c3231302c3132342c3230302c3231342c3131302c3130312c302c31352c3133392c3136332c36332c3138375d7d2c22307865326433613733396566666364336139393338376430313565323630656566616337326562656131223a7b22696e6465783a6f6d6974656d707479223a31372c22766f74655f61646472657373223a5b3134392c3130382c37312c31332c3232332c3234342c3134302c3138302c3134372c302c33322c31312c39352c3133312c37332c3132372c35382c36302c3230332c35382c3233352c3133312c3139372c3233372c3231372c3132392c3133332c3130352c332c3134322c39372c3230392c3135312c32342c37392c37342c3136362c3134372c3135382c3136352c3233332c3134352c33302c36322c3135322c3137322c3130392c33335d7d2c22307865396165333236316134373561323762623130323866313430626332613763383433333138616664223a7b22696e6465783a6f6d6974656d707479223a31382c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307865613061366533633531316262643130663435313965636533376463323438383765313162353564223a7b22696e6465783a6f6d6974656d707479223a31392c22766f74655f61646472657373223a5b3137382c3231322c3139382c34302c36302c36382c3136312c3139392c3138392c38302c35382c3137312c3136372c3130322c3131302c3135392c31322c3133312c31342c31352c3234302c32322c3139332c3139392c38302c3136352c3232382c3133352c38372c3136372c31392c3230382c3133312c3130372c32382c3137312c3235332c39322c34302c32372c32392c3232372c3138332c3132352c32382c32352c33332c3133315d7d2c22307865653232363337396462383363666663363831343935373330633131666464653739626134633063223a7b22696e6465783a6f6d6974656d707479223a32302c22766f74655f61646472657373223a5b3137342c3132332c3139382c3235302c3136332c3234302c3230342c36322c39362c3134372c3138322c35312c3235332c3132362c3232382c3234382c3130352c3131322c3134362c3130352c38382c3230382c3138332c3233362c3132382c36372c3132372c3134372c3130362c3230372c33332c34332c3132302c3234302c3230352c392c39352c36392c3130312c3235352c3234312c36382c3235332c36392c3134312c33352c35382c39315d7d2c22307865663032373465333138313063396466303266393866616664653066383431663465363661316364223a7b22696e6465783a6f6d6974656d707479223a32312c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d7d2c22726563656e7473223a7b223331323638353839223a22307838623663386664393364366634636561343262626233343564626336663064666462356265633733222c223331323638353930223a22307861366637396236303335396631343164663930613063373435313235623133316361616666643132222c223331323638353931223a22307862323138633564366166316639373961633432626336386439386135613064373936633661623031222c223331323638353932223a22307862346464363664376332633765353766363238323130313837313932666238396434623939646434222c223331323638353933223a22307862653830376464646230373436333963643966613631623437363736633036346663353064363263222c223331323638353934223a22307863633865366430306331376562343331333530633663353064386238663035313736623930623131222c223331323638353935223a22307863653266643735343465306232636339343639326434613730346465626566376263623631333238222c223331323638353936223a22307865326433613733396566666364336139393338376430313565323630656566616337326562656131222c223331323638353937223a22307865396165333236316134373561323762623130323866313430626332613763383433333138616664222c223331323638353938223a22307865613061366533633531316262643130663435313965636533376463323438383765313162353564222c223331323638353939223a22307865653232363337396462383363666663363831343935373330633131666464653739626134633063227d2c22726563656e745f666f726b5f686173686573223a7b223331323638353739223a226231396466346132222c223331323638353830223a226231396466346132222c223331323638353831223a226231396466346132222c223331323638353832223a226231396466346132222c223331323638353833223a226231396466346132222c223331323638353834223a226231396466346132222c223331323638353835223a226231396466346132222c223331323638353836223a226231396466346132222c223331323638353837223a226231396466346132222c223331323638353838223a226231396466346132222c223331323638353839223a226231396466346132222c223331323638353930223a226231396466346132222c223331323638353931223a226231396466346132222c223331323638353932223a226231396466346132222c223331323638353933223a226231396466346132222c223331323638353934223a226231396466346132222c223331323638353935223a226231396466346132222c223331323638353936223a226231396466346132222c223331323638353937223a226231396466346132222c223331323638353938223a226231396466346132222c223331323638353939223a226231396466346132227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33313236383539372c22536f7572636548617368223a22307863653762343062643836353463306339653961653131373063393839666531353138323562356235306163313063313838326539383331366164643362343833222c225461726765744e756d626572223a33313236383539382c2254617267657448617368223a22307837323335343633626530633139623361626461366666653766393035633936613861643632616565393663616239396465613937303531626433346564313366227d7d" - } -]`) - historySegmentsInBSCChapel = unmarshalHistorySegments(` -[ - { - "index": 0, - "re_genesis_number": 0, - "re_genesis_hash": "0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34", - "td": 1 - }, - { - "index": 1, - "re_genesis_number": 31268600, - "re_genesis_hash": "0x5faa1dcf2140c2fbaf9b713c74e34485d38218df6fc1797b19704d7c964d6943", - "td": 62348406, - "consensus_data": "0x7b226e756d626572223a33313236383539392c2268617368223a22307833336138623166303962626164356663623636323565333866353162663936656162313461383937636636366331633731306336366631383039323634353666222c2276616c696461746f7273223a7b22307831323834323134623962396338353534396162336432623937326466306465656636366163326339223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3134322c3133302c3134372c37362c3136392c3131362c3235332c3230352c3135312c3234332c34382c3135372c3233332c3130332c3231312c3230312c3139362c36332c3136372c31372c3136382c3231342c3131352c3137352c39332c3131372c37302c38382c36382c3139312c3133372c3130352c3230302c3230392c3134382c3134312c3134342c35352c37322c3137322c3132332c3133392c32332c33322c3235302c3130302c3232392c31325d7d2c22307833353535326331363730346432313433343766323966613737663737646136643735643763373532223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3138332c36362c3137332c37322c38352c3138362c3232372c34382c36362c3130372c3133302c36322c3131362c34352c3136332c33312c3132392c3130382c3230302c35392c3139332c3130392c3130352c3136392c31392c37352c3232342c3230372c3138302c3136312c3230392c3132362c3139352c37392c32372c39312c35302c3231332c3139342c342c36342c3138342c38332c3130372c33302c3133362c3234302c3234325d7d2c22307839383061373565636431333039656131326661326564383761383734346662666339623836336435223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b3133372c332c3132322c3135342c3230362c35392c38392c312c3130312c3233342c32382c31322c39302c3139392c34332c3234362c302c3138332c3230302c3134302c33302c36372c39352c36352c3134372c34342c31372c35302c3137302c3232352c3139312c3136302c3138372c3130342c3232382c3130372c3135302c3230342c3137372c34342c35322c32312c3232382c3231362c34322c3234372c32332c3231365d7d2c22307861323935396433663935656165356463376437303134346365316237336234303362376562366530223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3138352c3131352c3139342c3231312c3133322c3133352c3232392c3134332c3231342c3232352c36392c37332c32372c31372c302c3132382c3235312c32302c3137322c3134352c39302c342c31372c3235322c3132302c3234312c3135382c392c3136332c3135332c3232312c3233382c31332c33322c3139382c35382c3131372c3231362c3234392c34382c3234312c3130352c36392c36382c3137332c34352c3139322c32375d7d2c22307862373162323134636238383535303038343433363565393563643939343263373237366537666438223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3136322c3131372c31342c3139382c3232312c3233372c36312c3230352c3139342c3234332c38312c3132302c33352c31362c3137362c3233342c3232302c372c3132352c3138312c3135342c3138382c3136302c3234302c3230352c33382c3131392c3131302c34362c3132322c3230332c3135392c35392c3230362c36342c3137372c3235302c38322c33332c3235332c32312c39372c33342c3130382c39382c39392c3230342c39355d7d2c22307866343734636630336363656666323861626336356339636261653539346637323563383065313264223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3135302c3230312c3138342c3130382c35322c302c3232392c34312c3139312c3232352c3133322c352c3131302c33372c3132342c372c3134382c31312c3138322c3130302c39392c3131312c3130342c3135382c3134312c33322c33392c3230302c35322c3130342c33312c3134332c3133352c3133392c3131352c36382c38322c39372c332c37382c3134382c3130372c3137382c3231372c312c3138302c3138342c3132305d7d7d2c22726563656e7473223a7b223331323638353936223a22307862373162323134636238383535303038343433363565393563643939343263373237366537666438222c223331323638353937223a22307866343734636630336363656666323861626336356339636261653539346637323563383065313264222c223331323638353938223a22307831323834323134623962396338353534396162336432623937326466306465656636366163326339222c223331323638353939223a22307833353535326331363730346432313433343766323966613737663737646136643735643763373532227d2c22726563656e745f666f726b5f686173686573223a7b223331323638353934223a226463353539303563222c223331323638353935223a226463353539303563222c223331323638353936223a226463353539303563222c223331323638353937223a226463353539303563222c223331323638353938223a226463353539303563222c223331323638353939223a226463353539303563227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33313236383539372c22536f7572636548617368223a22307832656632326232643862366338616439303233616361336162393431313632616163313530336664666133323664303832333038373933636365346466353939222c225461726765744e756d626572223a33313236383539382c2254617267657448617368223a22307830643166383737333736613335393232616233366331613231346561663038353335663439656135613866336531316532373637326535386665326533666136227d7d" - }, - { - "index": 2, - "re_genesis_number": 33860600, - "re_genesis_hash": "0x4e5acd6301c45368469f3d0b59e3a0551cea55cfabb0d53b38f48bf463786621", - "td": 67529391, - "consensus_data": "0x7b226e756d626572223a33333836303539392c2268617368223a22307835383131616633393632353831303633656636393935346666613832326566616439333631636432336663303965653639666632343162313961336336373364222c2276616c696461746f7273223a7b22307831323834323134623962396338353534396162336432623937326466306465656636366163326339223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3134322c3133302c3134372c37362c3136392c3131362c3235332c3230352c3135312c3234332c34382c3135372c3233332c3130332c3231312c3230312c3139362c36332c3136372c31372c3136382c3231342c3131352c3137352c39332c3131372c37302c38382c36382c3139312c3133372c3130352c3230302c3230392c3134382c3134312c3134342c35352c37322c3137322c3132332c3133392c32332c33322c3235302c3130302c3232392c31325d7d2c22307833353535326331363730346432313433343766323966613737663737646136643735643763373532223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3138332c36362c3137332c37322c38352c3138362c3232372c34382c36362c3130372c3133302c36322c3131362c34352c3136332c33312c3132392c3130382c3230302c35392c3139332c3130392c3130352c3136392c31392c37352c3232342c3230372c3138302c3136312c3230392c3132362c3139352c37392c32372c39312c35302c3231332c3139342c342c36342c3138342c38332c3130372c33302c3133362c3234302c3234325d7d2c22307834373738383338366430656436633734386530336135333136306234623330656433373438636335223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307839383061373565636431333039656131326661326564383761383734346662666339623836336435223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3133372c332c3132322c3135342c3230362c35392c38392c312c3130312c3233342c32382c31322c39302c3139392c34332c3234362c302c3138332c3230302c3134302c33302c36372c39352c36352c3134372c34342c31372c35302c3137302c3232352c3139312c3136302c3138372c3130342c3232382c3130372c3135302c3230342c3137372c34342c35322c32312c3232382c3231362c34322c3234372c32332c3231365d7d2c22307861323935396433663935656165356463376437303134346365316237336234303362376562366530223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3138352c3131352c3139342c3231312c3133322c3133352c3232392c3134332c3231342c3232352c36392c37332c32372c31372c302c3132382c3235312c32302c3137322c3134352c39302c342c31372c3235322c3132302c3234312c3135382c392c3136332c3135332c3232312c3233382c31332c33322c3139382c35382c3131372c3231362c3234392c34382c3234312c3130352c36392c36382c3137332c34352c3139322c32375d7d2c22307862373162323134636238383535303038343433363565393563643939343263373237366537666438223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3136322c3131372c31342c3139382c3232312c3233372c36312c3230352c3139342c3234332c38312c3132302c33352c31362c3137362c3233342c3232302c372c3132352c3138312c3135342c3138382c3136302c3234302c3230352c33382c3131392c3131302c34362c3132322c3230332c3135392c35392c3230362c36342c3137372c3235302c38322c33332c3235332c32312c39372c33342c3130382c39382c39392c3230342c39355d7d2c22307866343734636630336363656666323861626336356339636261653539346637323563383065313264223a7b22696e6465783a6f6d6974656d707479223a372c22766f74655f61646472657373223a5b3135302c3230312c3138342c3130382c35322c302c3232392c34312c3139312c3232352c3133322c352c3131302c33372c3132342c372c3134382c31312c3138322c3130302c39392c3131312c3130342c3135382c3134312c33322c33392c3230302c35322c3130342c33312c3134332c3133352c3133392c3131352c36382c38322c39372c332c37382c3134382c3130372c3137382c3231372c312c3138302c3138342c3132305d7d7d2c22726563656e7473223a7b223333383630353936223a22307831323834323134623962396338353534396162336432623937326466306465656636366163326339222c223333383630353937223a22307833353535326331363730346432313433343766323966613737663737646136643735643763373532222c223333383630353938223a22307834373738383338366430656436633734386530336135333136306234623330656433373438636335222c223333383630353939223a22307839383061373565636431333039656131326661326564383761383734346662666339623836336435227d2c22726563656e745f666f726b5f686173686573223a7b223333383630353933223a226463353539303563222c223333383630353934223a226463353539303563222c223333383630353935223a226463353539303563222c223333383630353936223a226463353539303563222c223333383630353937223a226463353539303563222c223333383630353938223a226463353539303563222c223333383630353939223a226463353539303563227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33333836303539372c22536f7572636548617368223a22307839326661356163363435376339656333383830306130666431633362333861366137373833633432343363306130613435643937343539623263613030363538222c225461726765744e756d626572223a33333836303539382c2254617267657448617368223a22307836356464343461663939336263663737326462393139356666643265646432653965313733366432363162353534386330376264306166376439363334396432227d7d" - } -]`) -) - type HistoryBlock struct { Number uint64 hash common.Hash diff --git a/params/history_segment_config.go b/params/history_segment_config.go new file mode 100644 index 0000000000..69ac3810cf --- /dev/null +++ b/params/history_segment_config.go @@ -0,0 +1,56 @@ +package params + +const ( + BoundStartBlock uint64 = 31268600 // The starting block height of the first segment, was produced on Aug-29-2023 + HistorySegmentLength uint64 = 2592000 // Assume 1 block for every 3 second, 2,592,000 blocks will be produced in 90 days. +) + +var ( + historySegmentsInBSCMainnet = unmarshalHistorySegments(` +[ + { + "index": 0, + "re_genesis_number": 0, + "re_genesis_hash": "0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b", + "td": 1 + }, + { + "index": 1, + "re_genesis_number": 31268600, + "re_genesis_hash": "0x49bd8a17d31797ced6b466d91900cdd17a4c39cc685dc28ffd290196f417952c", + "td": 62131469, + "consensus_data": "0x7b226e756d626572223a33313236383539392c2268617368223a22307865663261363935356334383638373035623361376439323930313639376265613265303932366238313634386138373838393765386533333639383231306234222c2276616c696461746f7273223a7b22307830626163343932333836383632616433646634623636366263303936623035303562623639346461223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3137362c3139302c3139352c37322c3130342c32362c3234372c3130322c3131372c32382c3138342c35372c38372c3131302c3135362c38312c39302c392c3230302c3139312c3235302c34382c3136342c39382c3135302c3230342c3139372c3130322c31382c37332c31342c3138302c3132382c3230382c35392c3234392c37322c3232352c302c352c3138372c3230342c342c33332c3234392c31312c36312c37385d7d2c22307832343635313736633436316166623331366562633737336336316661656538356136353135646161223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3133382c3134362c35332c3130302c3139382c3235352c3231312c3132372c3137382c3235342c3135392c31372c3134322c3234382c3132382c3134362c3233322c3131382c34342c3132322c3232312c3138312c33382c3137312c3132362c3137372c3233312c3131342c3138362c3233392c3133332c32342c33312c3133372c34342c3131352c32372c3232342c3139332c3133372c32362c38302c3233302c3137362c39382c39382c3230302c32325d7d2c22307832643463343037626265343934333865643835396665393635623134306463663161616237316139223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b3134372c3139332c3234372c3234362c3134362c3135372c33312c3232362c3136312c3132332c37382c32302c39372c37382c3234392c3235322c39312c3232302c3131332c36312c3130322c34392c3231342c3131372c36342c36332c3139302c3233392c3137322c38352c39372c32372c3234362c31382c3131322c31312c32372c3130312c3234342c3131362c37322c39372c3138342c31312c31352c3132352c3130362c3137365d7d2c22307833663334396262616665633135353138313962386265316566656132666334366361373439616131223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3133322c33362c3133382c36392c3134382c3130302c3233382c3139332c3136322c33302c3132372c3139392c3138332c32362c352c36312c3135302c36382c3233332c3138372c3134312c3136342c3133332c35392c3134332c3133352c34342c3231352c3139332c3231342c3137392c33362c3139312c32352c33342c3133302c3135322c34382c3130302c3130382c3233342c3232332c3138322c38382c3231312c3232322c302c3135345d7d2c22307836316464343831613131346132653736316335353462363431373432633937333836373839396433223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3133382c3132382c3135302c3132352c35372c3232382c362c3136302c3136392c3130302c34352c36352c3233332c302c3132322c33392c3235322c31372c38302c3136322c3130332c3230392c36372c3136392c3234372c3133342c3230352c34332c39342c3233362c3138392c3230342c36342c35342c33392c35352c352c33342c39312c3134392c3130392c39342c34372c3134332c39342c3138352c39332c33375d7d2c22307836383562316465643830313337383564363632336363313864323134333230623662623634373539223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3133382c39362c3234382c34322c3132332c3230372c3131362c3138302c3230332c352c35392c3135352c3235342c3133312c3230382c3233372c322c3136382c37382c3138372c31362c3133342c39332c3235332c3231362c3232362c3131302c3131372c35332c3139362c35382c32382c3230342c3231302c3130342c3233322c39362c3234352c322c33332c3130372c35352c3135372c3235322c3135332c3131332c3231312c38385d7d2c22307837306636353731363465356237353638396236346237666431666132373566333334663238653138223a7b22696e6465783a6f6d6974656d707479223a372c22766f74655f61646472657373223a5b3135302c3136322c3130362c3235302c31382c3134392c3231382c3132392c36352c3133332c3134372c3138392c31382c3132392c36382c39392c3231372c3234362c3232382c39322c35342c3136302c3232382c3132362c3138302c3230352c36322c39312c3130362c3234322c3135362c36352c3232362c3136332c3136352c39392c3130302c34382c32312c39302c37302c3131302c33332c3130312c3133332c3137352c35392c3136375d7d2c22307837326236316336303134333432643931343437306563376163323937356265333435373936633262223a7b22696e6465783a6f6d6974656d707479223a382c22766f74655f61646472657373223a5b3132392c3231392c342c33342c3136352c3235332c382c3232382c31332c3137372c3235322c33352c3130342c3231302c33362c39342c37352c32342c3137372c3230382c3138342c39322c3134362c32362c3137302c3137352c3231302c3232372c36352c3131382c31342c34312c3235322c39372c36322c3232312c35372c3234372c31382c38342c39372c37382c33322c38352c3139352c34302c3132322c38315d7d2c22307837616532663562396533383663643162353061343535303639366439353763623439303066303361223a7b22696e6465783a6f6d6974656d707479223a392c22766f74655f61646472657373223a5b3138342c37392c3133312c3235352c34352c3234342c36352c3134372c37332c3130332c3134372c3138342c37312c3234362c37382c3135372c3130392c3137372c3137392c3134392c35342c3133302c3138372c3134392c3233372c3230382c3135302c3233352c33302c3130352c3138372c3231312c38372c3139342c302c3135332c34342c3136372c3132382c38302c3230382c3230332c3232352c3132382c3230372c3137302c312c3134325d7d2c22307838623663386664393364366634636561343262626233343564626336663064666462356265633733223a7b22696e6465783a6f6d6974656d707479223a31302c22766f74655f61646472657373223a5b3136382c3136322c38372c372c37382c3133302c3138342c3132392c3230372c3136302c3131302c3234332c3233352c37382c3235342c3230322c362c31322c33372c34392c35332c3135342c3138392c31342c3137312c3133382c3234312c3232372c3233372c3235302c33322c33372c3235322c3136342c3130302c3137322c3135362c36332c3230392c33352c3234362c3139342c37342c31332c3132302c3133342c3134382c3133335d7d2c22307861366637396236303335396631343164663930613063373435313235623133316361616666643132223a7b22696e6465783a6f6d6974656d707479223a31312c22766f74655f61646472657373223a5b3138332c3131342c3232352c3132382c3235312c3234332c3133382c352c32382c3135312c3231382c3138382c3133382c3137302c312c33382c3136322c35312c3136392c3233322c34302c3230352c3137352c3230342c3131362c33342c3139362c3138372c33312c36342c34382c3136352c3130372c3136332c3130302c3139372c36352c332c3234322c3130372c3137332c3134352c38302c3133392c38322c33322c3138332c36355d7d2c22307862323138633564366166316639373961633432626336386439386135613064373936633661623031223a7b22696e6465783a6f6d6974656d707479223a31322c22766f74655f61646472657373223a5b3138322c38392c3137332c31352c3138392c3135392c38312c38382c3134372c3235332c3231352c36342c3137382c3135352c3136302c3131392c34352c3138392c3233332c3138302c39392c38392c33332c3232312c3134352c3138392c34312c39392c3136302c3235322c3133332c39342c34392c3234362c35312c3134332c36392c3137382c31372c3139362c3233332c3232322c3231392c3132372c34362c3137362c3135372c3233315d7d2c22307862346464363664376332633765353766363238323130313837313932666238396434623939646434223a7b22696e6465783a6f6d6974656d707479223a31332c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307862653830376464646230373436333963643966613631623437363736633036346663353064363263223a7b22696e6465783a6f6d6974656d707479223a31342c22766f74655f61646472657373223a5b3137372c3234322c3139392c32312c3131392c3232322c3234332c32302c37392c3137312c3233352c3131372c3136382c3136312c3230302c3230332c39312c38312c3230392c3230392c3138302c3136302c39342c3233362c3130332c3135322c3133392c3133342c3133332c302c3133392c3137302c32332c36392c3135382c3139362c33372c3231392c3137342c3138382c3133332c34372c37332c3130392c3230312c33332c3135302c3230355d7d2c22307863633865366430306331376562343331333530633663353064386238663035313736623930623131223a7b22696e6465783a6f6d6974656d707479223a31352c22766f74655f61646472657373223a5b3137392c3136332c3231322c3235342c3138342c33372c3137342c3135312c322c3131332c32312c3130322c3232332c39332c3139312c35362c3233322c34322c3232312c37372c3230392c3138312c3131352c3138352c39332c33362c3130322c3235302c3130312c312c3230342c3138342c33302c3135372c33382c3136332c38322c3138352c39372c38302c3230342c3139312c3132332c3130352c3132372c3230382c3136342c32355d7d2c22307863653266643735343465306232636339343639326434613730346465626566376263623631333238223a7b22696e6465783a6f6d6974656d707479223a31362c22766f74655f61646472657373223a5b3138322c37342c3139302c33372c39372c37362c3135362c3235332c35302c3232382c38362c3138302c3231332c33332c3234322c3135362c3133312c38372c3234342c3137352c37302c362c3135312c3133302c3135302c3230312c3139302c3134372c37332c36342c3131342c3137322c352c3235302c3133342c3232372c3231302c3132342c3230302c3231342c3131302c3130312c302c31352c3133392c3136332c36332c3138375d7d2c22307865326433613733396566666364336139393338376430313565323630656566616337326562656131223a7b22696e6465783a6f6d6974656d707479223a31372c22766f74655f61646472657373223a5b3134392c3130382c37312c31332c3232332c3234342c3134302c3138302c3134372c302c33322c31312c39352c3133312c37332c3132372c35382c36302c3230332c35382c3233352c3133312c3139372c3233372c3231372c3132392c3133332c3130352c332c3134322c39372c3230392c3135312c32342c37392c37342c3136362c3134372c3135382c3136352c3233332c3134352c33302c36322c3135322c3137322c3130392c33335d7d2c22307865396165333236316134373561323762623130323866313430626332613763383433333138616664223a7b22696e6465783a6f6d6974656d707479223a31382c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307865613061366533633531316262643130663435313965636533376463323438383765313162353564223a7b22696e6465783a6f6d6974656d707479223a31392c22766f74655f61646472657373223a5b3137382c3231322c3139382c34302c36302c36382c3136312c3139392c3138392c38302c35382c3137312c3136372c3130322c3131302c3135392c31322c3133312c31342c31352c3234302c32322c3139332c3139392c38302c3136352c3232382c3133352c38372c3136372c31392c3230382c3133312c3130372c32382c3137312c3235332c39322c34302c32372c32392c3232372c3138332c3132352c32382c32352c33332c3133315d7d2c22307865653232363337396462383363666663363831343935373330633131666464653739626134633063223a7b22696e6465783a6f6d6974656d707479223a32302c22766f74655f61646472657373223a5b3137342c3132332c3139382c3235302c3136332c3234302c3230342c36322c39362c3134372c3138322c35312c3235332c3132362c3232382c3234382c3130352c3131322c3134362c3130352c38382c3230382c3138332c3233362c3132382c36372c3132372c3134372c3130362c3230372c33332c34332c3132302c3234302c3230352c392c39352c36392c3130312c3235352c3234312c36382c3235332c36392c3134312c33352c35382c39315d7d2c22307865663032373465333138313063396466303266393866616664653066383431663465363661316364223a7b22696e6465783a6f6d6974656d707479223a32312c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d7d2c22726563656e7473223a7b223331323638353839223a22307838623663386664393364366634636561343262626233343564626336663064666462356265633733222c223331323638353930223a22307861366637396236303335396631343164663930613063373435313235623133316361616666643132222c223331323638353931223a22307862323138633564366166316639373961633432626336386439386135613064373936633661623031222c223331323638353932223a22307862346464363664376332633765353766363238323130313837313932666238396434623939646434222c223331323638353933223a22307862653830376464646230373436333963643966613631623437363736633036346663353064363263222c223331323638353934223a22307863633865366430306331376562343331333530633663353064386238663035313736623930623131222c223331323638353935223a22307863653266643735343465306232636339343639326434613730346465626566376263623631333238222c223331323638353936223a22307865326433613733396566666364336139393338376430313565323630656566616337326562656131222c223331323638353937223a22307865396165333236316134373561323762623130323866313430626332613763383433333138616664222c223331323638353938223a22307865613061366533633531316262643130663435313965636533376463323438383765313162353564222c223331323638353939223a22307865653232363337396462383363666663363831343935373330633131666464653739626134633063227d2c22726563656e745f666f726b5f686173686573223a7b223331323638353739223a226231396466346132222c223331323638353830223a226231396466346132222c223331323638353831223a226231396466346132222c223331323638353832223a226231396466346132222c223331323638353833223a226231396466346132222c223331323638353834223a226231396466346132222c223331323638353835223a226231396466346132222c223331323638353836223a226231396466346132222c223331323638353837223a226231396466346132222c223331323638353838223a226231396466346132222c223331323638353839223a226231396466346132222c223331323638353930223a226231396466346132222c223331323638353931223a226231396466346132222c223331323638353932223a226231396466346132222c223331323638353933223a226231396466346132222c223331323638353934223a226231396466346132222c223331323638353935223a226231396466346132222c223331323638353936223a226231396466346132222c223331323638353937223a226231396466346132222c223331323638353938223a226231396466346132222c223331323638353939223a226231396466346132227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33313236383539372c22536f7572636548617368223a22307863653762343062643836353463306339653961653131373063393839666531353138323562356235306163313063313838326539383331366164643362343833222c225461726765744e756d626572223a33313236383539382c2254617267657448617368223a22307837323335343633626530633139623361626461366666653766393035633936613861643632616565393663616239396465613937303531626433346564313366227d7d" + }, + { + "index": 2, + "re_genesis_number": 33860600, + "re_genesis_hash": "0xe87f8726d9794e6034c6c16b4f5dd36879e91d60dc275f95800a3db6aa9238c1", + "td": 67274598, + "consensus_data": "0x7b226e756d626572223a33333836303539392c2268617368223a22307830316362653664666663306336363266383537323462346231643137616330623365663231623263626465636334633035623236323464313866343936333338222c2276616c696461746f7273223a7b22307832343635313736633436316166623331366562633737336336316661656538356136353135646161223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3133382c3134362c35332c3130302c3139382c3235352c3231312c3132372c3137382c3235342c3135392c31372c3134322c3234382c3132382c3134362c3233322c3131382c34342c3132322c3232312c3138312c33382c3137312c3132362c3137372c3233312c3131342c3138362c3233392c3133332c32342c33312c3133372c34342c3131352c32372c3232342c3139332c3133372c32362c38302c3233302c3137362c39382c39382c3230302c32325d7d2c22307832393565323634393563656636663639646661363939313164396438653466336262616462383962223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3135312c3132342c3234352c3133302c3134382c3234372c33352c3135372c38312c39342c32312c3137382c37362c3235342c3138342c33362c3134382c352c3130382c3234362c3134352c3233342c3234372c34312c3137372c3130312c3234332c34342c3135312c38372c3139362c34312c3231392c3136352c352c31372c38352c3134342c34382c3130332c3232392c3131302c3139302c35342c3135322c3130332c3134322c3134355d7d2c22307832643463343037626265343934333865643835396665393635623134306463663161616237316139223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b3134372c3139332c3234372c3234362c3134362c3135372c33312c3232362c3136312c3132332c37382c32302c39372c37382c3234392c3235322c39312c3232302c3131332c36312c3130322c34392c3231342c3131372c36342c36332c3139302c3233392c3137322c38352c39372c32372c3234362c31382c3131322c31312c32372c3130312c3234342c3131362c37322c39372c3138342c31312c31352c3132352c3130362c3137365d7d2c22307833663334396262616665633135353138313962386265316566656132666334366361373439616131223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3133322c33362c3133382c36392c3134382c3130302c3233382c3139332c3136322c33302c3132372c3139392c3138332c32362c352c36312c3135302c36382c3233332c3138372c3134312c3136342c3133332c35392c3134332c3133352c34342c3231352c3139332c3231342c3137392c33362c3139312c32352c33342c3133302c3135322c34382c3130302c3130382c3233342c3232332c3138322c38382c3231312c3232322c302c3135345d7d2c22307834343330623332333032393464313263366162326161633563326364363865383062313662353831223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307836383562316465643830313337383564363632336363313864323134333230623662623634373539223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3133382c39362c3234382c34322c3132332c3230372c3131362c3138302c3230332c352c35392c3135352c3235342c3133312c3230382c3233372c322c3136382c37382c3138372c31362c3133342c39332c3235332c3231362c3232362c3131302c3131372c35332c3139362c35382c32382c3230342c3231302c3130342c3233322c39362c3234352c322c33332c3130372c35352c3135372c3235322c3135332c3131332c3231312c38385d7d2c22307837303262653138303430616132613962316166393231393934313436396631613433353835346663223a7b22696e6465783a6f6d6974656d707479223a372c22766f74655f61646472657373223a5b3134312c3231302c392c3132312c3138392c39392c3139332c37372c3234362c32332c3136362c3134372c3135362c35382c35312c37312c3135322c32302c3134352c38312c38372c3132352c3231312c3234312c3235302c3231392c34332c3230392c3139332c3138302c3135302c3139312c3133322c3139342c39322c3133352c3135372c3136352c3234302c3234392c3232332c3231392c3133362c3139382c3232312c32332c3137372c3233305d7d2c22307837616532663562396533383663643162353061343535303639366439353763623439303066303361223a7b22696e6465783a6f6d6974656d707479223a382c22766f74655f61646472657373223a5b3138342c37392c3133312c3235352c34352c3234342c36352c3134372c37332c3130332c3134372c3138342c37312c3234362c37382c3135372c3130392c3137372c3137392c3134392c35342c3133302c3138372c3134392c3233372c3230382c3135302c3233352c33302c3130352c3138372c3231312c38372c3139342c302c3135332c34342c3136372c3132382c38302c3230382c3230332c3232352c3132382c3230372c3137302c312c3134325d7d2c22307838623663386664393364366634636561343262626233343564626336663064666462356265633733223a7b22696e6465783a6f6d6974656d707479223a392c22766f74655f61646472657373223a5b3136382c3136322c38372c372c37382c3133302c3138342c3132392c3230372c3136302c3131302c3234332c3233352c37382c3235342c3230322c362c31322c33372c34392c35332c3135342c3138392c31342c3137312c3133382c3234312c3232372c3233372c3235302c33322c33372c3235322c3136342c3130302c3137322c3135362c36332c3230392c33352c3234362c3139342c37342c31332c3132302c3133342c3134382c3133335d7d2c22307861366637396236303335396631343164663930613063373435313235623133316361616666643132223a7b22696e6465783a6f6d6974656d707479223a31302c22766f74655f61646472657373223a5b3138332c3131342c3232352c3132382c3235312c3234332c3133382c352c32382c3135312c3231382c3138382c3133382c3137302c312c33382c3136322c35312c3136392c3233322c34302c3230352c3137352c3230342c3131362c33342c3139362c3138372c33312c36342c34382c3136352c3130372c3136332c3130302c3139372c36352c332c3234322c3130372c3137332c3134352c38302c3133392c38322c33322c3138332c36355d7d2c22307862323138633564366166316639373961633432626336386439386135613064373936633661623031223a7b22696e6465783a6f6d6974656d707479223a31312c22766f74655f61646472657373223a5b3138322c38392c3137332c31352c3138392c3135392c38312c38382c3134372c3235332c3231352c36342c3137382c3135352c3136302c3131392c34352c3138392c3233332c3138302c39392c38392c33332c3232312c3134352c3138392c34312c39392c3136302c3235322c3133332c39342c34392c3234362c35312c3134332c36392c3137382c31372c3139362c3233332c3232322c3231392c3132372c34362c3137362c3135372c3233315d7d2c22307862346464363664376332633765353766363238323130313837313932666238396434623939646434223a7b22696e6465783a6f6d6974656d707479223a31322c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307862653830376464646230373436333963643966613631623437363736633036346663353064363263223a7b22696e6465783a6f6d6974656d707479223a31332c22766f74655f61646472657373223a5b3137372c3234322c3139392c32312c3131392c3232322c3234332c32302c37392c3137312c3233352c3131372c3136382c3136312c3230302c3230332c39312c38312c3230392c3230392c3138302c3136302c39342c3233362c3130332c3135322c3133392c3133342c3133332c302c3133392c3137302c32332c36392c3135382c3139362c33372c3231392c3137342c3138382c3133332c34372c37332c3130392c3230312c33332c3135302c3230355d7d2c22307863633865366430306331376562343331333530633663353064386238663035313736623930623131223a7b22696e6465783a6f6d6974656d707479223a31342c22766f74655f61646472657373223a5b3137392c3136332c3231322c3235342c3138342c33372c3137342c3135312c322c3131332c32312c3130322c3232332c39332c3139312c35362c3233322c34322c3232312c37372c3230392c3138312c3131352c3138352c39332c33362c3130322c3235302c3130312c312c3230342c3138342c33302c3135372c33382c3136332c38322c3138352c39372c38302c3230342c3139312c3132332c3130352c3132372c3230382c3136342c32355d7d2c22307864316436626637343238323738326230623365623134313363393031643665636630326538653238223a7b22696e6465783a6f6d6974656d707479223a31352c22766f74655f61646472657373223a5b3134372c3135382c3134332c3138302c32372c3130342c33352c3131342c35312c39312c3233322c372c312c3135332c3137332c36322c3133342c33332c3230392c3131362c35392c3230322c3139362c3230342c3135372c3134332c31352c3131302c31362c3234342c33302c38362c37302c31392c3133332c3230302c3233352c39332c3137302c3230302c342c3235342c36332c34332c3230322c3130382c3233312c35375d7d2c22307865326433613733396566666364336139393338376430313565323630656566616337326562656131223a7b22696e6465783a6f6d6974656d707479223a31362c22766f74655f61646472657373223a5b3134392c3130382c37312c31332c3232332c3234342c3134302c3138302c3134372c302c33322c31312c39352c3133312c37332c3132372c35382c36302c3230332c35382c3233352c3133312c3139372c3233372c3231372c3132392c3133332c3130352c332c3134322c39372c3230392c3135312c32342c37392c37342c3136362c3134372c3135382c3136352c3233332c3134352c33302c36322c3135322c3137322c3130392c33335d7d2c22307865396165333236316134373561323762623130323866313430626332613763383433333138616664223a7b22696e6465783a6f6d6974656d707479223a31372c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307865613061366533633531316262643130663435313965636533376463323438383765313162353564223a7b22696e6465783a6f6d6974656d707479223a31382c22766f74655f61646472657373223a5b3137382c3231322c3139382c34302c36302c36382c3136312c3139392c3138392c38302c35382c3137312c3136372c3130322c3131302c3135392c31322c3133312c31342c31352c3234302c32322c3139332c3139392c38302c3136352c3232382c3133352c38372c3136372c31392c3230382c3133312c3130372c32382c3137312c3235332c39322c34302c32372c32392c3232372c3138332c3132352c32382c32352c33332c3133315d7d2c22307865653031633362313238336161303637633538656162343730396638356539396434366465356665223a7b22696e6465783a6f6d6974656d707479223a31392c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307865653232363337396462383363666663363831343935373330633131666464653739626134633063223a7b22696e6465783a6f6d6974656d707479223a32302c22766f74655f61646472657373223a5b3137342c3132332c3139382c3235302c3136332c3234302c3230342c36322c39362c3134372c3138322c35312c3235332c3132362c3232382c3234382c3130352c3131322c3134362c3130352c38382c3230382c3138332c3233362c3132382c36372c3132372c3134372c3130362c3230372c33332c34332c3132302c3234302c3230352c392c39352c36392c3130312c3235352c3234312c36382c3235332c36392c3134312c33352c35382c39315d7d2c22307865663032373465333138313063396466303266393866616664653066383431663465363661316364223a7b22696e6465783a6f6d6974656d707479223a32312c22766f74655f61646472657373223a5b3135322c3230332c3234382c33342c3232382c3138382c34312c3234312c3131322c32362c3139322c35332c31302c36312c342c34342c3230382c3131372c3131302c3135392c3131362c3133302c34342c3130302c3132392c3131392c36302c3233352c302c362c36352c3139372c32372c3133352c31302c3135332c3131312c3232342c3234362c3136382c36382c38312c31312c31362c39372c3234332c3134302c3230385d7d7d2c22726563656e7473223a7b223333383630353839223a22307832343635313736633436316166623331366562633737336336316661656538356136353135646161222c223333383630353930223a22307832393565323634393563656636663639646661363939313164396438653466336262616462383962222c223333383630353931223a22307832643463343037626265343934333865643835396665393635623134306463663161616237316139222c223333383630353932223a22307833663334396262616665633135353138313962386265316566656132666334366361373439616131222c223333383630353933223a22307834343330623332333032393464313263366162326161633563326364363865383062313662353831222c223333383630353934223a22307836383562316465643830313337383564363632336363313864323134333230623662623634373539222c223333383630353935223a22307837303262653138303430616132613962316166393231393934313436396631613433353835346663222c223333383630353936223a22307837616532663562396533383663643162353061343535303639366439353763623439303066303361222c223333383630353937223a22307838623663386664393364366634636561343262626233343564626336663064666462356265633733222c223333383630353938223a22307861366637396236303335396631343164663930613063373435313235623133316361616666643132222c223333383630353939223a22307862323138633564366166316639373961633432626336386439386135613064373936633661623031227d2c22726563656e745f666f726b5f686173686573223a7b223333383630353739223a226231396466346132222c223333383630353830223a226231396466346132222c223333383630353831223a226231396466346132222c223333383630353832223a226231396466346132222c223333383630353833223a226231396466346132222c223333383630353834223a226231396466346132222c223333383630353835223a226231396466346132222c223333383630353836223a226231396466346132222c223333383630353837223a226231396466346132222c223333383630353838223a226231396466346132222c223333383630353839223a226231396466346132222c223333383630353930223a226231396466346132222c223333383630353931223a226231396466346132222c223333383630353932223a226231396466346132222c223333383630353933223a226231396466346132222c223333383630353934223a226231396466346132222c223333383630353935223a226231396466346132222c223333383630353936223a226231396466346132222c223333383630353937223a226231396466346132222c223333383630353938223a226231396466346132222c223333383630353939223a226231396466346132227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33333836303539372c22536f7572636548617368223a22307839663861356634636536613137326330356339633434633937313533663639303565386537356261386364323030393731303237363061663437306639313235222c225461726765744e756d626572223a33333836303539382c2254617267657448617368223a22307833393963343031386438646637323133656361373061303937623531653836613539613631623961396534653962633863323864376338643138306261313661227d7d" + } +]`) + + historySegmentsInBSCChapel = unmarshalHistorySegments(` +[ + { + "index": 0, + "re_genesis_number": 0, + "re_genesis_hash": "0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34", + "td": 1 + }, + { + "index": 1, + "re_genesis_number": 31268600, + "re_genesis_hash": "0x5faa1dcf2140c2fbaf9b713c74e34485d38218df6fc1797b19704d7c964d6943", + "td": 62348406, + "consensus_data": "0x7b226e756d626572223a33313236383539392c2268617368223a22307833336138623166303962626164356663623636323565333866353162663936656162313461383937636636366331633731306336366631383039323634353666222c2276616c696461746f7273223a7b22307831323834323134623962396338353534396162336432623937326466306465656636366163326339223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3134322c3133302c3134372c37362c3136392c3131362c3235332c3230352c3135312c3234332c34382c3135372c3233332c3130332c3231312c3230312c3139362c36332c3136372c31372c3136382c3231342c3131352c3137352c39332c3131372c37302c38382c36382c3139312c3133372c3130352c3230302c3230392c3134382c3134312c3134342c35352c37322c3137322c3132332c3133392c32332c33322c3235302c3130302c3232392c31325d7d2c22307833353535326331363730346432313433343766323966613737663737646136643735643763373532223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3138332c36362c3137332c37322c38352c3138362c3232372c34382c36362c3130372c3133302c36322c3131362c34352c3136332c33312c3132392c3130382c3230302c35392c3139332c3130392c3130352c3136392c31392c37352c3232342c3230372c3138302c3136312c3230392c3132362c3139352c37392c32372c39312c35302c3231332c3139342c342c36342c3138342c38332c3130372c33302c3133362c3234302c3234325d7d2c22307839383061373565636431333039656131326661326564383761383734346662666339623836336435223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b3133372c332c3132322c3135342c3230362c35392c38392c312c3130312c3233342c32382c31322c39302c3139392c34332c3234362c302c3138332c3230302c3134302c33302c36372c39352c36352c3134372c34342c31372c35302c3137302c3232352c3139312c3136302c3138372c3130342c3232382c3130372c3135302c3230342c3137372c34342c35322c32312c3232382c3231362c34322c3234372c32332c3231365d7d2c22307861323935396433663935656165356463376437303134346365316237336234303362376562366530223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3138352c3131352c3139342c3231312c3133322c3133352c3232392c3134332c3231342c3232352c36392c37332c32372c31372c302c3132382c3235312c32302c3137322c3134352c39302c342c31372c3235322c3132302c3234312c3135382c392c3136332c3135332c3232312c3233382c31332c33322c3139382c35382c3131372c3231362c3234392c34382c3234312c3130352c36392c36382c3137332c34352c3139322c32375d7d2c22307862373162323134636238383535303038343433363565393563643939343263373237366537666438223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3136322c3131372c31342c3139382c3232312c3233372c36312c3230352c3139342c3234332c38312c3132302c33352c31362c3137362c3233342c3232302c372c3132352c3138312c3135342c3138382c3136302c3234302c3230352c33382c3131392c3131302c34362c3132322c3230332c3135392c35392c3230362c36342c3137372c3235302c38322c33332c3235332c32312c39372c33342c3130382c39382c39392c3230342c39355d7d2c22307866343734636630336363656666323861626336356339636261653539346637323563383065313264223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3135302c3230312c3138342c3130382c35322c302c3232392c34312c3139312c3232352c3133322c352c3131302c33372c3132342c372c3134382c31312c3138322c3130302c39392c3131312c3130342c3135382c3134312c33322c33392c3230302c35322c3130342c33312c3134332c3133352c3133392c3131352c36382c38322c39372c332c37382c3134382c3130372c3137382c3231372c312c3138302c3138342c3132305d7d7d2c22726563656e7473223a7b223331323638353936223a22307862373162323134636238383535303038343433363565393563643939343263373237366537666438222c223331323638353937223a22307866343734636630336363656666323861626336356339636261653539346637323563383065313264222c223331323638353938223a22307831323834323134623962396338353534396162336432623937326466306465656636366163326339222c223331323638353939223a22307833353535326331363730346432313433343766323966613737663737646136643735643763373532227d2c22726563656e745f666f726b5f686173686573223a7b223331323638353934223a226463353539303563222c223331323638353935223a226463353539303563222c223331323638353936223a226463353539303563222c223331323638353937223a226463353539303563222c223331323638353938223a226463353539303563222c223331323638353939223a226463353539303563227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33313236383539372c22536f7572636548617368223a22307832656632326232643862366338616439303233616361336162393431313632616163313530336664666133323664303832333038373933636365346466353939222c225461726765744e756d626572223a33313236383539382c2254617267657448617368223a22307830643166383737333736613335393232616233366331613231346561663038353335663439656135613866336531316532373637326535386665326533666136227d7d" + }, + { + "index": 2, + "re_genesis_number": 33860600, + "re_genesis_hash": "0x4e5acd6301c45368469f3d0b59e3a0551cea55cfabb0d53b38f48bf463786621", + "td": 67529391, + "consensus_data": "0x7b226e756d626572223a33333836303539392c2268617368223a22307835383131616633393632353831303633656636393935346666613832326566616439333631636432336663303965653639666632343162313961336336373364222c2276616c696461746f7273223a7b22307831323834323134623962396338353534396162336432623937326466306465656636366163326339223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3134322c3133302c3134372c37362c3136392c3131362c3235332c3230352c3135312c3234332c34382c3135372c3233332c3130332c3231312c3230312c3139362c36332c3136372c31372c3136382c3231342c3131352c3137352c39332c3131372c37302c38382c36382c3139312c3133372c3130352c3230302c3230392c3134382c3134312c3134342c35352c37322c3137322c3132332c3133392c32332c33322c3235302c3130302c3232392c31325d7d2c22307833353535326331363730346432313433343766323966613737663737646136643735643763373532223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3138332c36362c3137332c37322c38352c3138362c3232372c34382c36362c3130372c3133302c36322c3131362c34352c3136332c33312c3132392c3130382c3230302c35392c3139332c3130392c3130352c3136392c31392c37352c3232342c3230372c3138302c3136312c3230392c3132362c3139352c37392c32372c39312c35302c3231332c3139342c342c36342c3138342c38332c3130372c33302c3133362c3234302c3234325d7d2c22307834373738383338366430656436633734386530336135333136306234623330656433373438636335223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307839383061373565636431333039656131326661326564383761383734346662666339623836336435223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3133372c332c3132322c3135342c3230362c35392c38392c312c3130312c3233342c32382c31322c39302c3139392c34332c3234362c302c3138332c3230302c3134302c33302c36372c39352c36352c3134372c34342c31372c35302c3137302c3232352c3139312c3136302c3138372c3130342c3232382c3130372c3135302c3230342c3137372c34342c35322c32312c3232382c3231362c34322c3234372c32332c3231365d7d2c22307861323935396433663935656165356463376437303134346365316237336234303362376562366530223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3138352c3131352c3139342c3231312c3133322c3133352c3232392c3134332c3231342c3232352c36392c37332c32372c31372c302c3132382c3235312c32302c3137322c3134352c39302c342c31372c3235322c3132302c3234312c3135382c392c3136332c3135332c3232312c3233382c31332c33322c3139382c35382c3131372c3231362c3234392c34382c3234312c3130352c36392c36382c3137332c34352c3139322c32375d7d2c22307862373162323134636238383535303038343433363565393563643939343263373237366537666438223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3136322c3131372c31342c3139382c3232312c3233372c36312c3230352c3139342c3234332c38312c3132302c33352c31362c3137362c3233342c3232302c372c3132352c3138312c3135342c3138382c3136302c3234302c3230352c33382c3131392c3131302c34362c3132322c3230332c3135392c35392c3230362c36342c3137372c3235302c38322c33332c3235332c32312c39372c33342c3130382c39382c39392c3230342c39355d7d2c22307866343734636630336363656666323861626336356339636261653539346637323563383065313264223a7b22696e6465783a6f6d6974656d707479223a372c22766f74655f61646472657373223a5b3135302c3230312c3138342c3130382c35322c302c3232392c34312c3139312c3232352c3133322c352c3131302c33372c3132342c372c3134382c31312c3138322c3130302c39392c3131312c3130342c3135382c3134312c33322c33392c3230302c35322c3130342c33312c3134332c3133352c3133392c3131352c36382c38322c39372c332c37382c3134382c3130372c3137382c3231372c312c3138302c3138342c3132305d7d7d2c22726563656e7473223a7b223333383630353936223a22307831323834323134623962396338353534396162336432623937326466306465656636366163326339222c223333383630353937223a22307833353535326331363730346432313433343766323966613737663737646136643735643763373532222c223333383630353938223a22307834373738383338366430656436633734386530336135333136306234623330656433373438636335222c223333383630353939223a22307839383061373565636431333039656131326661326564383761383734346662666339623836336435227d2c22726563656e745f666f726b5f686173686573223a7b223333383630353933223a226463353539303563222c223333383630353934223a226463353539303563222c223333383630353935223a226463353539303563222c223333383630353936223a226463353539303563222c223333383630353937223a226463353539303563222c223333383630353938223a226463353539303563222c223333383630353939223a226463353539303563227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33333836303539372c22536f7572636548617368223a22307839326661356163363435376339656333383830306130666431633362333861366137373833633432343363306130613435643937343539623263613030363538222c225461726765744e756d626572223a33333836303539382c2254617267657448617368223a22307836356464343461663939336263663737326462393139356666643265646432653965313733366432363162353534386330376264306166376439363334396432227d7d" + } +]`) +) From ec5a4aa7287f648bd99cd338360ac70fdc6c0a50 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Fri, 22 Dec 2023 16:32:18 +0800 Subject: [PATCH 18/22] historysegment: opt some naming; --- cmd/geth/chaincmd.go | 8 ++++---- consensus/parlia/parlia.go | 16 +++++++--------- core/blockchain_reader.go | 4 ++-- core/rawdb/freezer.go | 2 +- eth/backend.go | 24 ++++++++++++------------ eth/downloader/downloader.go | 28 ++++++++++++++-------------- eth/downloader/fetchers.go | 16 ++++++++-------- params/history_segment.go | 10 +++++----- params/history_segment_test.go | 8 ++++---- 9 files changed, 57 insertions(+), 59 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 2e3bfc9989..c9873a3398 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -862,18 +862,18 @@ func pruneHistorySegments(ctx *cli.Context) error { // get latest 2 segments latestHeader := headerChain.CurrentHeader() curSegment := hsm.CurSegment(latestHeader.Number.Uint64()) - lastSegment, ok := hsm.LastSegment(curSegment) + prevSegment, ok := hsm.PrevSegment(curSegment) if !ok { return fmt.Errorf("there is no enough history to prune, cur: %v", &curSegment) } // check segment if match hard code - if err = rawdb.AvailableHistorySegment(db, curSegment, lastSegment); err != nil { + if err = rawdb.AvailableHistorySegment(db, curSegment, prevSegment); err != nil { return err } - pruneTail := lastSegment.ReGenesisNumber - log.Info("The older history will be pruned", "lastSegment", lastSegment, "curSegment", curSegment, "pruneTail", pruneTail) + pruneTail := prevSegment.ReGenesisNumber + log.Info("The older history will be pruned", "prevSegment", prevSegment, "curSegment", curSegment, "pruneTail", pruneTail) if err = rawdb.PruneTxLookupToTail(db, pruneTail); err != nil { return err } diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 97daf5f69c..9bcdc434a0 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -1767,15 +1767,13 @@ func (p *Parlia) applyTransaction( } actualTx := (*receivedTxs)[0] if !bytes.Equal(p.signer.Hash(actualTx).Bytes(), expectedHash.Bytes()) { - return fmt.Errorf("expected tx hash %v:%v, nonce %d:%d, to %s:%s, value %s:%s, gas %d:%d, gasPrice %s:%s, data %s:%s, dbErr: %v", - expectedHash.String(), actualTx.Hash().String(), - expectedTx.Nonce(), actualTx.Nonce(), - expectedTx.To().String(), actualTx.To().String(), - expectedTx.Value().String(), actualTx.Value().String(), - expectedTx.Gas(), actualTx.Gas(), - expectedTx.GasPrice().String(), actualTx.GasPrice().String(), - hex.EncodeToString(expectedTx.Data()), hex.EncodeToString(actualTx.Data()), - state.Error(), + return fmt.Errorf("expected tx hash %v, get %v, nonce %d, to %s, value %s, gas %d, gasPrice %s, data %s", expectedHash.String(), actualTx.Hash().String(), + expectedTx.Nonce(), + expectedTx.To().String(), + expectedTx.Value().String(), + expectedTx.Gas(), + expectedTx.GasPrice().String(), + hex.EncodeToString(expectedTx.Data()), ) } expectedTx = actualTx diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index a74ee533a1..1bd5fb29d8 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -449,11 +449,11 @@ func (bc *BlockChain) SubscribeFinalizedHeaderEvent(ch chan<- FinalizedHeaderEve return bc.scope.Track(bc.finalizedHeaderFeed.Subscribe(ch)) } -func (bc *BlockChain) LastHistorySegment(num uint64) *params.HistorySegment { +func (bc *BlockChain) PrevHistorySegment(num uint64) *params.HistorySegment { if bc.hsm == nil { return nil } - segment, ok := bc.hsm.LastSegmentByNumber(num) + segment, ok := bc.hsm.PrevSegmentByNumber(num) if !ok { return nil } diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index a55e00d536..7fea36c60a 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -607,7 +607,7 @@ func (f *Freezer) AncientReset(tail, head uint64) error { defer f.writeLock.Unlock() for i := range f.tables { - nt, err := f.tables[i].resetItems(tail, head) + nt, err := f.tables[i].resetItems(tail-f.offset, head-f.offset) if err != nil { return err } diff --git a/eth/backend.go b/eth/backend.go index 7fef1398fd..9986ad52f7 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -212,18 +212,18 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } var ( hsm *params.HistorySegmentManager - lastSegment *params.HistorySegment + prevSegment *params.HistorySegment ) if config.HistorySegmentEnabled { - hsm, lastSegment, err = GetHistorySegmentAndLastSegment(chainDb, genesisHash, config.HistorySegmentCustomFile) + hsm, prevSegment, err = GetHistorySegmentAndPrevSegment(chainDb, genesisHash, config.HistorySegmentCustomFile) if err != nil { return nil, err } if p, ok := eth.engine.(consensus.PoSA); ok { p.SetupHistorySegment(hsm) } - if lastSegment != nil { - eth.bloomIndexer.AddCheckpoint(eth.bloomIndexer.GetSection(lastSegment.ReGenesisNumber), lastSegment.ReGenesisHash) + if prevSegment != nil { + eth.bloomIndexer.AddCheckpoint(eth.bloomIndexer.GetSection(prevSegment.ReGenesisNumber), prevSegment.ReGenesisHash) } } @@ -285,7 +285,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { bcOps = append(bcOps, func(bc *core.BlockChain) (*core.BlockChain, error) { // if enable history segment, try prune ancient data when restart if config.HistorySegmentEnabled { - if err = truncateAncientTail(chainDb, lastSegment); err != nil { + if err = truncateAncientTail(chainDb, prevSegment); err != nil { return nil, err } bc.SetupHistorySegment(hsm) @@ -408,7 +408,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { return eth, nil } -func GetHistorySegmentAndLastSegment(db ethdb.Database, genesisHash common.Hash, CustomPath string) (*params.HistorySegmentManager, *params.HistorySegment, error) { +func GetHistorySegmentAndPrevSegment(db ethdb.Database, genesisHash common.Hash, CustomPath string) (*params.HistorySegmentManager, *params.HistorySegment, error) { td := rawdb.ReadTd(db, genesisHash, 0) hsm, err := params.NewHistorySegmentManager(¶ms.HistorySegmentConfig{ CustomPath: CustomPath, @@ -420,26 +420,26 @@ func GetHistorySegmentAndLastSegment(db ethdb.Database, genesisHash common.Hash, // get latest 2 segments latestHeader := rawdb.ReadHeadHeader(db) - lastSegment, ok := hsm.LastSegmentByNumber(latestHeader.Number.Uint64()) + prevSegment, ok := hsm.PrevSegmentByNumber(latestHeader.Number.Uint64()) if !ok { log.Warn("there is no enough history to prune", "head", latestHeader.Number) return hsm, nil, nil } // check segment if match hard code - if err = rawdb.AvailableHistorySegment(db, lastSegment); err != nil { + if err = rawdb.AvailableHistorySegment(db, prevSegment); err != nil { log.Warn("there is no available history to prune", "head", latestHeader.Number) return hsm, nil, nil } - return hsm, lastSegment, nil + return hsm, prevSegment, nil } -func truncateAncientTail(db ethdb.Database, lastSegment *params.HistorySegment) error { - if lastSegment == nil { +func truncateAncientTail(db ethdb.Database, prevSegment *params.HistorySegment) error { + if prevSegment == nil { return nil } - pruneTail := lastSegment.ReGenesisNumber + pruneTail := prevSegment.ReGenesisNumber start := time.Now() old, err := db.TruncateTail(pruneTail) if err != nil { diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 11e0caea30..46934711c1 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -152,7 +152,7 @@ type Downloader struct { syncLogTime time.Time // Time instance when status was last reported // history segment feature - lastSegment *params.HistorySegment + prevSegment *params.HistorySegment } // LightChain encapsulates functions required to synchronise a light chain. @@ -211,8 +211,8 @@ type BlockChain interface { // with trie nodes. TrieDB() *trie.Database - // LastHistorySegment get last history segment - LastHistorySegment(num uint64) *params.HistorySegment + // PrevHistorySegment get last history segment + PrevHistorySegment(num uint64) *params.HistorySegment // WriteCanonicalBlockAndReceipt just write header into db, it an unsafe interface, just for history segment WriteCanonicalBlockAndReceipt([]*types.Header, []uint64, []*types.Body, [][]*types.Receipt) error @@ -499,10 +499,10 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * // If the remote peer is lagging behind, no need to sync with it, drop the peer. remoteHeight := remoteHeader.Number.Uint64() - // if enable history segment, override lastSegment - lastSegment := d.blockchain.LastHistorySegment(remoteHeight) - if lastSegment != nil { - d.lastSegment = lastSegment + // if enable history segment, override prevSegment + prevSegment := d.blockchain.PrevHistorySegment(remoteHeight) + if prevSegment != nil { + d.prevSegment = prevSegment } var localHeight uint64 @@ -597,7 +597,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * } // if enable history segment, force reset freezer tail - if d.lastSegment != nil && localHeight == 0 { + if d.prevSegment != nil && localHeight == 0 { if err := d.blockchain.FreezerDBReset(origin, origin); err != nil { return err } @@ -846,7 +846,7 @@ func (d *Downloader) findAncestor(p *peerConnection, localHeight uint64, remoteH } // try to find ancestor from history segment - if localHeight == 0 && mode == SnapSync && d.lastSegment != nil { + if localHeight == 0 && mode == SnapSync && d.prevSegment != nil { return d.findAncestorFromHistorySegment(p, remoteHeight) } @@ -1762,11 +1762,11 @@ func (d *Downloader) reportSnapSyncProgress(force bool) { } func (d *Downloader) findAncestorFromHistorySegment(p *peerConnection, remoteHeight uint64) (uint64, error) { - if d.lastSegment == nil || d.lastSegment.ReGenesisNumber == 0 { + if d.prevSegment == nil || d.prevSegment.ReGenesisNumber == 0 { return 0, nil } - expect := d.lastSegment.ReGenesisNumber + expect := d.prevSegment.ReGenesisNumber if expect > remoteHeight { return 0, nil } @@ -1782,7 +1782,7 @@ func (d *Downloader) findAncestorFromHistorySegment(p *peerConnection, remoteHei // check if it matches local previous segment h := hashes[0] n := headers[0].Number.Uint64() - if !d.lastSegment.MatchBlock(h, n) { + if !d.prevSegment.MatchBlock(h, n) { return 0, nil } @@ -1795,10 +1795,10 @@ func (d *Downloader) findAncestorFromHistorySegment(p *peerConnection, remoteHei return 0, err } // just write header, td, because it's snap sync, just sync history is enough - if err = d.blockchain.WriteCanonicalBlockAndReceipt(headers, []uint64{d.lastSegment.TD}, []*types.Body{body}, [][]*types.Receipt{receipts}); err != nil { + if err = d.blockchain.WriteCanonicalBlockAndReceipt(headers, []uint64{d.prevSegment.TD}, []*types.Body{body}, [][]*types.Receipt{receipts}); err != nil { return 0, err } - log.Debug("sync history segment header to local", "number", n, "hash", h, "segment", d.lastSegment) + log.Debug("sync history segment header to local", "number", n, "hash", h, "segment", d.prevSegment) return n, nil } diff --git a/eth/downloader/fetchers.go b/eth/downloader/fetchers.go index 1ce1c22187..596408eb95 100644 --- a/eth/downloader/fetchers.go +++ b/eth/downloader/fetchers.go @@ -138,15 +138,15 @@ func (d *Downloader) fetchBodiesByHashes(p *peerConnection, hashes []common.Hash case <-timeoutTimer.C: // Header retrieval timed out, update the metrics - p.log.Debug("Header request timed out", "elapsed", ttl) - headerTimeoutMeter.Mark(1) + p.log.Debug("Body request timed out", "elapsed", ttl) + bodyTimeoutMeter.Mark(1) return nil, nil, errTimeout case res := <-resCh: // Headers successfully retrieved, update the metrics - headerReqTimer.Update(time.Since(start)) - headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockBodiesPacket)))) + bodyReqTimer.Update(time.Since(start)) + bodyInMeter.Mark(int64(len(*res.Res.(*eth.BlockBodiesPacket)))) // Don't reject the packet even if it turns out to be bad, downloader will // disconnect the peer on its own terms. Simply delivery the headers to @@ -190,15 +190,15 @@ func (d *Downloader) fetchReceiptsByHashes(p *peerConnection, hashes []common.Ha case <-timeoutTimer.C: // Header retrieval timed out, update the metrics - p.log.Debug("Header request timed out", "elapsed", ttl) - headerTimeoutMeter.Mark(1) + p.log.Debug("Receipt request timed out", "elapsed", ttl) + receiptTimeoutMeter.Mark(1) return nil, nil, errTimeout case res := <-resCh: // Headers successfully retrieved, update the metrics - headerReqTimer.Update(time.Since(start)) - headerInMeter.Mark(int64(len(*res.Res.(*eth.ReceiptsPacket)))) + receiptReqTimer.Update(time.Since(start)) + receiptInMeter.Mark(int64(len(*res.Res.(*eth.ReceiptsPacket)))) // Don't reject the packet even if it turns out to be bad, downloader will // disconnect the peer on its own terms. Simply delivery the headers to diff --git a/params/history_segment.go b/params/history_segment.go index baa2fe8b58..b3b1864bb9 100644 --- a/params/history_segment.go +++ b/params/history_segment.go @@ -173,9 +173,9 @@ func (m *HistorySegmentManager) CurSegment(num uint64) *HistorySegment { return &segments[i] } -// LastSegment return the current's last segment, because the latest 2 segments is available, +// PrevSegment return the current's last segment, because the latest 2 segments is available, // so user could keep current & prev segment -func (m *HistorySegmentManager) LastSegment(cur *HistorySegment) (*HistorySegment, bool) { +func (m *HistorySegmentManager) PrevSegment(cur *HistorySegment) (*HistorySegment, bool) { if cur == nil { return nil, false } @@ -186,10 +186,10 @@ func (m *HistorySegmentManager) LastSegment(cur *HistorySegment) (*HistorySegmen return &segments[cur.Index-1], true } -// LastSegmentByNumber return the current's last segment -func (m *HistorySegmentManager) LastSegmentByNumber(num uint64) (*HistorySegment, bool) { +// PrevSegmentByNumber return the current's last segment +func (m *HistorySegmentManager) PrevSegmentByNumber(num uint64) (*HistorySegment, bool) { cur := m.CurSegment(num) - return m.LastSegment(cur) + return m.PrevSegment(cur) } func unmarshalHistorySegments(enc string) []HistorySegment { diff --git a/params/history_segment_test.go b/params/history_segment_test.go index 5d870609da..91ca7fb21f 100644 --- a/params/history_segment_test.go +++ b/params/history_segment_test.go @@ -162,15 +162,15 @@ func TestIndexSegment(t *testing.T) { prev *HistorySegment ok bool ) - _, ok = hsm.LastSegment(&segments[0]) + _, ok = hsm.PrevSegment(&segments[0]) assert.Equal(t, false, ok) - prev, ok = hsm.LastSegment(&segments[1]) + prev, ok = hsm.PrevSegment(&segments[1]) assert.Equal(t, true, ok) assert.Equal(t, &segments[0], prev) - prev, ok = hsm.LastSegment(&segments[2]) + prev, ok = hsm.PrevSegment(&segments[2]) assert.Equal(t, true, ok) assert.Equal(t, &segments[1], prev) - _, ok = hsm.LastSegment(&HistorySegment{ + _, ok = hsm.PrevSegment(&HistorySegment{ Index: uint64(len(segments)), }) assert.Equal(t, false, ok) From 4cf9aebc2d089794f20da6dbcfc5b33f5cc1d9a5 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Tue, 26 Dec 2023 11:20:50 +0800 Subject: [PATCH 19/22] bloombits: support fast forward by history segment; --- core/chain_indexer.go | 34 +++++++++++++++++++++++++++++----- eth/backend.go | 4 +--- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/core/chain_indexer.go b/core/chain_indexer.go index dd1c4a5278..63f164e94f 100644 --- a/core/chain_indexer.go +++ b/core/chain_indexer.go @@ -25,6 +25,8 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" @@ -92,6 +94,8 @@ type ChainIndexer struct { checkpointSections uint64 // Number of sections covered by the checkpoint checkpointHead common.Hash // Section head belonging to the checkpoint + hsm *params.HistorySegmentManager // HistorySegmentManager only produce last 2 segments when enabled + throttling time.Duration // Disk throttling to prevent a heavy upgrade from hogging resources log log.Logger @@ -143,6 +147,14 @@ func (c *ChainIndexer) AddCheckpoint(section uint64, shead common.Hash) { c.setValidSections(section + 1) } +// SetupHistorySegment set HistorySegmentManager for later use +func (c *ChainIndexer) SetupHistorySegment(hsm *params.HistorySegmentManager) { + c.lock.Lock() + defer c.lock.Unlock() + + c.hsm = hsm +} + // Start creates a goroutine to feed chain head events into the indexer for // cascading background processing. Children do not need to be started, they // are notified about new events by their parents. @@ -334,6 +346,10 @@ func (c *ChainIndexer) updateLoop() { if section > 0 { oldHead = c.SectionHead(section - 1) } + // if there is a available history segment, fast-forward to the next section + if c.hsm != nil && section == 0 { + section, oldHead = c.fastForwardByHistorySegment(section, oldHead) + } // Process the newly defined section in the background c.lock.Unlock() newHead, err := c.processSection(section, oldHead) @@ -382,6 +398,19 @@ func (c *ChainIndexer) updateLoop() { } } +func (c *ChainIndexer) fastForwardByHistorySegment(section uint64, oldHead common.Hash) (uint64, common.Hash) { + prevSegment, ok := c.hsm.PrevSegmentByNumber(c.knownSections * c.sectionSize) + if !ok { + return section, oldHead + } + if prevSegment.ReGenesisNumber > 0 && section <= (prevSegment.ReGenesisNumber+1)/c.sectionSize { + section = (prevSegment.ReGenesisNumber+1)/c.sectionSize + 1 + oldHead = rawdb.ReadCanonicalHash(c.chainDb, section*c.sectionSize-1) + c.setSectionHead(section-1, oldHead) + } + return section, oldHead +} + // processSection processes an entire section by calling backend functions while // ensuring the continuity of the passed headers. Since the chain mutex is not // held while processing, the continuity can be broken by a long reorg, in which @@ -521,8 +550,3 @@ func (c *ChainIndexer) removeSectionHead(section uint64) { c.indexDb.Delete(append([]byte("shead"), data[:]...)) } - -// GetSection calculate section from head number -func (c *ChainIndexer) GetSection(head uint64) uint64 { - return (head + 1) / c.sectionSize -} diff --git a/eth/backend.go b/eth/backend.go index 9986ad52f7..b56112711a 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -222,9 +222,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if p, ok := eth.engine.(consensus.PoSA); ok { p.SetupHistorySegment(hsm) } - if prevSegment != nil { - eth.bloomIndexer.AddCheckpoint(eth.bloomIndexer.GetSection(prevSegment.ReGenesisNumber), prevSegment.ReGenesisHash) - } + eth.bloomIndexer.SetupHistorySegment(hsm) } bcVersion := rawdb.ReadDatabaseVersion(chainDb) From 15e4c1d59450ca1539d41438bf9a53a8929ab350 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Wed, 27 Dec 2023 17:45:09 +0800 Subject: [PATCH 20/22] freezer: compatible with pruneancient when restart; --- core/rawdb/freezer.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index 7fea36c60a..f3e0e739d5 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -124,6 +124,13 @@ func NewFreezer(datadir string, namespace string, readonly bool, offset uint64, // Create the tables. for name, disableSnappy := range tables { + // try to recreate idx files when enable prune ancient before + if offset > 0 && readonly { + table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, maxTableSize, disableSnappy, false) + if err == nil { + table.Close() + } + } table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, maxTableSize, disableSnappy, readonly) if err != nil { for _, table := range freezer.tables { From 1ffe19944a192de737a740db66b8cdf5e3c1a165 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Fri, 29 Dec 2023 12:13:14 +0800 Subject: [PATCH 21/22] flags: fix history flag not found issue; --- cmd/utils/flags.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 843c338f7c..42760fa953 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1133,31 +1133,31 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server. Name: "history-segment", Usage: "Enable history segment feature, it will auto prune history segments by hard-code segment hash", Value: false, - Category: flags.HistoryCategory, + Category: flags.BlockHistoryCategory, } HistorySegCustomFlag = &cli.StringFlag{ Name: "history-segment.custom", Usage: "Specific history segments custom definition", Value: "./history_segments.json", - Category: flags.HistoryCategory, + Category: flags.BlockHistoryCategory, } HistorySegOutputFlag = &cli.StringFlag{ Name: "history-segment.output", Usage: "Specific history segments output file", Value: "./history_segments.json", - Category: flags.HistoryCategory, + Category: flags.BlockHistoryCategory, } BoundStartBlockFlag = &cli.Uint64Flag{ Name: "history-segment.boundstart", Usage: "Specific history segments BoundStartBlock, it indicate segment1 start block", Value: params.BoundStartBlock, - Category: flags.HistoryCategory, + Category: flags.BlockHistoryCategory, } HistorySegmentLengthFlag = &cli.Uint64Flag{ Name: "history-segment.segmentlen", Usage: "Specific history segments HistorySegmentLength", Value: params.HistorySegmentLength, - Category: flags.HistoryCategory, + Category: flags.BlockHistoryCategory, } ) From d54b026a3250439132083013b9be5ce73bdea581 Mon Sep 17 00:00:00 2001 From: 0xbundler <124862913+0xbundler@users.noreply.github.com> Date: Thu, 18 Jan 2024 09:36:34 +0800 Subject: [PATCH 22/22] fix: fix some cr comments; --- cmd/geth/chaincmd.go | 12 ++++++++---- cmd/geth/dbcmd.go | 2 +- consensus/parlia/parlia.go | 3 +-- core/headerchain.go | 4 +--- params/history_segment_config.go | 16 +--------------- 5 files changed, 12 insertions(+), 25 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index c9873a3398..598136e033 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -728,8 +728,8 @@ func exportSegment(ctx *cli.Context) error { if _, ok := engine.(consensus.PoSA); !ok { return errors.New("cannot generate history segment because consensus engine is not PoSA") } - if !chainConfig.IsLuban(latest.Number) { - return errors.New("luban hard fork is not enabled , cannot generate history segment") + if !chainConfig.IsPlato(latest.Number) { + return errors.New("plato hard fork is not enabled , cannot generate history segment") } var ( @@ -737,7 +737,7 @@ func exportSegment(ctx *cli.Context) error { historySegmentLength = params.HistorySegmentLength ) switch genesisHash { - case params.BSCGenesisHash, params.ChapelGenesisHash, params.RialtoGenesisHash: + case params.BSCGenesisHash, params.ChapelGenesisHash: boundStartBlock = params.BoundStartBlock historySegmentLength = params.HistorySegmentLength default: @@ -751,6 +751,9 @@ func exportSegment(ctx *cli.Context) error { if boundStartBlock == 0 || historySegmentLength == 0 { return fmt.Errorf("wrong params, boundStartBlock: %v, historySegmentLength: %v", boundStartBlock, historySegmentLength) } + if chainConfig.Parlia != nil && (boundStartBlock%chainConfig.Parlia.Epoch != 0 || historySegmentLength%chainConfig.Parlia.Epoch != 0) { + return fmt.Errorf("please ensure that the parameters is an integer multiple of parlia epoch, boundStartBlock: %v, historySegmentLength: %v", boundStartBlock, historySegmentLength) + } latestNum := latest.Number.Uint64() if latestNum < params.FullImmutabilityThreshold || latestNum < boundStartBlock { @@ -803,7 +806,8 @@ func exportSegment(ctx *cli.Context) error { segment.TD = headerChain.GetTd(segment.ReGenesisHash, segment.ReGenesisNumber).Uint64() // if using posa consensus, just get snapshot as consensus data if p, ok := engine.(consensus.PoSA); ok { - enc, err := p.GetConsensusData(headerChain, ft) + parent := headerChain.GetHeader(ft.ParentHash, ft.Number.Uint64()-1) + enc, err := p.GetConsensusData(headerChain, parent) if err != nil { return err } diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 4a2b930866..24d3d51c19 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -257,7 +257,7 @@ WARNING: This is a low-level operation which may cause database corruption!`, } ancientInspectCmd = &cli.Command{ Action: ancientInspect, - Name: "inspect-ancient", + Name: "inspect-reserved-oldest-blocks", Flags: []cli.Flag{ utils.DataDirFlag, }, diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 9bcdc434a0..526008e8d0 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -1557,8 +1557,7 @@ func (p *Parlia) Close() error { // GetConsensusData load the header's last snapshot for history segment func (p *Parlia) GetConsensusData(chain consensus.ChainHeaderReader, header *types.Header) ([]byte, error) { - number := header.Number.Uint64() - snap, err := p.snapshot(chain, number-1, header.ParentHash, nil) + snap, err := p.snapshot(chain, header.Number.Uint64(), header.Hash(), nil) if err != nil { return nil, err } diff --git a/core/headerchain.go b/core/headerchain.go index dc4211094b..b4d081f16e 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -137,9 +137,7 @@ func (hc *HeaderChain) getFinalizedNumber(header *types.Header) uint64 { // GetFinalizedHeader returns the highest finalized header before the specific block. func (hc *HeaderChain) GetFinalizedHeader(header *types.Header) *types.Header { if p, ok := hc.engine.(consensus.PoSA); ok { - if finalizedHeader := p.GetFinalizedHeader(hc, header); finalizedHeader != nil { - return finalizedHeader - } + return p.GetFinalizedHeader(hc, header) } return nil diff --git a/params/history_segment_config.go b/params/history_segment_config.go index 69ac3810cf..61fb2f6cc1 100644 --- a/params/history_segment_config.go +++ b/params/history_segment_config.go @@ -2,7 +2,7 @@ package params const ( BoundStartBlock uint64 = 31268600 // The starting block height of the first segment, was produced on Aug-29-2023 - HistorySegmentLength uint64 = 2592000 // Assume 1 block for every 3 second, 2,592,000 blocks will be produced in 90 days. + HistorySegmentLength uint64 = 6912000 // Assume 1 block for every 3 second, 6912000 blocks will be produced in 240 days. ) var ( @@ -20,13 +20,6 @@ var ( "re_genesis_hash": "0x49bd8a17d31797ced6b466d91900cdd17a4c39cc685dc28ffd290196f417952c", "td": 62131469, "consensus_data": "0x7b226e756d626572223a33313236383539392c2268617368223a22307865663261363935356334383638373035623361376439323930313639376265613265303932366238313634386138373838393765386533333639383231306234222c2276616c696461746f7273223a7b22307830626163343932333836383632616433646634623636366263303936623035303562623639346461223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3137362c3139302c3139352c37322c3130342c32362c3234372c3130322c3131372c32382c3138342c35372c38372c3131302c3135362c38312c39302c392c3230302c3139312c3235302c34382c3136342c39382c3135302c3230342c3139372c3130322c31382c37332c31342c3138302c3132382c3230382c35392c3234392c37322c3232352c302c352c3138372c3230342c342c33332c3234392c31312c36312c37385d7d2c22307832343635313736633436316166623331366562633737336336316661656538356136353135646161223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3133382c3134362c35332c3130302c3139382c3235352c3231312c3132372c3137382c3235342c3135392c31372c3134322c3234382c3132382c3134362c3233322c3131382c34342c3132322c3232312c3138312c33382c3137312c3132362c3137372c3233312c3131342c3138362c3233392c3133332c32342c33312c3133372c34342c3131352c32372c3232342c3139332c3133372c32362c38302c3233302c3137362c39382c39382c3230302c32325d7d2c22307832643463343037626265343934333865643835396665393635623134306463663161616237316139223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b3134372c3139332c3234372c3234362c3134362c3135372c33312c3232362c3136312c3132332c37382c32302c39372c37382c3234392c3235322c39312c3232302c3131332c36312c3130322c34392c3231342c3131372c36342c36332c3139302c3233392c3137322c38352c39372c32372c3234362c31382c3131322c31312c32372c3130312c3234342c3131362c37322c39372c3138342c31312c31352c3132352c3130362c3137365d7d2c22307833663334396262616665633135353138313962386265316566656132666334366361373439616131223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3133322c33362c3133382c36392c3134382c3130302c3233382c3139332c3136322c33302c3132372c3139392c3138332c32362c352c36312c3135302c36382c3233332c3138372c3134312c3136342c3133332c35392c3134332c3133352c34342c3231352c3139332c3231342c3137392c33362c3139312c32352c33342c3133302c3135322c34382c3130302c3130382c3233342c3232332c3138322c38382c3231312c3232322c302c3135345d7d2c22307836316464343831613131346132653736316335353462363431373432633937333836373839396433223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3133382c3132382c3135302c3132352c35372c3232382c362c3136302c3136392c3130302c34352c36352c3233332c302c3132322c33392c3235322c31372c38302c3136322c3130332c3230392c36372c3136392c3234372c3133342c3230352c34332c39342c3233362c3138392c3230342c36342c35342c33392c35352c352c33342c39312c3134392c3130392c39342c34372c3134332c39342c3138352c39332c33375d7d2c22307836383562316465643830313337383564363632336363313864323134333230623662623634373539223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3133382c39362c3234382c34322c3132332c3230372c3131362c3138302c3230332c352c35392c3135352c3235342c3133312c3230382c3233372c322c3136382c37382c3138372c31362c3133342c39332c3235332c3231362c3232362c3131302c3131372c35332c3139362c35382c32382c3230342c3231302c3130342c3233322c39362c3234352c322c33332c3130372c35352c3135372c3235322c3135332c3131332c3231312c38385d7d2c22307837306636353731363465356237353638396236346237666431666132373566333334663238653138223a7b22696e6465783a6f6d6974656d707479223a372c22766f74655f61646472657373223a5b3135302c3136322c3130362c3235302c31382c3134392c3231382c3132392c36352c3133332c3134372c3138392c31382c3132392c36382c39392c3231372c3234362c3232382c39322c35342c3136302c3232382c3132362c3138302c3230352c36322c39312c3130362c3234322c3135362c36352c3232362c3136332c3136352c39392c3130302c34382c32312c39302c37302c3131302c33332c3130312c3133332c3137352c35392c3136375d7d2c22307837326236316336303134333432643931343437306563376163323937356265333435373936633262223a7b22696e6465783a6f6d6974656d707479223a382c22766f74655f61646472657373223a5b3132392c3231392c342c33342c3136352c3235332c382c3232382c31332c3137372c3235322c33352c3130342c3231302c33362c39342c37352c32342c3137372c3230382c3138342c39322c3134362c32362c3137302c3137352c3231302c3232372c36352c3131382c31342c34312c3235322c39372c36322c3232312c35372c3234372c31382c38342c39372c37382c33322c38352c3139352c34302c3132322c38315d7d2c22307837616532663562396533383663643162353061343535303639366439353763623439303066303361223a7b22696e6465783a6f6d6974656d707479223a392c22766f74655f61646472657373223a5b3138342c37392c3133312c3235352c34352c3234342c36352c3134372c37332c3130332c3134372c3138342c37312c3234362c37382c3135372c3130392c3137372c3137392c3134392c35342c3133302c3138372c3134392c3233372c3230382c3135302c3233352c33302c3130352c3138372c3231312c38372c3139342c302c3135332c34342c3136372c3132382c38302c3230382c3230332c3232352c3132382c3230372c3137302c312c3134325d7d2c22307838623663386664393364366634636561343262626233343564626336663064666462356265633733223a7b22696e6465783a6f6d6974656d707479223a31302c22766f74655f61646472657373223a5b3136382c3136322c38372c372c37382c3133302c3138342c3132392c3230372c3136302c3131302c3234332c3233352c37382c3235342c3230322c362c31322c33372c34392c35332c3135342c3138392c31342c3137312c3133382c3234312c3232372c3233372c3235302c33322c33372c3235322c3136342c3130302c3137322c3135362c36332c3230392c33352c3234362c3139342c37342c31332c3132302c3133342c3134382c3133335d7d2c22307861366637396236303335396631343164663930613063373435313235623133316361616666643132223a7b22696e6465783a6f6d6974656d707479223a31312c22766f74655f61646472657373223a5b3138332c3131342c3232352c3132382c3235312c3234332c3133382c352c32382c3135312c3231382c3138382c3133382c3137302c312c33382c3136322c35312c3136392c3233322c34302c3230352c3137352c3230342c3131362c33342c3139362c3138372c33312c36342c34382c3136352c3130372c3136332c3130302c3139372c36352c332c3234322c3130372c3137332c3134352c38302c3133392c38322c33322c3138332c36355d7d2c22307862323138633564366166316639373961633432626336386439386135613064373936633661623031223a7b22696e6465783a6f6d6974656d707479223a31322c22766f74655f61646472657373223a5b3138322c38392c3137332c31352c3138392c3135392c38312c38382c3134372c3235332c3231352c36342c3137382c3135352c3136302c3131392c34352c3138392c3233332c3138302c39392c38392c33332c3232312c3134352c3138392c34312c39392c3136302c3235322c3133332c39342c34392c3234362c35312c3134332c36392c3137382c31372c3139362c3233332c3232322c3231392c3132372c34362c3137362c3135372c3233315d7d2c22307862346464363664376332633765353766363238323130313837313932666238396434623939646434223a7b22696e6465783a6f6d6974656d707479223a31332c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307862653830376464646230373436333963643966613631623437363736633036346663353064363263223a7b22696e6465783a6f6d6974656d707479223a31342c22766f74655f61646472657373223a5b3137372c3234322c3139392c32312c3131392c3232322c3234332c32302c37392c3137312c3233352c3131372c3136382c3136312c3230302c3230332c39312c38312c3230392c3230392c3138302c3136302c39342c3233362c3130332c3135322c3133392c3133342c3133332c302c3133392c3137302c32332c36392c3135382c3139362c33372c3231392c3137342c3138382c3133332c34372c37332c3130392c3230312c33332c3135302c3230355d7d2c22307863633865366430306331376562343331333530633663353064386238663035313736623930623131223a7b22696e6465783a6f6d6974656d707479223a31352c22766f74655f61646472657373223a5b3137392c3136332c3231322c3235342c3138342c33372c3137342c3135312c322c3131332c32312c3130322c3232332c39332c3139312c35362c3233322c34322c3232312c37372c3230392c3138312c3131352c3138352c39332c33362c3130322c3235302c3130312c312c3230342c3138342c33302c3135372c33382c3136332c38322c3138352c39372c38302c3230342c3139312c3132332c3130352c3132372c3230382c3136342c32355d7d2c22307863653266643735343465306232636339343639326434613730346465626566376263623631333238223a7b22696e6465783a6f6d6974656d707479223a31362c22766f74655f61646472657373223a5b3138322c37342c3139302c33372c39372c37362c3135362c3235332c35302c3232382c38362c3138302c3231332c33332c3234322c3135362c3133312c38372c3234342c3137352c37302c362c3135312c3133302c3135302c3230312c3139302c3134372c37332c36342c3131342c3137322c352c3235302c3133342c3232372c3231302c3132342c3230302c3231342c3131302c3130312c302c31352c3133392c3136332c36332c3138375d7d2c22307865326433613733396566666364336139393338376430313565323630656566616337326562656131223a7b22696e6465783a6f6d6974656d707479223a31372c22766f74655f61646472657373223a5b3134392c3130382c37312c31332c3232332c3234342c3134302c3138302c3134372c302c33322c31312c39352c3133312c37332c3132372c35382c36302c3230332c35382c3233352c3133312c3139372c3233372c3231372c3132392c3133332c3130352c332c3134322c39372c3230392c3135312c32342c37392c37342c3136362c3134372c3135382c3136352c3233332c3134352c33302c36322c3135322c3137322c3130392c33335d7d2c22307865396165333236316134373561323762623130323866313430626332613763383433333138616664223a7b22696e6465783a6f6d6974656d707479223a31382c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307865613061366533633531316262643130663435313965636533376463323438383765313162353564223a7b22696e6465783a6f6d6974656d707479223a31392c22766f74655f61646472657373223a5b3137382c3231322c3139382c34302c36302c36382c3136312c3139392c3138392c38302c35382c3137312c3136372c3130322c3131302c3135392c31322c3133312c31342c31352c3234302c32322c3139332c3139392c38302c3136352c3232382c3133352c38372c3136372c31392c3230382c3133312c3130372c32382c3137312c3235332c39322c34302c32372c32392c3232372c3138332c3132352c32382c32352c33332c3133315d7d2c22307865653232363337396462383363666663363831343935373330633131666464653739626134633063223a7b22696e6465783a6f6d6974656d707479223a32302c22766f74655f61646472657373223a5b3137342c3132332c3139382c3235302c3136332c3234302c3230342c36322c39362c3134372c3138322c35312c3235332c3132362c3232382c3234382c3130352c3131322c3134362c3130352c38382c3230382c3138332c3233362c3132382c36372c3132372c3134372c3130362c3230372c33332c34332c3132302c3234302c3230352c392c39352c36392c3130312c3235352c3234312c36382c3235332c36392c3134312c33352c35382c39315d7d2c22307865663032373465333138313063396466303266393866616664653066383431663465363661316364223a7b22696e6465783a6f6d6974656d707479223a32312c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d7d2c22726563656e7473223a7b223331323638353839223a22307838623663386664393364366634636561343262626233343564626336663064666462356265633733222c223331323638353930223a22307861366637396236303335396631343164663930613063373435313235623133316361616666643132222c223331323638353931223a22307862323138633564366166316639373961633432626336386439386135613064373936633661623031222c223331323638353932223a22307862346464363664376332633765353766363238323130313837313932666238396434623939646434222c223331323638353933223a22307862653830376464646230373436333963643966613631623437363736633036346663353064363263222c223331323638353934223a22307863633865366430306331376562343331333530633663353064386238663035313736623930623131222c223331323638353935223a22307863653266643735343465306232636339343639326434613730346465626566376263623631333238222c223331323638353936223a22307865326433613733396566666364336139393338376430313565323630656566616337326562656131222c223331323638353937223a22307865396165333236316134373561323762623130323866313430626332613763383433333138616664222c223331323638353938223a22307865613061366533633531316262643130663435313965636533376463323438383765313162353564222c223331323638353939223a22307865653232363337396462383363666663363831343935373330633131666464653739626134633063227d2c22726563656e745f666f726b5f686173686573223a7b223331323638353739223a226231396466346132222c223331323638353830223a226231396466346132222c223331323638353831223a226231396466346132222c223331323638353832223a226231396466346132222c223331323638353833223a226231396466346132222c223331323638353834223a226231396466346132222c223331323638353835223a226231396466346132222c223331323638353836223a226231396466346132222c223331323638353837223a226231396466346132222c223331323638353838223a226231396466346132222c223331323638353839223a226231396466346132222c223331323638353930223a226231396466346132222c223331323638353931223a226231396466346132222c223331323638353932223a226231396466346132222c223331323638353933223a226231396466346132222c223331323638353934223a226231396466346132222c223331323638353935223a226231396466346132222c223331323638353936223a226231396466346132222c223331323638353937223a226231396466346132222c223331323638353938223a226231396466346132222c223331323638353939223a226231396466346132227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33313236383539372c22536f7572636548617368223a22307863653762343062643836353463306339653961653131373063393839666531353138323562356235306163313063313838326539383331366164643362343833222c225461726765744e756d626572223a33313236383539382c2254617267657448617368223a22307837323335343633626530633139623361626461366666653766393035633936613861643632616565393663616239396465613937303531626433346564313366227d7d" - }, - { - "index": 2, - "re_genesis_number": 33860600, - "re_genesis_hash": "0xe87f8726d9794e6034c6c16b4f5dd36879e91d60dc275f95800a3db6aa9238c1", - "td": 67274598, - "consensus_data": "0x7b226e756d626572223a33333836303539392c2268617368223a22307830316362653664666663306336363266383537323462346231643137616330623365663231623263626465636334633035623236323464313866343936333338222c2276616c696461746f7273223a7b22307832343635313736633436316166623331366562633737336336316661656538356136353135646161223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3133382c3134362c35332c3130302c3139382c3235352c3231312c3132372c3137382c3235342c3135392c31372c3134322c3234382c3132382c3134362c3233322c3131382c34342c3132322c3232312c3138312c33382c3137312c3132362c3137372c3233312c3131342c3138362c3233392c3133332c32342c33312c3133372c34342c3131352c32372c3232342c3139332c3133372c32362c38302c3233302c3137362c39382c39382c3230302c32325d7d2c22307832393565323634393563656636663639646661363939313164396438653466336262616462383962223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3135312c3132342c3234352c3133302c3134382c3234372c33352c3135372c38312c39342c32312c3137382c37362c3235342c3138342c33362c3134382c352c3130382c3234362c3134352c3233342c3234372c34312c3137372c3130312c3234332c34342c3135312c38372c3139362c34312c3231392c3136352c352c31372c38352c3134342c34382c3130332c3232392c3131302c3139302c35342c3135322c3130332c3134322c3134355d7d2c22307832643463343037626265343934333865643835396665393635623134306463663161616237316139223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b3134372c3139332c3234372c3234362c3134362c3135372c33312c3232362c3136312c3132332c37382c32302c39372c37382c3234392c3235322c39312c3232302c3131332c36312c3130322c34392c3231342c3131372c36342c36332c3139302c3233392c3137322c38352c39372c32372c3234362c31382c3131322c31312c32372c3130312c3234342c3131362c37322c39372c3138342c31312c31352c3132352c3130362c3137365d7d2c22307833663334396262616665633135353138313962386265316566656132666334366361373439616131223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3133322c33362c3133382c36392c3134382c3130302c3233382c3139332c3136322c33302c3132372c3139392c3138332c32362c352c36312c3135302c36382c3233332c3138372c3134312c3136342c3133332c35392c3134332c3133352c34342c3231352c3139332c3231342c3137392c33362c3139312c32352c33342c3133302c3135322c34382c3130302c3130382c3233342c3232332c3138322c38382c3231312c3232322c302c3135345d7d2c22307834343330623332333032393464313263366162326161633563326364363865383062313662353831223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307836383562316465643830313337383564363632336363313864323134333230623662623634373539223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3133382c39362c3234382c34322c3132332c3230372c3131362c3138302c3230332c352c35392c3135352c3235342c3133312c3230382c3233372c322c3136382c37382c3138372c31362c3133342c39332c3235332c3231362c3232362c3131302c3131372c35332c3139362c35382c32382c3230342c3231302c3130342c3233322c39362c3234352c322c33332c3130372c35352c3135372c3235322c3135332c3131332c3231312c38385d7d2c22307837303262653138303430616132613962316166393231393934313436396631613433353835346663223a7b22696e6465783a6f6d6974656d707479223a372c22766f74655f61646472657373223a5b3134312c3231302c392c3132312c3138392c39392c3139332c37372c3234362c32332c3136362c3134372c3135362c35382c35312c37312c3135322c32302c3134352c38312c38372c3132352c3231312c3234312c3235302c3231392c34332c3230392c3139332c3138302c3135302c3139312c3133322c3139342c39322c3133352c3135372c3136352c3234302c3234392c3232332c3231392c3133362c3139382c3232312c32332c3137372c3233305d7d2c22307837616532663562396533383663643162353061343535303639366439353763623439303066303361223a7b22696e6465783a6f6d6974656d707479223a382c22766f74655f61646472657373223a5b3138342c37392c3133312c3235352c34352c3234342c36352c3134372c37332c3130332c3134372c3138342c37312c3234362c37382c3135372c3130392c3137372c3137392c3134392c35342c3133302c3138372c3134392c3233372c3230382c3135302c3233352c33302c3130352c3138372c3231312c38372c3139342c302c3135332c34342c3136372c3132382c38302c3230382c3230332c3232352c3132382c3230372c3137302c312c3134325d7d2c22307838623663386664393364366634636561343262626233343564626336663064666462356265633733223a7b22696e6465783a6f6d6974656d707479223a392c22766f74655f61646472657373223a5b3136382c3136322c38372c372c37382c3133302c3138342c3132392c3230372c3136302c3131302c3234332c3233352c37382c3235342c3230322c362c31322c33372c34392c35332c3135342c3138392c31342c3137312c3133382c3234312c3232372c3233372c3235302c33322c33372c3235322c3136342c3130302c3137322c3135362c36332c3230392c33352c3234362c3139342c37342c31332c3132302c3133342c3134382c3133335d7d2c22307861366637396236303335396631343164663930613063373435313235623133316361616666643132223a7b22696e6465783a6f6d6974656d707479223a31302c22766f74655f61646472657373223a5b3138332c3131342c3232352c3132382c3235312c3234332c3133382c352c32382c3135312c3231382c3138382c3133382c3137302c312c33382c3136322c35312c3136392c3233322c34302c3230352c3137352c3230342c3131362c33342c3139362c3138372c33312c36342c34382c3136352c3130372c3136332c3130302c3139372c36352c332c3234322c3130372c3137332c3134352c38302c3133392c38322c33322c3138332c36355d7d2c22307862323138633564366166316639373961633432626336386439386135613064373936633661623031223a7b22696e6465783a6f6d6974656d707479223a31312c22766f74655f61646472657373223a5b3138322c38392c3137332c31352c3138392c3135392c38312c38382c3134372c3235332c3231352c36342c3137382c3135352c3136302c3131392c34352c3138392c3233332c3138302c39392c38392c33332c3232312c3134352c3138392c34312c39392c3136302c3235322c3133332c39342c34392c3234362c35312c3134332c36392c3137382c31372c3139362c3233332c3232322c3231392c3132372c34362c3137362c3135372c3233315d7d2c22307862346464363664376332633765353766363238323130313837313932666238396434623939646434223a7b22696e6465783a6f6d6974656d707479223a31322c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307862653830376464646230373436333963643966613631623437363736633036346663353064363263223a7b22696e6465783a6f6d6974656d707479223a31332c22766f74655f61646472657373223a5b3137372c3234322c3139392c32312c3131392c3232322c3234332c32302c37392c3137312c3233352c3131372c3136382c3136312c3230302c3230332c39312c38312c3230392c3230392c3138302c3136302c39342c3233362c3130332c3135322c3133392c3133342c3133332c302c3133392c3137302c32332c36392c3135382c3139362c33372c3231392c3137342c3138382c3133332c34372c37332c3130392c3230312c33332c3135302c3230355d7d2c22307863633865366430306331376562343331333530633663353064386238663035313736623930623131223a7b22696e6465783a6f6d6974656d707479223a31342c22766f74655f61646472657373223a5b3137392c3136332c3231322c3235342c3138342c33372c3137342c3135312c322c3131332c32312c3130322c3232332c39332c3139312c35362c3233322c34322c3232312c37372c3230392c3138312c3131352c3138352c39332c33362c3130322c3235302c3130312c312c3230342c3138342c33302c3135372c33382c3136332c38322c3138352c39372c38302c3230342c3139312c3132332c3130352c3132372c3230382c3136342c32355d7d2c22307864316436626637343238323738326230623365623134313363393031643665636630326538653238223a7b22696e6465783a6f6d6974656d707479223a31352c22766f74655f61646472657373223a5b3134372c3135382c3134332c3138302c32372c3130342c33352c3131342c35312c39312c3233322c372c312c3135332c3137332c36322c3133342c33332c3230392c3131362c35392c3230322c3139362c3230342c3135372c3134332c31352c3131302c31362c3234342c33302c38362c37302c31392c3133332c3230302c3233352c39332c3137302c3230302c342c3235342c36332c34332c3230322c3130382c3233312c35375d7d2c22307865326433613733396566666364336139393338376430313565323630656566616337326562656131223a7b22696e6465783a6f6d6974656d707479223a31362c22766f74655f61646472657373223a5b3134392c3130382c37312c31332c3232332c3234342c3134302c3138302c3134372c302c33322c31312c39352c3133312c37332c3132372c35382c36302c3230332c35382c3233352c3133312c3139372c3233372c3231372c3132392c3133332c3130352c332c3134322c39372c3230392c3135312c32342c37392c37342c3136362c3134372c3135382c3136352c3233332c3134352c33302c36322c3135322c3137322c3130392c33335d7d2c22307865396165333236316134373561323762623130323866313430626332613763383433333138616664223a7b22696e6465783a6f6d6974656d707479223a31372c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307865613061366533633531316262643130663435313965636533376463323438383765313162353564223a7b22696e6465783a6f6d6974656d707479223a31382c22766f74655f61646472657373223a5b3137382c3231322c3139382c34302c36302c36382c3136312c3139392c3138392c38302c35382c3137312c3136372c3130322c3131302c3135392c31322c3133312c31342c31352c3234302c32322c3139332c3139392c38302c3136352c3232382c3133352c38372c3136372c31392c3230382c3133312c3130372c32382c3137312c3235332c39322c34302c32372c32392c3232372c3138332c3132352c32382c32352c33332c3133315d7d2c22307865653031633362313238336161303637633538656162343730396638356539396434366465356665223a7b22696e6465783a6f6d6974656d707479223a31392c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307865653232363337396462383363666663363831343935373330633131666464653739626134633063223a7b22696e6465783a6f6d6974656d707479223a32302c22766f74655f61646472657373223a5b3137342c3132332c3139382c3235302c3136332c3234302c3230342c36322c39362c3134372c3138322c35312c3235332c3132362c3232382c3234382c3130352c3131322c3134362c3130352c38382c3230382c3138332c3233362c3132382c36372c3132372c3134372c3130362c3230372c33332c34332c3132302c3234302c3230352c392c39352c36392c3130312c3235352c3234312c36382c3235332c36392c3134312c33352c35382c39315d7d2c22307865663032373465333138313063396466303266393866616664653066383431663465363661316364223a7b22696e6465783a6f6d6974656d707479223a32312c22766f74655f61646472657373223a5b3135322c3230332c3234382c33342c3232382c3138382c34312c3234312c3131322c32362c3139322c35332c31302c36312c342c34342c3230382c3131372c3131302c3135392c3131362c3133302c34342c3130302c3132392c3131392c36302c3233352c302c362c36352c3139372c32372c3133352c31302c3135332c3131312c3232342c3234362c3136382c36382c38312c31312c31362c39372c3234332c3134302c3230385d7d7d2c22726563656e7473223a7b223333383630353839223a22307832343635313736633436316166623331366562633737336336316661656538356136353135646161222c223333383630353930223a22307832393565323634393563656636663639646661363939313164396438653466336262616462383962222c223333383630353931223a22307832643463343037626265343934333865643835396665393635623134306463663161616237316139222c223333383630353932223a22307833663334396262616665633135353138313962386265316566656132666334366361373439616131222c223333383630353933223a22307834343330623332333032393464313263366162326161633563326364363865383062313662353831222c223333383630353934223a22307836383562316465643830313337383564363632336363313864323134333230623662623634373539222c223333383630353935223a22307837303262653138303430616132613962316166393231393934313436396631613433353835346663222c223333383630353936223a22307837616532663562396533383663643162353061343535303639366439353763623439303066303361222c223333383630353937223a22307838623663386664393364366634636561343262626233343564626336663064666462356265633733222c223333383630353938223a22307861366637396236303335396631343164663930613063373435313235623133316361616666643132222c223333383630353939223a22307862323138633564366166316639373961633432626336386439386135613064373936633661623031227d2c22726563656e745f666f726b5f686173686573223a7b223333383630353739223a226231396466346132222c223333383630353830223a226231396466346132222c223333383630353831223a226231396466346132222c223333383630353832223a226231396466346132222c223333383630353833223a226231396466346132222c223333383630353834223a226231396466346132222c223333383630353835223a226231396466346132222c223333383630353836223a226231396466346132222c223333383630353837223a226231396466346132222c223333383630353838223a226231396466346132222c223333383630353839223a226231396466346132222c223333383630353930223a226231396466346132222c223333383630353931223a226231396466346132222c223333383630353932223a226231396466346132222c223333383630353933223a226231396466346132222c223333383630353934223a226231396466346132222c223333383630353935223a226231396466346132222c223333383630353936223a226231396466346132222c223333383630353937223a226231396466346132222c223333383630353938223a226231396466346132222c223333383630353939223a226231396466346132227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33333836303539372c22536f7572636548617368223a22307839663861356634636536613137326330356339633434633937313533663639303565386537356261386364323030393731303237363061663437306639313235222c225461726765744e756d626572223a33333836303539382c2254617267657448617368223a22307833393963343031386438646637323133656361373061303937623531653836613539613631623961396534653962633863323864376338643138306261313661227d7d" } ]`) @@ -44,13 +37,6 @@ var ( "re_genesis_hash": "0x5faa1dcf2140c2fbaf9b713c74e34485d38218df6fc1797b19704d7c964d6943", "td": 62348406, "consensus_data": "0x7b226e756d626572223a33313236383539392c2268617368223a22307833336138623166303962626164356663623636323565333866353162663936656162313461383937636636366331633731306336366631383039323634353666222c2276616c696461746f7273223a7b22307831323834323134623962396338353534396162336432623937326466306465656636366163326339223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3134322c3133302c3134372c37362c3136392c3131362c3235332c3230352c3135312c3234332c34382c3135372c3233332c3130332c3231312c3230312c3139362c36332c3136372c31372c3136382c3231342c3131352c3137352c39332c3131372c37302c38382c36382c3139312c3133372c3130352c3230302c3230392c3134382c3134312c3134342c35352c37322c3137322c3132332c3133392c32332c33322c3235302c3130302c3232392c31325d7d2c22307833353535326331363730346432313433343766323966613737663737646136643735643763373532223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3138332c36362c3137332c37322c38352c3138362c3232372c34382c36362c3130372c3133302c36322c3131362c34352c3136332c33312c3132392c3130382c3230302c35392c3139332c3130392c3130352c3136392c31392c37352c3232342c3230372c3138302c3136312c3230392c3132362c3139352c37392c32372c39312c35302c3231332c3139342c342c36342c3138342c38332c3130372c33302c3133362c3234302c3234325d7d2c22307839383061373565636431333039656131326661326564383761383734346662666339623836336435223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b3133372c332c3132322c3135342c3230362c35392c38392c312c3130312c3233342c32382c31322c39302c3139392c34332c3234362c302c3138332c3230302c3134302c33302c36372c39352c36352c3134372c34342c31372c35302c3137302c3232352c3139312c3136302c3138372c3130342c3232382c3130372c3135302c3230342c3137372c34342c35322c32312c3232382c3231362c34322c3234372c32332c3231365d7d2c22307861323935396433663935656165356463376437303134346365316237336234303362376562366530223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3138352c3131352c3139342c3231312c3133322c3133352c3232392c3134332c3231342c3232352c36392c37332c32372c31372c302c3132382c3235312c32302c3137322c3134352c39302c342c31372c3235322c3132302c3234312c3135382c392c3136332c3135332c3232312c3233382c31332c33322c3139382c35382c3131372c3231362c3234392c34382c3234312c3130352c36392c36382c3137332c34352c3139322c32375d7d2c22307862373162323134636238383535303038343433363565393563643939343263373237366537666438223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3136322c3131372c31342c3139382c3232312c3233372c36312c3230352c3139342c3234332c38312c3132302c33352c31362c3137362c3233342c3232302c372c3132352c3138312c3135342c3138382c3136302c3234302c3230352c33382c3131392c3131302c34362c3132322c3230332c3135392c35392c3230362c36342c3137372c3235302c38322c33332c3235332c32312c39372c33342c3130382c39382c39392c3230342c39355d7d2c22307866343734636630336363656666323861626336356339636261653539346637323563383065313264223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3135302c3230312c3138342c3130382c35322c302c3232392c34312c3139312c3232352c3133322c352c3131302c33372c3132342c372c3134382c31312c3138322c3130302c39392c3131312c3130342c3135382c3134312c33322c33392c3230302c35322c3130342c33312c3134332c3133352c3133392c3131352c36382c38322c39372c332c37382c3134382c3130372c3137382c3231372c312c3138302c3138342c3132305d7d7d2c22726563656e7473223a7b223331323638353936223a22307862373162323134636238383535303038343433363565393563643939343263373237366537666438222c223331323638353937223a22307866343734636630336363656666323861626336356339636261653539346637323563383065313264222c223331323638353938223a22307831323834323134623962396338353534396162336432623937326466306465656636366163326339222c223331323638353939223a22307833353535326331363730346432313433343766323966613737663737646136643735643763373532227d2c22726563656e745f666f726b5f686173686573223a7b223331323638353934223a226463353539303563222c223331323638353935223a226463353539303563222c223331323638353936223a226463353539303563222c223331323638353937223a226463353539303563222c223331323638353938223a226463353539303563222c223331323638353939223a226463353539303563227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33313236383539372c22536f7572636548617368223a22307832656632326232643862366338616439303233616361336162393431313632616163313530336664666133323664303832333038373933636365346466353939222c225461726765744e756d626572223a33313236383539382c2254617267657448617368223a22307830643166383737333736613335393232616233366331613231346561663038353335663439656135613866336531316532373637326535386665326533666136227d7d" - }, - { - "index": 2, - "re_genesis_number": 33860600, - "re_genesis_hash": "0x4e5acd6301c45368469f3d0b59e3a0551cea55cfabb0d53b38f48bf463786621", - "td": 67529391, - "consensus_data": "0x7b226e756d626572223a33333836303539392c2268617368223a22307835383131616633393632353831303633656636393935346666613832326566616439333631636432336663303965653639666632343162313961336336373364222c2276616c696461746f7273223a7b22307831323834323134623962396338353534396162336432623937326466306465656636366163326339223a7b22696e6465783a6f6d6974656d707479223a312c22766f74655f61646472657373223a5b3134322c3133302c3134372c37362c3136392c3131362c3235332c3230352c3135312c3234332c34382c3135372c3233332c3130332c3231312c3230312c3139362c36332c3136372c31372c3136382c3231342c3131352c3137352c39332c3131372c37302c38382c36382c3139312c3133372c3130352c3230302c3230392c3134382c3134312c3134342c35352c37322c3137322c3132332c3133392c32332c33322c3235302c3130302c3232392c31325d7d2c22307833353535326331363730346432313433343766323966613737663737646136643735643763373532223a7b22696e6465783a6f6d6974656d707479223a322c22766f74655f61646472657373223a5b3138332c36362c3137332c37322c38352c3138362c3232372c34382c36362c3130372c3133302c36322c3131362c34352c3136332c33312c3132392c3130382c3230302c35392c3139332c3130392c3130352c3136392c31392c37352c3232342c3230372c3138302c3136312c3230392c3132362c3139352c37392c32372c39312c35302c3231332c3139342c342c36342c3138342c38332c3130372c33302c3133362c3234302c3234325d7d2c22307834373738383338366430656436633734386530336135333136306234623330656433373438636335223a7b22696e6465783a6f6d6974656d707479223a332c22766f74655f61646472657373223a5b302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c305d7d2c22307839383061373565636431333039656131326661326564383761383734346662666339623836336435223a7b22696e6465783a6f6d6974656d707479223a342c22766f74655f61646472657373223a5b3133372c332c3132322c3135342c3230362c35392c38392c312c3130312c3233342c32382c31322c39302c3139392c34332c3234362c302c3138332c3230302c3134302c33302c36372c39352c36352c3134372c34342c31372c35302c3137302c3232352c3139312c3136302c3138372c3130342c3232382c3130372c3135302c3230342c3137372c34342c35322c32312c3232382c3231362c34322c3234372c32332c3231365d7d2c22307861323935396433663935656165356463376437303134346365316237336234303362376562366530223a7b22696e6465783a6f6d6974656d707479223a352c22766f74655f61646472657373223a5b3138352c3131352c3139342c3231312c3133322c3133352c3232392c3134332c3231342c3232352c36392c37332c32372c31372c302c3132382c3235312c32302c3137322c3134352c39302c342c31372c3235322c3132302c3234312c3135382c392c3136332c3135332c3232312c3233382c31332c33322c3139382c35382c3131372c3231362c3234392c34382c3234312c3130352c36392c36382c3137332c34352c3139322c32375d7d2c22307862373162323134636238383535303038343433363565393563643939343263373237366537666438223a7b22696e6465783a6f6d6974656d707479223a362c22766f74655f61646472657373223a5b3136322c3131372c31342c3139382c3232312c3233372c36312c3230352c3139342c3234332c38312c3132302c33352c31362c3137362c3233342c3232302c372c3132352c3138312c3135342c3138382c3136302c3234302c3230352c33382c3131392c3131302c34362c3132322c3230332c3135392c35392c3230362c36342c3137372c3235302c38322c33332c3235332c32312c39372c33342c3130382c39382c39392c3230342c39355d7d2c22307866343734636630336363656666323861626336356339636261653539346637323563383065313264223a7b22696e6465783a6f6d6974656d707479223a372c22766f74655f61646472657373223a5b3135302c3230312c3138342c3130382c35322c302c3232392c34312c3139312c3232352c3133322c352c3131302c33372c3132342c372c3134382c31312c3138322c3130302c39392c3131312c3130342c3135382c3134312c33322c33392c3230302c35322c3130342c33312c3134332c3133352c3133392c3131352c36382c38322c39372c332c37382c3134382c3130372c3137382c3231372c312c3138302c3138342c3132305d7d7d2c22726563656e7473223a7b223333383630353936223a22307831323834323134623962396338353534396162336432623937326466306465656636366163326339222c223333383630353937223a22307833353535326331363730346432313433343766323966613737663737646136643735643763373532222c223333383630353938223a22307834373738383338366430656436633734386530336135333136306234623330656433373438636335222c223333383630353939223a22307839383061373565636431333039656131326661326564383761383734346662666339623836336435227d2c22726563656e745f666f726b5f686173686573223a7b223333383630353933223a226463353539303563222c223333383630353934223a226463353539303563222c223333383630353935223a226463353539303563222c223333383630353936223a226463353539303563222c223333383630353937223a226463353539303563222c223333383630353938223a226463353539303563222c223333383630353939223a226463353539303563227d2c226174746573746174696f6e3a6f6d6974656d707479223a7b22536f757263654e756d626572223a33333836303539372c22536f7572636548617368223a22307839326661356163363435376339656333383830306130666431633362333861366137373833633432343363306130613435643937343539623263613030363538222c225461726765744e756d626572223a33333836303539382c2254617267657448617368223a22307836356464343461663939336263663737326462393139356666643265646432653965313733366432363162353534386330376264306166376439363334396432227d7d" } ]`) )