Merge branch 'master' into shivam/temp-master-develop

This commit is contained in:
Shivam Sharma 2024-03-20 14:29:04 +05:30
commit 184b2d628d
34 changed files with 239 additions and 138 deletions

View file

@ -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

View file

@ -14,6 +14,7 @@
"berlinBlock": 14750000, "berlinBlock": 14750000,
"londonBlock": 23850000, "londonBlock": 23850000,
"shanghaiBlock": 50523000, "shanghaiBlock": 50523000,
"cancunBlock": 54876000,
"bor": { "bor": {
"jaipurBlock": 23850000, "jaipurBlock": 23850000,
"delhiBlock": 38189056, "delhiBlock": 38189056,

View file

@ -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:

View file

@ -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.

View file

@ -27,7 +27,8 @@ devfakeauthor = false # Run miner without validator set authorization
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)

View file

@ -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)

View file

@ -292,6 +292,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
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
} }

View file

@ -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.

View file

@ -117,6 +117,7 @@ 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)
@ -126,6 +127,7 @@ type bodyFilterTask struct {
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,10 +199,13 @@ 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),
@ -225,6 +230,7 @@ func NewBlockFetcher(light bool, getHeader HeaderRetrievalFn, getBlock blockRetr
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)
@ -564,8 +571,8 @@ func (f *BlockFetcher) loop() {
case res := <-resCh: case res := <-resCh:
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.BlockBodiesPacket).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)

View file

@ -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

View file

@ -98,6 +98,7 @@ type handlerConfig struct {
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{}
@ -155,6 +158,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
merger: config.Merger, merger: config.Merger,
ethAPI: config.EthAPI, ethAPI: config.EthAPI,
requiredBlocks: config.RequiredBlocks, requiredBlocks: config.RequiredBlocks,
enableBlockTracking: config.enableBlockTracking,
quitSync: make(chan struct{}), quitSync: make(chan struct{}),
handlerDoneCh: make(chan struct{}), handlerDoneCh: make(chan struct{}),
handlerStartCh: make(chan struct{}), handlerStartCh: make(chan struct{}),
@ -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
} }

View file

@ -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())

View file

@ -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,7 +794,7 @@ 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())
@ -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
} }
} }

View file

@ -69,15 +69,19 @@ 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))
} }
} }

View file

@ -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: &params.BorConfig{ Bor: &params.BorConfig{
JaipurBlock: big.NewInt(23850000), JaipurBlock: big.NewInt(23850000),
DelhiBlock: big.NewInt(38189056), DelhiBlock: big.NewInt(38189056),

View file

@ -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"`
@ -613,6 +616,7 @@ func DefaultConfig() *Config {
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
} }

View file

@ -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{

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,5 @@
Source: bor Source: bor
Version: 1.2.5-beta Version: 1.2.8
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -1,5 +1,5 @@
Source: bor Source: bor
Version: 1.2.5-beta Version: 1.2.8
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -1,5 +1,5 @@
Source: bor-profile Source: bor-profile
Version: 1.2.5-beta Version: 1.2.8
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -1,5 +1,5 @@
Source: bor-profile Source: bor-profile
Version: 1.2.5-beta Version: 1.2.8
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -1,5 +1,5 @@
Source: bor-profile Source: bor-profile
Version: 1.2.5-beta Version: 1.2.8
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -1,5 +1,5 @@
Source: bor-profile Source: bor-profile
Version: 1.2.5-beta Version: 1.2.8
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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),

View file

@ -23,8 +23,8 @@ 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 = 8 // Patch version component of the current release
VersionMeta = "beta" // Version metadata to append to the version string VersionMeta = "" // Version metadata to append to the version string
) )
var GitCommit string var GitCommit string