mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
Merge pull request #1194 from maticnetwork/shivam/temp-master-develop
Merge branch 'master' into develop
This commit is contained in:
commit
b1bb876d0a
35 changed files with 247 additions and 193 deletions
|
|
@ -25,6 +25,7 @@ syncmode = "full"
|
||||||
# json = false
|
# json = false
|
||||||
# backtrace = ""
|
# backtrace = ""
|
||||||
# debug = true
|
# debug = true
|
||||||
|
# enable-block-tracking = false
|
||||||
|
|
||||||
[p2p]
|
[p2p]
|
||||||
# maxpeers = 1
|
# maxpeers = 1
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@
|
||||||
"muirGlacierBlock": 3395000,
|
"muirGlacierBlock": 3395000,
|
||||||
"berlinBlock": 14750000,
|
"berlinBlock": 14750000,
|
||||||
"londonBlock": 23850000,
|
"londonBlock": 23850000,
|
||||||
"shanghaiBlock":50523000,
|
"shanghaiBlock": 50523000,
|
||||||
|
"cancunBlock": 54876000,
|
||||||
"bor": {
|
"bor": {
|
||||||
"jaipurBlock": 23850000,
|
"jaipurBlock": 23850000,
|
||||||
"delhiBlock": 38189056,
|
"delhiBlock": 38189056,
|
||||||
|
|
|
||||||
|
|
@ -33,15 +33,11 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.opentelemetry.io/otel/attribute"
|
|
||||||
"go.opentelemetry.io/otel/trace"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/lru"
|
"github.com/ethereum/go-ethereum/common/lru"
|
||||||
"github.com/ethereum/go-ethereum/common/mclock"
|
"github.com/ethereum/go-ethereum/common/mclock"
|
||||||
"github.com/ethereum/go-ethereum/common/prque"
|
"github.com/ethereum/go-ethereum/common/prque"
|
||||||
"github.com/ethereum/go-ethereum/common/tracing"
|
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/core/blockstm"
|
"github.com/ethereum/go-ethereum/core/blockstm"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
|
@ -1779,77 +1775,34 @@ func (bc *BlockChain) WriteBlockAndSetHead(ctx context.Context, block *types.Blo
|
||||||
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
|
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
|
||||||
// This function expects the chain mutex to be held.
|
// This function expects the chain mutex to be held.
|
||||||
func (bc *BlockChain) writeBlockAndSetHead(ctx context.Context, block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
|
func (bc *BlockChain) writeBlockAndSetHead(ctx context.Context, block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
|
||||||
writeBlockAndSetHeadCtx, span := tracing.StartSpan(ctx, "blockchain.writeBlockAndSetHead")
|
stateSyncLogs, err := bc.writeBlockWithState(block, receipts, logs, state)
|
||||||
defer tracing.EndSpan(span)
|
|
||||||
|
|
||||||
var stateSyncLogs []*types.Log
|
|
||||||
|
|
||||||
tracing.Exec(writeBlockAndSetHeadCtx, "", "blockchain.writeBlockWithState", func(_ context.Context, span trace.Span) {
|
|
||||||
stateSyncLogs, err = bc.writeBlockWithState(block, receipts, logs, state)
|
|
||||||
tracing.SetAttributes(
|
|
||||||
span,
|
|
||||||
attribute.Int("number", int(block.Number().Uint64())),
|
|
||||||
attribute.Bool("error", err != nil),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NonStatTy, err
|
return NonStatTy, err
|
||||||
}
|
}
|
||||||
|
|
||||||
currentBlock := bc.CurrentBlock()
|
currentBlock := bc.CurrentBlock()
|
||||||
|
reorg, err := bc.forker.ReorgNeeded(currentBlock, block.Header())
|
||||||
var reorg bool
|
|
||||||
|
|
||||||
tracing.Exec(writeBlockAndSetHeadCtx, "", "blockchain.ReorgNeeded", func(_ context.Context, span trace.Span) {
|
|
||||||
reorg, err = bc.forker.ReorgNeeded(currentBlock, block.Header())
|
|
||||||
tracing.SetAttributes(
|
|
||||||
span,
|
|
||||||
attribute.Int("number", int(block.Number().Uint64())),
|
|
||||||
attribute.Int("current block", int(currentBlock.Number.Uint64())),
|
|
||||||
attribute.Bool("reorg needed", reorg),
|
|
||||||
attribute.Bool("error", err != nil),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NonStatTy, err
|
return NonStatTy, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tracing.Exec(writeBlockAndSetHeadCtx, "", "blockchain.reorg", func(_ context.Context, span trace.Span) {
|
if reorg {
|
||||||
if reorg {
|
// Reorganise the chain if the parent is not the head block
|
||||||
// Reorganise the chain if the parent is not the head block
|
if block.ParentHash() != currentBlock.Hash() {
|
||||||
if block.ParentHash() != currentBlock.Hash() {
|
if err = bc.reorg(currentBlock, block); err != nil {
|
||||||
if err = bc.reorg(currentBlock, block); err != nil {
|
return NonStatTy, err
|
||||||
status = NonStatTy
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status = CanonStatTy
|
|
||||||
} else {
|
|
||||||
status = SideStatTy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tracing.SetAttributes(
|
status = CanonStatTy
|
||||||
span,
|
} else {
|
||||||
attribute.Int("number", int(block.Number().Uint64())),
|
status = SideStatTy
|
||||||
attribute.Int("current block", int(currentBlock.Number.Uint64())),
|
|
||||||
attribute.Bool("reorg needed", reorg),
|
|
||||||
attribute.Bool("error", err != nil),
|
|
||||||
attribute.String("status", string(status)),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
if status == NonStatTy {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set new head.
|
// Set new head.
|
||||||
if status == CanonStatTy {
|
if status == CanonStatTy {
|
||||||
tracing.Exec(writeBlockAndSetHeadCtx, "", "blockchain.writeHeadBlock", func(_ context.Context, _ trace.Span) {
|
bc.writeHeadBlock(block)
|
||||||
bc.writeHeadBlock(block)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bc.futureBlocks.Remove(block.Hash())
|
bc.futureBlocks.Remove(block.Hash())
|
||||||
|
|
||||||
if status == CanonStatTy {
|
if status == CanonStatTy {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -73,6 +74,7 @@ type stateObject struct {
|
||||||
trie Trie // storage trie, which becomes non-nil on first access
|
trie Trie // storage trie, which becomes non-nil on first access
|
||||||
code Code // contract bytecode, which gets set when code is loaded
|
code Code // contract bytecode, which gets set when code is loaded
|
||||||
|
|
||||||
|
storageMutex sync.Mutex
|
||||||
originStorage Storage // Storage cache of original entries to dedup rewrites
|
originStorage Storage // Storage cache of original entries to dedup rewrites
|
||||||
pendingStorage Storage // Storage entries that need to be flushed to disk, at the end of an entire block
|
pendingStorage Storage // Storage entries that need to be flushed to disk, at the end of an entire block
|
||||||
dirtyStorage Storage // Storage entries that have been modified in the current transaction execution, reset for every transaction
|
dirtyStorage Storage // Storage entries that have been modified in the current transaction execution, reset for every transaction
|
||||||
|
|
@ -175,6 +177,8 @@ func (s *stateObject) GetState(key common.Hash) common.Hash {
|
||||||
|
|
||||||
// GetCommittedState retrieves a value from the committed account storage trie.
|
// GetCommittedState retrieves a value from the committed account storage trie.
|
||||||
func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
|
func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
|
||||||
|
s.storageMutex.Lock()
|
||||||
|
defer s.storageMutex.Unlock()
|
||||||
// If we have a pending write or clean cached, return that
|
// If we have a pending write or clean cached, return that
|
||||||
if value, pending := s.pendingStorage[key]; pending {
|
if value, pending := s.pendingStorage[key]; pending {
|
||||||
return value
|
return value
|
||||||
|
|
@ -183,6 +187,7 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
|
||||||
if value, cached := s.originStorage[key]; cached {
|
if value, cached := s.originStorage[key]; cached {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the object was destructed in *this* block (and potentially resurrected),
|
// If the object was destructed in *this* block (and potentially resurrected),
|
||||||
// the storage has been cleared out, and we should *not* consult the previous
|
// the storage has been cleared out, and we should *not* consult the previous
|
||||||
// database about any storage values. The only possible alternatives are:
|
// database about any storage values. The only possible alternatives are:
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,7 @@ type Block struct {
|
||||||
// inter-peer block relay.
|
// inter-peer block relay.
|
||||||
ReceivedAt time.Time
|
ReceivedAt time.Time
|
||||||
ReceivedFrom interface{}
|
ReceivedFrom interface{}
|
||||||
|
AnnouncedAt *time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// "external" block encoding. used for eth protocol, etc.
|
// "external" block encoding. used for eth protocol, etc.
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,11 @@ devfakeauthor = false # Run miner without validator set authorization
|
||||||
"32000000" = "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68"
|
"32000000" = "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68"
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
vmodule = "" # Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)
|
vmodule = "" # Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)
|
||||||
json = false # Format logs with JSON
|
json = false # Format logs with JSON
|
||||||
backtrace = "" # Request a stack trace at a specific logging statement (e.g. "block.go:271")
|
backtrace = "" # Request a stack trace at a specific logging statement (e.g. "block.go:271")
|
||||||
debug = true # Prepends log messages with call-site location (file and line number) - {requires some effort}
|
debug = true # Prepends log messages with call-site location (file and line number)
|
||||||
|
enable-block-tracking = false # Enables additional logging of information collected while tracking block lifecycle
|
||||||
|
|
||||||
[p2p]
|
[p2p]
|
||||||
maxpeers = 50 # Maximum number of network peers (network disabled if set to 0)
|
maxpeers = 50 # Maximum number of network peers (network disabled if set to 0)
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,8 @@ The ```bor server``` command runs the Bor client.
|
||||||
|
|
||||||
- ```log.debug```: Prepends log messages with call-site location (file and line number) (default: false)
|
- ```log.debug```: Prepends log messages with call-site location (file and line number) (default: false)
|
||||||
|
|
||||||
|
- ```log.enable-block-tracking```: Enables additional logging of information collected while tracking block lifecycle (default: false)
|
||||||
|
|
||||||
- ```log.json```: Format logs with JSON (default: false)
|
- ```log.json```: Format logs with JSON (default: false)
|
||||||
|
|
||||||
- ```vmodule```: Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)
|
- ```vmodule```: Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)
|
||||||
|
|
|
||||||
|
|
@ -280,18 +280,19 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
// Permit the downloader to use the trie cache allowance during fast sync
|
// Permit the downloader to use the trie cache allowance during fast sync
|
||||||
cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit
|
cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit
|
||||||
if eth.handler, err = newHandler(&handlerConfig{
|
if eth.handler, err = newHandler(&handlerConfig{
|
||||||
Database: chainDb,
|
Database: chainDb,
|
||||||
Chain: eth.blockchain,
|
Chain: eth.blockchain,
|
||||||
TxPool: eth.txPool,
|
TxPool: eth.txPool,
|
||||||
Merger: eth.merger,
|
Merger: eth.merger,
|
||||||
Network: config.NetworkId,
|
Network: config.NetworkId,
|
||||||
Sync: config.SyncMode,
|
Sync: config.SyncMode,
|
||||||
BloomCache: uint64(cacheLimit),
|
BloomCache: uint64(cacheLimit),
|
||||||
EventMux: eth.eventMux,
|
EventMux: eth.eventMux,
|
||||||
RequiredBlocks: config.RequiredBlocks,
|
RequiredBlocks: config.RequiredBlocks,
|
||||||
EthAPI: blockChainAPI,
|
EthAPI: blockChainAPI,
|
||||||
checker: checker,
|
checker: checker,
|
||||||
txArrivalWait: eth.p2pServer.TxArrivalWait,
|
txArrivalWait: eth.p2pServer.TxArrivalWait,
|
||||||
|
enableBlockTracking: eth.config.EnableBlockTracking,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,9 @@ type Config struct {
|
||||||
|
|
||||||
// OverrideVerkle (TODO: remove after the fork)
|
// OverrideVerkle (TODO: remove after the fork)
|
||||||
OverrideVerkle *big.Int `toml:",omitempty"`
|
OverrideVerkle *big.Int `toml:",omitempty"`
|
||||||
|
|
||||||
|
// EnableBlockTracking allows logging of information collected while tracking block lifecycle
|
||||||
|
EnableBlockTracking bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateConsensusEngine creates a consensus engine for the given chain configuration.
|
// CreateConsensusEngine creates a consensus engine for the given chain configuration.
|
||||||
|
|
|
||||||
|
|
@ -114,18 +114,20 @@ type blockAnnounce struct {
|
||||||
|
|
||||||
// headerFilterTask represents a batch of headers needing fetcher filtering.
|
// headerFilterTask represents a batch of headers needing fetcher filtering.
|
||||||
type headerFilterTask struct {
|
type headerFilterTask struct {
|
||||||
peer string // The source peer of block headers
|
peer string // The source peer of block headers
|
||||||
headers []*types.Header // Collection of headers to filter
|
headers []*types.Header // Collection of headers to filter
|
||||||
time time.Time // Arrival time of the headers
|
time time.Time // Arrival time of the headers
|
||||||
|
announcedTime time.Time // Announcement time of the availability of the block
|
||||||
}
|
}
|
||||||
|
|
||||||
// bodyFilterTask represents a batch of block bodies (transactions and uncles)
|
// bodyFilterTask represents a batch of block bodies (transactions and uncles)
|
||||||
// needing fetcher filtering.
|
// needing fetcher filtering.
|
||||||
type bodyFilterTask struct {
|
type bodyFilterTask struct {
|
||||||
peer string // The source peer of block bodies
|
peer string // The source peer of block bodies
|
||||||
transactions [][]*types.Transaction // Collection of transactions per block bodies
|
transactions [][]*types.Transaction // Collection of transactions per block bodies
|
||||||
uncles [][]*types.Header // Collection of uncles per block bodies
|
uncles [][]*types.Header // Collection of uncles per block bodies
|
||||||
time time.Time // Arrival time of the blocks' contents
|
time time.Time // Arrival time of the blocks' contents
|
||||||
|
announcedTime time.Time // Announcement time of the availability of the block
|
||||||
}
|
}
|
||||||
|
|
||||||
// blockOrHeaderInject represents a schedules import operation.
|
// blockOrHeaderInject represents a schedules import operation.
|
||||||
|
|
@ -197,34 +199,38 @@ type BlockFetcher struct {
|
||||||
fetchingHook func([]common.Hash) // Method to call upon starting a block (eth/61) or header (eth/62) fetch
|
fetchingHook func([]common.Hash) // Method to call upon starting a block (eth/61) or header (eth/62) fetch
|
||||||
completingHook func([]common.Hash) // Method to call upon starting a block body fetch (eth/62)
|
completingHook func([]common.Hash) // Method to call upon starting a block body fetch (eth/62)
|
||||||
importedHook func(*types.Header, *types.Block) // Method to call upon successful header or block import (both eth/61 and eth/62)
|
importedHook func(*types.Header, *types.Block) // Method to call upon successful header or block import (both eth/61 and eth/62)
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
enableBlockTracking bool // Whether to log information collected while tracking block lifecycle
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockFetcher creates a block fetcher to retrieve blocks based on hash announcements.
|
// NewBlockFetcher creates a block fetcher to retrieve blocks based on hash announcements.
|
||||||
func NewBlockFetcher(light bool, getHeader HeaderRetrievalFn, getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertHeaders headersInsertFn, insertChain chainInsertFn, dropPeer peerDropFn) *BlockFetcher {
|
func NewBlockFetcher(light bool, getHeader HeaderRetrievalFn, getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertHeaders headersInsertFn, insertChain chainInsertFn, dropPeer peerDropFn, enableBlockTracking bool) *BlockFetcher {
|
||||||
return &BlockFetcher{
|
return &BlockFetcher{
|
||||||
light: light,
|
light: light,
|
||||||
notify: make(chan *blockAnnounce),
|
notify: make(chan *blockAnnounce),
|
||||||
inject: make(chan *blockOrHeaderInject),
|
inject: make(chan *blockOrHeaderInject),
|
||||||
headerFilter: make(chan chan *headerFilterTask),
|
headerFilter: make(chan chan *headerFilterTask),
|
||||||
bodyFilter: make(chan chan *bodyFilterTask),
|
bodyFilter: make(chan chan *bodyFilterTask),
|
||||||
done: make(chan common.Hash),
|
done: make(chan common.Hash),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
announces: make(map[string]int),
|
announces: make(map[string]int),
|
||||||
announced: make(map[common.Hash][]*blockAnnounce),
|
announced: make(map[common.Hash][]*blockAnnounce),
|
||||||
fetching: make(map[common.Hash]*blockAnnounce),
|
fetching: make(map[common.Hash]*blockAnnounce),
|
||||||
fetched: make(map[common.Hash][]*blockAnnounce),
|
fetched: make(map[common.Hash][]*blockAnnounce),
|
||||||
completing: make(map[common.Hash]*blockAnnounce),
|
completing: make(map[common.Hash]*blockAnnounce),
|
||||||
queue: prque.New[int64, *blockOrHeaderInject](nil),
|
queue: prque.New[int64, *blockOrHeaderInject](nil),
|
||||||
queues: make(map[string]int),
|
queues: make(map[string]int),
|
||||||
queued: make(map[common.Hash]*blockOrHeaderInject),
|
queued: make(map[common.Hash]*blockOrHeaderInject),
|
||||||
getHeader: getHeader,
|
getHeader: getHeader,
|
||||||
getBlock: getBlock,
|
getBlock: getBlock,
|
||||||
verifyHeader: verifyHeader,
|
verifyHeader: verifyHeader,
|
||||||
broadcastBlock: broadcastBlock,
|
broadcastBlock: broadcastBlock,
|
||||||
chainHeight: chainHeight,
|
chainHeight: chainHeight,
|
||||||
insertHeaders: insertHeaders,
|
insertHeaders: insertHeaders,
|
||||||
insertChain: insertChain,
|
insertChain: insertChain,
|
||||||
dropPeer: dropPeer,
|
dropPeer: dropPeer,
|
||||||
|
enableBlockTracking: enableBlockTracking,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,7 +282,7 @@ func (f *BlockFetcher) Enqueue(peer string, block *types.Block) error {
|
||||||
|
|
||||||
// FilterHeaders extracts all the headers that were explicitly requested by the fetcher,
|
// FilterHeaders extracts all the headers that were explicitly requested by the fetcher,
|
||||||
// returning those that should be handled differently.
|
// returning those that should be handled differently.
|
||||||
func (f *BlockFetcher) FilterHeaders(peer string, headers []*types.Header, time time.Time) []*types.Header {
|
func (f *BlockFetcher) FilterHeaders(peer string, headers []*types.Header, time time.Time, announcedAt time.Time) []*types.Header {
|
||||||
log.Trace("Filtering headers", "peer", peer, "headers", len(headers))
|
log.Trace("Filtering headers", "peer", peer, "headers", len(headers))
|
||||||
|
|
||||||
// Send the filter channel to the fetcher
|
// Send the filter channel to the fetcher
|
||||||
|
|
@ -289,7 +295,7 @@ func (f *BlockFetcher) FilterHeaders(peer string, headers []*types.Header, time
|
||||||
}
|
}
|
||||||
// Request the filtering of the header list
|
// Request the filtering of the header list
|
||||||
select {
|
select {
|
||||||
case filter <- &headerFilterTask{peer: peer, headers: headers, time: time}:
|
case filter <- &headerFilterTask{peer: peer, headers: headers, time: time, announcedTime: announcedAt}:
|
||||||
case <-f.quit:
|
case <-f.quit:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -304,7 +310,7 @@ func (f *BlockFetcher) FilterHeaders(peer string, headers []*types.Header, time
|
||||||
|
|
||||||
// FilterBodies extracts all the block bodies that were explicitly requested by
|
// FilterBodies extracts all the block bodies that were explicitly requested by
|
||||||
// the fetcher, returning those that should be handled differently.
|
// the fetcher, returning those that should be handled differently.
|
||||||
func (f *BlockFetcher) FilterBodies(peer string, transactions [][]*types.Transaction, uncles [][]*types.Header, time time.Time) ([][]*types.Transaction, [][]*types.Header) {
|
func (f *BlockFetcher) FilterBodies(peer string, transactions [][]*types.Transaction, uncles [][]*types.Header, time time.Time, announcedAt time.Time) ([][]*types.Transaction, [][]*types.Header) {
|
||||||
log.Trace("Filtering bodies", "peer", peer, "txs", len(transactions), "uncles", len(uncles))
|
log.Trace("Filtering bodies", "peer", peer, "txs", len(transactions), "uncles", len(uncles))
|
||||||
|
|
||||||
// Send the filter channel to the fetcher
|
// Send the filter channel to the fetcher
|
||||||
|
|
@ -317,7 +323,7 @@ func (f *BlockFetcher) FilterBodies(peer string, transactions [][]*types.Transac
|
||||||
}
|
}
|
||||||
// Request the filtering of the body list
|
// Request the filtering of the body list
|
||||||
select {
|
select {
|
||||||
case filter <- &bodyFilterTask{peer: peer, transactions: transactions, uncles: uncles, time: time}:
|
case filter <- &bodyFilterTask{peer: peer, transactions: transactions, uncles: uncles, time: time, announcedTime: announcedAt}:
|
||||||
case <-f.quit:
|
case <-f.quit:
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
@ -480,7 +486,7 @@ func (f *BlockFetcher) loop() {
|
||||||
log.Trace("Fetching scheduled headers", "peer", peer, "list", hashes)
|
log.Trace("Fetching scheduled headers", "peer", peer, "list", hashes)
|
||||||
|
|
||||||
// Create a closure of the fetch and schedule in on a new thread
|
// Create a closure of the fetch and schedule in on a new thread
|
||||||
fetchHeader, hashes := f.fetching[hashes[0]].fetchHeader, hashes
|
fetchHeader, hashes, announcedAt := f.fetching[hashes[0]].fetchHeader, hashes, f.fetching[hashes[0]].time
|
||||||
go func(peer string) {
|
go func(peer string) {
|
||||||
if f.fetchingHook != nil {
|
if f.fetchingHook != nil {
|
||||||
f.fetchingHook(hashes)
|
f.fetchingHook(hashes)
|
||||||
|
|
@ -504,7 +510,7 @@ func (f *BlockFetcher) loop() {
|
||||||
select {
|
select {
|
||||||
case res := <-resCh:
|
case res := <-resCh:
|
||||||
res.Done <- nil
|
res.Done <- nil
|
||||||
f.FilterHeaders(peer, *res.Res.(*eth.BlockHeadersRequest), time.Now().Add(res.Time))
|
f.FilterHeaders(peer, *res.Res.(*eth.BlockHeadersRequest), time.Now(), announcedAt)
|
||||||
|
|
||||||
case <-timeout.C:
|
case <-timeout.C:
|
||||||
// The peer didn't respond in time. The request
|
// The peer didn't respond in time. The request
|
||||||
|
|
@ -547,6 +553,7 @@ func (f *BlockFetcher) loop() {
|
||||||
|
|
||||||
fetchBodies := f.completing[hashes[0]].fetchBodies
|
fetchBodies := f.completing[hashes[0]].fetchBodies
|
||||||
bodyFetchMeter.Mark(int64(len(hashes)))
|
bodyFetchMeter.Mark(int64(len(hashes)))
|
||||||
|
announcedAt := f.completing[hashes[0]].time
|
||||||
|
|
||||||
go func(peer string, hashes []common.Hash) {
|
go func(peer string, hashes []common.Hash) {
|
||||||
resCh := make(chan *eth.Response)
|
resCh := make(chan *eth.Response)
|
||||||
|
|
@ -565,7 +572,7 @@ func (f *BlockFetcher) loop() {
|
||||||
res.Done <- nil
|
res.Done <- nil
|
||||||
// Ignoring withdrawals here, since the block fetcher is not used post-merge.
|
// Ignoring withdrawals here, since the block fetcher is not used post-merge.
|
||||||
txs, uncles, _ := res.Res.(*eth.BlockBodiesResponse).Unpack()
|
txs, uncles, _ := res.Res.(*eth.BlockBodiesResponse).Unpack()
|
||||||
f.FilterBodies(peer, txs, uncles, time.Now())
|
f.FilterBodies(peer, txs, uncles, time.Now(), announcedAt)
|
||||||
|
|
||||||
case <-timeout.C:
|
case <-timeout.C:
|
||||||
// The peer didn't respond in time. The request
|
// The peer didn't respond in time. The request
|
||||||
|
|
@ -631,6 +638,7 @@ func (f *BlockFetcher) loop() {
|
||||||
|
|
||||||
block := types.NewBlockWithHeader(header)
|
block := types.NewBlockWithHeader(header)
|
||||||
block.ReceivedAt = task.time
|
block.ReceivedAt = task.time
|
||||||
|
block.AnnouncedAt = &task.announcedTime
|
||||||
|
|
||||||
complete = append(complete, block)
|
complete = append(complete, block)
|
||||||
f.completing[hash] = announce
|
f.completing[hash] = announce
|
||||||
|
|
@ -725,6 +733,7 @@ func (f *BlockFetcher) loop() {
|
||||||
if f.getBlock(hash) == nil {
|
if f.getBlock(hash) == nil {
|
||||||
block := types.NewBlockWithHeader(announce.header).WithBody(task.transactions[i], task.uncles[i])
|
block := types.NewBlockWithHeader(announce.header).WithBody(task.transactions[i], task.uncles[i])
|
||||||
block.ReceivedAt = task.time
|
block.ReceivedAt = task.time
|
||||||
|
block.AnnouncedAt = &task.announcedTime
|
||||||
blocks = append(blocks, block)
|
blocks = append(blocks, block)
|
||||||
} else {
|
} else {
|
||||||
f.forgetHash(hash)
|
f.forgetHash(hash)
|
||||||
|
|
@ -923,6 +932,31 @@ func (f *BlockFetcher) importBlocks(peer string, block *types.Block) {
|
||||||
log.Debug("Propagated block import failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err)
|
log.Debug("Propagated block import failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if f.enableBlockTracking {
|
||||||
|
// Log the insertion event
|
||||||
|
var (
|
||||||
|
msg string
|
||||||
|
delayInMs uint64
|
||||||
|
prettyDelay common.PrettyDuration
|
||||||
|
)
|
||||||
|
|
||||||
|
if block.AnnouncedAt != nil {
|
||||||
|
msg = "[block tracker] Inserted new block with announcement"
|
||||||
|
delayInMs = uint64(time.Since(*block.AnnouncedAt).Milliseconds())
|
||||||
|
prettyDelay = common.PrettyDuration(time.Since(*block.AnnouncedAt))
|
||||||
|
} else {
|
||||||
|
msg = "[block tracker] Inserted new block without announcement"
|
||||||
|
delayInMs = uint64(time.Since(block.ReceivedAt).Milliseconds())
|
||||||
|
prettyDelay = common.PrettyDuration(time.Since(block.ReceivedAt))
|
||||||
|
}
|
||||||
|
|
||||||
|
totalDelayInMs := uint64(time.Now().UnixMilli()) - block.Time()*1000
|
||||||
|
totalDelay := common.PrettyDuration(time.Millisecond * time.Duration(totalDelayInMs))
|
||||||
|
|
||||||
|
log.Info(msg, "number", block.Number().Uint64(), "hash", hash, "delay", prettyDelay, "delayInMs", delayInMs, "totalDelay", totalDelay, "totalDelayInMs", totalDelayInMs)
|
||||||
|
}
|
||||||
|
|
||||||
// If import succeeded, broadcast the block
|
// If import succeeded, broadcast the block
|
||||||
blockAnnounceOutTimer.UpdateSince(block.ReceivedAt)
|
blockAnnounceOutTimer.UpdateSince(block.ReceivedAt)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ func newTester(light bool) *fetcherTester {
|
||||||
blocks: map[common.Hash]*types.Block{genesis.Hash(): genesis},
|
blocks: map[common.Hash]*types.Block{genesis.Hash(): genesis},
|
||||||
drops: make(map[string]bool),
|
drops: make(map[string]bool),
|
||||||
}
|
}
|
||||||
tester.fetcher = NewBlockFetcher(light, tester.getHeader, tester.getBlock, tester.verifyHeader, tester.broadcastBlock, tester.chainHeight, tester.insertHeaders, tester.insertChain, tester.dropPeer)
|
tester.fetcher = NewBlockFetcher(light, tester.getHeader, tester.getBlock, tester.verifyHeader, tester.broadcastBlock, tester.chainHeight, tester.insertHeaders, tester.insertChain, tester.dropPeer, false)
|
||||||
tester.fetcher.Start()
|
tester.fetcher.Start()
|
||||||
|
|
||||||
return tester
|
return tester
|
||||||
|
|
|
||||||
|
|
@ -86,18 +86,19 @@ type txPool interface {
|
||||||
// handlerConfig is the collection of initialization parameters to create a full
|
// handlerConfig is the collection of initialization parameters to create a full
|
||||||
// node network handler.
|
// node network handler.
|
||||||
type handlerConfig struct {
|
type handlerConfig struct {
|
||||||
Database ethdb.Database // Database for direct sync insertions
|
Database ethdb.Database // Database for direct sync insertions
|
||||||
Chain *core.BlockChain // Blockchain to serve data from
|
Chain *core.BlockChain // Blockchain to serve data from
|
||||||
TxPool txPool // Transaction pool to propagate from
|
TxPool txPool // Transaction pool to propagate from
|
||||||
Merger *consensus.Merger // The manager for eth1/2 transition
|
Merger *consensus.Merger // The manager for eth1/2 transition
|
||||||
Network uint64 // Network identifier to adfvertise
|
Network uint64 // Network identifier to adfvertise
|
||||||
Sync downloader.SyncMode // Whether to snap or full sync
|
Sync downloader.SyncMode // Whether to snap or full sync
|
||||||
BloomCache uint64 // Megabytes to alloc for snap sync bloom
|
BloomCache uint64 // Megabytes to alloc for snap sync bloom
|
||||||
EventMux *event.TypeMux // Legacy event mux, deprecate for `feed`
|
EventMux *event.TypeMux // Legacy event mux, deprecate for `feed`
|
||||||
txArrivalWait time.Duration // Maximum duration to wait for an announced tx before requesting it
|
txArrivalWait time.Duration // Maximum duration to wait for an announced tx before requesting it
|
||||||
checker ethereum.ChainValidator
|
checker ethereum.ChainValidator
|
||||||
RequiredBlocks map[uint64]common.Hash // Hard coded map of required block hashes for sync challenges
|
RequiredBlocks map[uint64]common.Hash // Hard coded map of required block hashes for sync challenges
|
||||||
EthAPI *ethapi.BlockChainAPI // EthAPI to interact
|
EthAPI *ethapi.BlockChainAPI // EthAPI to interact
|
||||||
|
enableBlockTracking bool // Whether to log information collected while tracking block lifecycle
|
||||||
}
|
}
|
||||||
|
|
||||||
type handler struct {
|
type handler struct {
|
||||||
|
|
@ -127,6 +128,8 @@ type handler struct {
|
||||||
|
|
||||||
requiredBlocks map[uint64]common.Hash
|
requiredBlocks map[uint64]common.Hash
|
||||||
|
|
||||||
|
enableBlockTracking bool
|
||||||
|
|
||||||
// channels for fetcher, syncer, txsyncLoop
|
// channels for fetcher, syncer, txsyncLoop
|
||||||
quitSync chan struct{}
|
quitSync chan struct{}
|
||||||
|
|
||||||
|
|
@ -145,19 +148,20 @@ func newHandler(config *handlerConfig) (*handler, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
h := &handler{
|
h := &handler{
|
||||||
networkID: config.Network,
|
networkID: config.Network,
|
||||||
forkFilter: forkid.NewFilter(config.Chain),
|
forkFilter: forkid.NewFilter(config.Chain),
|
||||||
eventMux: config.EventMux,
|
eventMux: config.EventMux,
|
||||||
database: config.Database,
|
database: config.Database,
|
||||||
txpool: config.TxPool,
|
txpool: config.TxPool,
|
||||||
chain: config.Chain,
|
chain: config.Chain,
|
||||||
peers: newPeerSet(),
|
peers: newPeerSet(),
|
||||||
merger: config.Merger,
|
merger: config.Merger,
|
||||||
ethAPI: config.EthAPI,
|
ethAPI: config.EthAPI,
|
||||||
requiredBlocks: config.RequiredBlocks,
|
requiredBlocks: config.RequiredBlocks,
|
||||||
quitSync: make(chan struct{}),
|
enableBlockTracking: config.enableBlockTracking,
|
||||||
handlerDoneCh: make(chan struct{}),
|
quitSync: make(chan struct{}),
|
||||||
handlerStartCh: make(chan struct{}),
|
handlerDoneCh: make(chan struct{}),
|
||||||
|
handlerStartCh: make(chan struct{}),
|
||||||
}
|
}
|
||||||
if config.Sync == downloader.FullSync {
|
if config.Sync == downloader.FullSync {
|
||||||
// The database seems empty as the current block is the genesis. Yet the snap
|
// The database seems empty as the current block is the genesis. Yet the snap
|
||||||
|
|
@ -282,7 +286,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
|
||||||
}
|
}
|
||||||
return h.chain.InsertChain(blocks)
|
return h.chain.InsertChain(blocks)
|
||||||
}
|
}
|
||||||
h.blockFetcher = fetcher.NewBlockFetcher(false, nil, h.chain.GetBlockByHash, validator, h.BroadcastBlock, heighter, nil, inserter, h.removePeer)
|
h.blockFetcher = fetcher.NewBlockFetcher(false, nil, h.chain.GetBlockByHash, validator, h.BroadcastBlock, heighter, nil, inserter, h.removePeer, h.enableBlockTracking)
|
||||||
|
|
||||||
fetchTx := func(peer string, hashes []common.Hash) error {
|
fetchTx := func(peer string, hashes []common.Hash) error {
|
||||||
p := h.peers.peer(peer)
|
p := h.peers.peer(peer)
|
||||||
|
|
@ -679,6 +683,11 @@ func (h *handler) minedBroadcastLoop() {
|
||||||
|
|
||||||
for obj := range h.minedBlockSub.Chan() {
|
for obj := range h.minedBlockSub.Chan() {
|
||||||
if ev, ok := obj.Data.(core.NewMinedBlockEvent); ok {
|
if ev, ok := obj.Data.(core.NewMinedBlockEvent); ok {
|
||||||
|
if h.enableBlockTracking {
|
||||||
|
delayInMs := uint64(time.Now().UnixMilli()) - ev.Block.Time()*1000
|
||||||
|
delay := common.PrettyDuration(time.Millisecond * time.Duration(delayInMs))
|
||||||
|
log.Info("[block tracker] Broadcasting mined block", "number", ev.Block.NumberU64(), "hash", ev.Block.Hash(), "blockTime", ev.Block.Time(), "now", time.Now().Unix(), "delay", delay, "delayInMs", delayInMs)
|
||||||
|
}
|
||||||
h.BroadcastBlock(ev.Block, true) // First propagate block to peers
|
h.BroadcastBlock(ev.Block, true) // First propagate block to peers
|
||||||
h.BroadcastBlock(ev.Block, false) // Only then announce to the rest
|
h.BroadcastBlock(ev.Block, false) // Only then announce to the rest
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -333,8 +333,10 @@ func handleNewBlock(backend Backend, msg Decoder, peer *Peer) error {
|
||||||
return nil // TODO(karalabe): return error eventually, but wait a few releases
|
return nil // TODO(karalabe): return error eventually, but wait a few releases
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msgTime := msg.Time()
|
||||||
ann.Block.ReceivedAt = msg.Time()
|
ann.Block.ReceivedAt = msg.Time()
|
||||||
ann.Block.ReceivedFrom = peer
|
ann.Block.ReceivedFrom = peer
|
||||||
|
ann.Block.AnnouncedAt = &msgTime
|
||||||
|
|
||||||
// Mark the peer as owning the block
|
// Mark the peer as owning the block
|
||||||
peer.markBlock(ann.Block.Hash())
|
peer.markBlock(ann.Block.Hash())
|
||||||
|
|
|
||||||
|
|
@ -169,11 +169,13 @@ func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber
|
||||||
return api.blockByHash(ctx, hash)
|
return api.blockByHash(ctx, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns block transactions along with state-sync transaction if present
|
// getAllBlockTransactions returns all blocks transactions including state-sync transaction if present
|
||||||
func (api *API) getAllBlockTransactions(ctx context.Context, block *types.Block) (types.Transactions, bool) {
|
// along with a flag and it's hash (which is calculated differently than regular transactions)
|
||||||
|
func (api *API) getAllBlockTransactions(ctx context.Context, block *types.Block) (types.Transactions, bool, common.Hash) {
|
||||||
txs := block.Transactions()
|
txs := block.Transactions()
|
||||||
|
|
||||||
stateSyncPresent := false
|
stateSyncPresent := false
|
||||||
|
stateSyncHash := common.Hash{}
|
||||||
|
|
||||||
borReceipt := rawdb.ReadBorReceipt(api.backend.ChainDb(), block.Hash(), block.NumberU64(), api.backend.ChainConfig())
|
borReceipt := rawdb.ReadBorReceipt(api.backend.ChainDb(), block.Hash(), block.NumberU64(), api.backend.ChainConfig())
|
||||||
if borReceipt != nil {
|
if borReceipt != nil {
|
||||||
|
|
@ -182,10 +184,11 @@ func (api *API) getAllBlockTransactions(ctx context.Context, block *types.Block)
|
||||||
borTx, _, _, _, _ := api.backend.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash())
|
borTx, _, _, _, _ := api.backend.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash())
|
||||||
txs = append(txs, borTx)
|
txs = append(txs, borTx)
|
||||||
stateSyncPresent = true
|
stateSyncPresent = true
|
||||||
|
stateSyncHash = txHash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return txs, stateSyncPresent
|
return txs, stateSyncPresent, stateSyncHash
|
||||||
}
|
}
|
||||||
|
|
||||||
// TraceConfig holds extra parameters to trace functions.
|
// TraceConfig holds extra parameters to trace functions.
|
||||||
|
|
@ -337,19 +340,23 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
||||||
blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil)
|
blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil)
|
||||||
)
|
)
|
||||||
// Trace all the transactions contained within
|
// Trace all the transactions contained within
|
||||||
txs, stateSyncPresent := api.getAllBlockTransactions(ctx, task.block)
|
txs, stateSyncPresent, stateSyncHash := api.getAllBlockTransactions(ctx, task.block)
|
||||||
if !*config.BorTraceEnabled && stateSyncPresent {
|
if !*config.BorTraceEnabled && stateSyncPresent {
|
||||||
txs = txs[:len(txs)-1]
|
txs = txs[:len(txs)-1]
|
||||||
stateSyncPresent = false
|
stateSyncPresent = false
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tx := range task.block.Transactions() {
|
for i, tx := range txs {
|
||||||
msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee())
|
msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee())
|
||||||
|
txHash := tx.Hash()
|
||||||
|
if stateSyncPresent && i == len(txs)-1 {
|
||||||
|
txHash = stateSyncHash
|
||||||
|
}
|
||||||
txctx := &Context{
|
txctx := &Context{
|
||||||
BlockHash: task.block.Hash(),
|
BlockHash: task.block.Hash(),
|
||||||
BlockNumber: task.block.Number(),
|
BlockNumber: task.block.Number(),
|
||||||
TxIndex: i,
|
TxIndex: i,
|
||||||
TxHash: tx.Hash(),
|
TxHash: txHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
var res interface{}
|
var res interface{}
|
||||||
|
|
@ -364,14 +371,14 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
||||||
|
|
||||||
res, err = api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
|
res, err = api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()}
|
task.results[i] = &txTraceResult{TxHash: txHash, Error: err.Error()}
|
||||||
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
|
log.Warn("Tracing failed", "hash", txHash, "block", task.block.NumberU64(), "err", err)
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||||
task.statedb.Finalise(api.backend.ChainConfig().IsEIP158(task.block.Number()))
|
task.statedb.Finalise(api.backend.ChainConfig().IsEIP158(task.block.Number()))
|
||||||
task.results[i] = &txTraceResult{TxHash: tx.Hash(), Result: res}
|
task.results[i] = &txTraceResult{TxHash: txHash, Result: res}
|
||||||
}
|
}
|
||||||
// Tracing state is used up, queue it for de-referencing. Note the
|
// Tracing state is used up, queue it for de-referencing. Note the
|
||||||
// state is the parent state of trace block, use block.number-1 as
|
// state is the parent state of trace block, use block.number-1 as
|
||||||
|
|
@ -666,7 +673,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
||||||
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
|
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
|
||||||
)
|
)
|
||||||
|
|
||||||
txs, stateSyncPresent := api.getAllBlockTransactions(ctx, block)
|
txs, stateSyncPresent, stateSyncHash := api.getAllBlockTransactions(ctx, block)
|
||||||
for i, tx := range txs {
|
for i, tx := range txs {
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -678,14 +685,13 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
||||||
vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{})
|
vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{})
|
||||||
)
|
)
|
||||||
|
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
|
||||||
//nolint: nestif
|
//nolint: nestif
|
||||||
if stateSyncPresent && i == len(txs)-1 {
|
if stateSyncPresent && i == len(txs)-1 {
|
||||||
if *config.BorTraceEnabled {
|
if *config.BorTraceEnabled {
|
||||||
callmsg := prepareCallMessage(*msg)
|
callmsg := prepareCallMessage(*msg)
|
||||||
|
statedb.SetTxContext(stateSyncHash, i)
|
||||||
if _, err := statefull.ApplyMessage(ctx, callmsg, statedb, block.Header(), api.backend.ChainConfig(), api.chainContext(ctx)); err != nil {
|
if _, err := statefull.ApplyMessage(ctx, callmsg, statedb, block.Header(), api.backend.ChainConfig(), api.chainContext(ctx)); err != nil {
|
||||||
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", stateSyncHash, "err", err)
|
||||||
// We intentionally don't return the error here: if we do, then the RPC server will not
|
// We intentionally don't return the error here: if we do, then the RPC server will not
|
||||||
// return the roots. Most likely, the caller already knows that a certain transaction fails to
|
// return the roots. Most likely, the caller already knows that a certain transaction fails to
|
||||||
// be included, but still want the intermediate roots that led to that point.
|
// be included, but still want the intermediate roots that led to that point.
|
||||||
|
|
@ -698,6 +704,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
// nolint : contextcheck
|
// nolint : contextcheck
|
||||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), context.Background()); err != nil {
|
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), context.Background()); err != nil {
|
||||||
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
||||||
|
|
@ -787,12 +794,12 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
||||||
|
|
||||||
// Execute all the transaction contained within the block concurrently
|
// Execute all the transaction contained within the block concurrently
|
||||||
var (
|
var (
|
||||||
txs, stateSyncPresent = api.getAllBlockTransactions(ctx, block)
|
txs, stateSyncPresent, stateSyncHash = api.getAllBlockTransactions(ctx, block)
|
||||||
blockHash = block.Hash()
|
blockHash = block.Hash()
|
||||||
blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
|
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
|
||||||
results = make([]*txTraceResult, len(txs))
|
results = make([]*txTraceResult, len(txs))
|
||||||
pend sync.WaitGroup
|
pend sync.WaitGroup
|
||||||
)
|
)
|
||||||
|
|
||||||
threads := runtime.NumCPU()
|
threads := runtime.NumCPU()
|
||||||
|
|
@ -810,11 +817,15 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
||||||
// Fetch and execute the next transaction trace tasks
|
// Fetch and execute the next transaction trace tasks
|
||||||
for task := range jobs {
|
for task := range jobs {
|
||||||
msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee())
|
msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee())
|
||||||
|
txHash := txs[task.index].Hash()
|
||||||
|
if stateSyncPresent && task.index == len(txs)-1 {
|
||||||
|
txHash = stateSyncHash
|
||||||
|
}
|
||||||
txctx := &Context{
|
txctx := &Context{
|
||||||
BlockHash: blockHash,
|
BlockHash: blockHash,
|
||||||
BlockNumber: block.Number(),
|
BlockNumber: block.Number(),
|
||||||
TxIndex: task.index,
|
TxIndex: task.index,
|
||||||
TxHash: txs[task.index].Hash(),
|
TxHash: txHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
var res interface{}
|
var res interface{}
|
||||||
|
|
@ -833,10 +844,10 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()}
|
results[task.index] = &txTraceResult{TxHash: txHash, Error: err.Error()}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Result: res}
|
results[task.index] = &txTraceResult{TxHash: txHash, Result: res}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
@ -1048,7 +1059,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
chainConfig, canon = overrideConfig(chainConfig, config.Overrides)
|
chainConfig, canon = overrideConfig(chainConfig, config.Overrides)
|
||||||
}
|
}
|
||||||
|
|
||||||
txs, stateSyncPresent := api.getAllBlockTransactions(ctx, block)
|
txs, stateSyncPresent, stateSyncHash := api.getAllBlockTransactions(ctx, block)
|
||||||
if !*config.BorTraceEnabled && stateSyncPresent {
|
if !*config.BorTraceEnabled && stateSyncPresent {
|
||||||
txs = txs[:len(txs)-1]
|
txs = txs[:len(txs)-1]
|
||||||
stateSyncPresent = false
|
stateSyncPresent = false
|
||||||
|
|
@ -1065,7 +1076,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
// If the transaction needs tracing, swap out the configs
|
// If the transaction needs tracing, swap out the configs
|
||||||
if tx.Hash() == txHash || txHash == (common.Hash{}) {
|
if tx.Hash() == txHash || txHash == (common.Hash{}) || txHash == stateSyncHash {
|
||||||
// Generate a unique temporary file to dump it into
|
// Generate a unique temporary file to dump it into
|
||||||
prefix := fmt.Sprintf("block_%#x-%d-%#x-", block.Hash().Bytes()[:4], i, tx.Hash().Bytes()[:4])
|
prefix := fmt.Sprintf("block_%#x-%d-%#x-", block.Hash().Bytes()[:4], i, tx.Hash().Bytes()[:4])
|
||||||
if !canon {
|
if !canon {
|
||||||
|
|
@ -1088,11 +1099,12 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
}
|
}
|
||||||
// Execute the transaction and flush any traces to disk
|
// Execute the transaction and flush any traces to disk
|
||||||
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
|
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
|
||||||
//nolint: nestif
|
//nolint: nestif
|
||||||
if stateSyncPresent && i == len(txs)-1 {
|
if stateSyncPresent && i == len(txs)-1 {
|
||||||
if *config.BorTraceEnabled {
|
if *config.BorTraceEnabled {
|
||||||
callmsg := prepareCallMessage(*msg)
|
callmsg := prepareCallMessage(*msg)
|
||||||
|
statedb.SetTxContext(stateSyncHash, i)
|
||||||
_, err = statefull.ApplyBorMessage(vmenv, callmsg)
|
_, err = statefull.ApplyBorMessage(vmenv, callmsg)
|
||||||
|
|
||||||
if writer != nil {
|
if writer != nil {
|
||||||
|
|
@ -1100,6 +1112,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
// nolint : contextcheck
|
// nolint : contextcheck
|
||||||
_, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), context.Background())
|
_, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), context.Background())
|
||||||
|
|
||||||
|
|
@ -1132,9 +1145,9 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
// containsTx reports whether the transaction with a certain hash
|
// containsTx reports whether the transaction with a certain hash
|
||||||
// is contained within the specified block.
|
// is contained within the specified block.
|
||||||
func (api *API) containsTx(ctx context.Context, block *types.Block, hash common.Hash) bool {
|
func (api *API) containsTx(ctx context.Context, block *types.Block, hash common.Hash) bool {
|
||||||
txs, _ := api.getAllBlockTransactions(ctx, block)
|
txs, _, stateSyncHash := api.getAllBlockTransactions(ctx, block)
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
if tx.Hash() == hash {
|
if tx.Hash() == hash || stateSyncHash == hash {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,16 +68,20 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
|
||||||
|
|
||||||
// Execute all the transaction contained within the block concurrently
|
// Execute all the transaction contained within the block concurrently
|
||||||
var (
|
var (
|
||||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
|
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
|
||||||
txs, stateSyncPresent = api.getAllBlockTransactions(ctx, block)
|
txs, stateSyncPresent, stateSyncHash = api.getAllBlockTransactions(ctx, block)
|
||||||
deleteEmptyObjects = api.backend.ChainConfig().IsEIP158(block.Number())
|
deleteEmptyObjects = api.backend.ChainConfig().IsEIP158(block.Number())
|
||||||
)
|
)
|
||||||
|
|
||||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||||
|
|
||||||
traceTxn := func(indx int, tx *types.Transaction, borTx bool) *TxTraceResult {
|
traceTxn := func(indx int, tx *types.Transaction, borTx bool, stateSyncHash common.Hash) *TxTraceResult {
|
||||||
message, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
|
message, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
|
||||||
txContext := core.NewEVMTxContext(message)
|
txContext := core.NewEVMTxContext(message)
|
||||||
|
txHash := tx.Hash()
|
||||||
|
if borTx {
|
||||||
|
txHash = stateSyncHash
|
||||||
|
}
|
||||||
|
|
||||||
tracer := logger.NewStructLogger(config.Config)
|
tracer := logger.NewStructLogger(config.Config)
|
||||||
|
|
||||||
|
|
@ -86,7 +90,7 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
|
||||||
|
|
||||||
// Call Prepare to clear out the statedb access list
|
// Call Prepare to clear out the statedb access list
|
||||||
// Not sure if we need to do this
|
// Not sure if we need to do this
|
||||||
statedb.SetTxContext(tx.Hash(), indx)
|
statedb.SetTxContext(txHash, indx)
|
||||||
|
|
||||||
var execRes *core.ExecutionResult
|
var execRes *core.ExecutionResult
|
||||||
|
|
||||||
|
|
@ -124,9 +128,9 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
|
||||||
|
|
||||||
for indx, tx := range txs {
|
for indx, tx := range txs {
|
||||||
if stateSyncPresent && indx == len(txs)-1 {
|
if stateSyncPresent && indx == len(txs)-1 {
|
||||||
res.Transactions = append(res.Transactions, traceTxn(indx, tx, true))
|
res.Transactions = append(res.Transactions, traceTxn(indx, tx, true, stateSyncHash))
|
||||||
} else {
|
} else {
|
||||||
res.Transactions = append(res.Transactions, traceTxn(indx, tx, false))
|
res.Transactions = append(res.Transactions, traceTxn(indx, tx, false, stateSyncHash))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ var mainnetBor = &Chain{
|
||||||
BerlinBlock: big.NewInt(14750000),
|
BerlinBlock: big.NewInt(14750000),
|
||||||
LondonBlock: big.NewInt(23850000),
|
LondonBlock: big.NewInt(23850000),
|
||||||
ShanghaiBlock: big.NewInt(50523000),
|
ShanghaiBlock: big.NewInt(50523000),
|
||||||
|
CancunBlock: big.NewInt(54876000),
|
||||||
Bor: ¶ms.BorConfig{
|
Bor: ¶ms.BorConfig{
|
||||||
JaipurBlock: big.NewInt(23850000),
|
JaipurBlock: big.NewInt(23850000),
|
||||||
DelhiBlock: big.NewInt(38189056),
|
DelhiBlock: big.NewInt(38189056),
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,9 @@ type LoggingConfig struct {
|
||||||
// Prepends log messages with call-site location (file and line number)
|
// Prepends log messages with call-site location (file and line number)
|
||||||
Debug bool `hcl:"debug,optional" toml:"debug,optional"`
|
Debug bool `hcl:"debug,optional" toml:"debug,optional"`
|
||||||
|
|
||||||
|
// EnableBlockTracking allows logging of information collected while tracking block lifecycle
|
||||||
|
EnableBlockTracking bool `hcl:"enable-block-tracking,optional" toml:"enable-block-tracking,optional"`
|
||||||
|
|
||||||
// TODO - implement this
|
// TODO - implement this
|
||||||
// // Write execution trace to the given file
|
// // Write execution trace to the given file
|
||||||
// Trace string `hcl:"trace,optional" toml:"trace,optional"`
|
// Trace string `hcl:"trace,optional" toml:"trace,optional"`
|
||||||
|
|
@ -609,10 +612,11 @@ func DefaultConfig() *Config {
|
||||||
DBEngine: "leveldb",
|
DBEngine: "leveldb",
|
||||||
KeyStoreDir: "",
|
KeyStoreDir: "",
|
||||||
Logging: &LoggingConfig{
|
Logging: &LoggingConfig{
|
||||||
Vmodule: "",
|
Vmodule: "",
|
||||||
Json: false,
|
Json: false,
|
||||||
Backtrace: "",
|
Backtrace: "",
|
||||||
Debug: false,
|
Debug: false,
|
||||||
|
EnableBlockTracking: false,
|
||||||
},
|
},
|
||||||
RPCBatchLimit: 100,
|
RPCBatchLimit: 100,
|
||||||
RPCReturnDataLimit: 100000,
|
RPCReturnDataLimit: 100000,
|
||||||
|
|
@ -1198,6 +1202,8 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (*
|
||||||
n.DatabaseFreezer = c.Ancient
|
n.DatabaseFreezer = c.Ancient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n.EnableBlockTracking = c.Logging.EnableBlockTracking
|
||||||
|
|
||||||
return &n, nil
|
return &n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,13 @@ func (c *Command) Flags(config *Config) *flagset.Flagset {
|
||||||
Default: c.cliConfig.Logging.Debug,
|
Default: c.cliConfig.Logging.Debug,
|
||||||
Group: "Logging",
|
Group: "Logging",
|
||||||
})
|
})
|
||||||
|
f.BoolFlag(&flagset.BoolFlag{
|
||||||
|
Name: "log.enable-block-tracking",
|
||||||
|
Usage: "Enables additional logging of information collected while tracking block lifecycle",
|
||||||
|
Value: &c.cliConfig.Logging.EnableBlockTracking,
|
||||||
|
Default: c.cliConfig.Logging.EnableBlockTracking,
|
||||||
|
Group: "Logging",
|
||||||
|
})
|
||||||
|
|
||||||
// heimdall
|
// heimdall
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
|
|
|
||||||
|
|
@ -960,6 +960,14 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn
|
||||||
|
|
||||||
mainloop:
|
mainloop:
|
||||||
for {
|
for {
|
||||||
|
// Check interruption signal and abort building if it's fired.
|
||||||
|
if interrupt != nil {
|
||||||
|
if signal := interrupt.Load(); signal != commitInterruptNone {
|
||||||
|
breakCause = "interrupt"
|
||||||
|
return signalToErr(signal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if interruptCtx != nil {
|
if interruptCtx != nil {
|
||||||
if EnableMVHashMap && w.IsRunning() {
|
if EnableMVHashMap && w.IsRunning() {
|
||||||
env.state.AddEmptyMVHashMap()
|
env.state.AddEmptyMVHashMap()
|
||||||
|
|
@ -975,13 +983,6 @@ mainloop:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check interruption signal and abort building if it's fired.
|
|
||||||
if interrupt != nil {
|
|
||||||
if signal := interrupt.Load(); signal != commitInterruptNone {
|
|
||||||
breakCause = "interrupt"
|
|
||||||
return signalToErr(signal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If we don't have enough gas for any further transactions then we're done.
|
// If we don't have enough gas for any further transactions then we're done.
|
||||||
if env.gasPool.Gas() < params.TxGas {
|
if env.gasPool.Gas() < params.TxGas {
|
||||||
breakCause = "Not enough gas for further transactions"
|
breakCause = "Not enough gas for further transactions"
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ gcmode = "archive"
|
||||||
# json = false
|
# json = false
|
||||||
# backtrace = ""
|
# backtrace = ""
|
||||||
# debug = true
|
# debug = true
|
||||||
|
# enable-block-tracking = false
|
||||||
|
|
||||||
[p2p]
|
[p2p]
|
||||||
maxpeers = 50
|
maxpeers = 50
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ syncmode = "full"
|
||||||
# json = false
|
# json = false
|
||||||
# backtrace = ""
|
# backtrace = ""
|
||||||
# debug = true
|
# debug = true
|
||||||
|
# enable-block-tracking = false
|
||||||
|
|
||||||
[p2p]
|
[p2p]
|
||||||
maxpeers = 50
|
maxpeers = 50
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ syncmode = "full"
|
||||||
# json = false
|
# json = false
|
||||||
# backtrace = ""
|
# backtrace = ""
|
||||||
# debug = true
|
# debug = true
|
||||||
|
# enable-block-tracking = false
|
||||||
|
|
||||||
[p2p]
|
[p2p]
|
||||||
maxpeers = 20
|
maxpeers = 20
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ syncmode = "full"
|
||||||
# json = false
|
# json = false
|
||||||
# backtrace = ""
|
# backtrace = ""
|
||||||
# debug = true
|
# debug = true
|
||||||
|
# enable-block-tracking = false
|
||||||
|
|
||||||
[p2p]
|
[p2p]
|
||||||
maxpeers = 50
|
maxpeers = 50
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor
|
Source: bor
|
||||||
Version: 1.2.5-beta
|
Version: 1.2.9-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor
|
Source: bor
|
||||||
Version: 1.2.5-beta
|
Version: 1.2.9-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor-profile
|
Source: bor-profile
|
||||||
Version: 1.2.5-beta
|
Version: 1.2.9-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor-profile
|
Source: bor-profile
|
||||||
Version: 1.2.5-beta
|
Version: 1.2.9-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor-profile
|
Source: bor-profile
|
||||||
Version: 1.2.5-beta
|
Version: 1.2.9-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor-profile
|
Source: bor-profile
|
||||||
Version: 1.2.5-beta
|
Version: 1.2.9-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ gcmode = "archive"
|
||||||
# json = false
|
# json = false
|
||||||
# backtrace = ""
|
# backtrace = ""
|
||||||
# debug = true
|
# debug = true
|
||||||
|
# enable-block-tracking = false
|
||||||
|
|
||||||
[p2p]
|
[p2p]
|
||||||
maxpeers = 50
|
maxpeers = 50
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ syncmode = "full"
|
||||||
# json = false
|
# json = false
|
||||||
# backtrace = ""
|
# backtrace = ""
|
||||||
# debug = true
|
# debug = true
|
||||||
|
# enable-block-tracking = false
|
||||||
|
|
||||||
[p2p]
|
[p2p]
|
||||||
maxpeers = 50
|
maxpeers = 50
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ syncmode = "full"
|
||||||
# json = false
|
# json = false
|
||||||
# backtrace = ""
|
# backtrace = ""
|
||||||
# debug = true
|
# debug = true
|
||||||
|
# enable-block-tracking = false
|
||||||
|
|
||||||
[p2p]
|
[p2p]
|
||||||
maxpeers = 1
|
maxpeers = 1
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ syncmode = "full"
|
||||||
# json = false
|
# json = false
|
||||||
# backtrace = ""
|
# backtrace = ""
|
||||||
# debug = true
|
# debug = true
|
||||||
|
# enable-block-tracking = false
|
||||||
|
|
||||||
[p2p]
|
[p2p]
|
||||||
maxpeers = 50
|
maxpeers = 50
|
||||||
|
|
|
||||||
|
|
@ -310,6 +310,7 @@ var (
|
||||||
BerlinBlock: big.NewInt(14750000),
|
BerlinBlock: big.NewInt(14750000),
|
||||||
LondonBlock: big.NewInt(23850000),
|
LondonBlock: big.NewInt(23850000),
|
||||||
ShanghaiBlock: big.NewInt(50523000),
|
ShanghaiBlock: big.NewInt(50523000),
|
||||||
|
CancunBlock: big.NewInt(54876000),
|
||||||
Bor: &BorConfig{
|
Bor: &BorConfig{
|
||||||
JaipurBlock: big.NewInt(23850000),
|
JaipurBlock: big.NewInt(23850000),
|
||||||
DelhiBlock: big.NewInt(38189056),
|
DelhiBlock: big.NewInt(38189056),
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import (
|
||||||
const (
|
const (
|
||||||
VersionMajor = 1 // Major version component of the current release
|
VersionMajor = 1 // Major version component of the current release
|
||||||
VersionMinor = 2 // Minor version component of the current release
|
VersionMinor = 2 // Minor version component of the current release
|
||||||
VersionPatch = 5 // Patch version component of the current release
|
VersionPatch = 9 // Patch version component of the current release
|
||||||
VersionMeta = "beta" // Version metadata to append to the version string
|
VersionMeta = "beta" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue