mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +00:00
PR fix
This commit is contained in:
parent
d6d789368c
commit
d0f6dfdf60
3 changed files with 35 additions and 47 deletions
|
|
@ -170,13 +170,15 @@ func (c *FirehoseConfig) ForcedBackwardCompatibility() bool {
|
||||||
|
|
||||||
type Firehose struct {
|
type Firehose struct {
|
||||||
// Global state
|
// Global state
|
||||||
outputBuffer *bytes.Buffer
|
outputBuffer *bytes.Buffer
|
||||||
initSent *atomic.Bool
|
initSent *atomic.Bool
|
||||||
config *FirehoseConfig
|
config *FirehoseConfig
|
||||||
chainConfig *params.ChainConfig
|
chainConfig *params.ChainConfig
|
||||||
hasher crypto.KeccakState // Keccak256 hasher instance shared across tracer needs (non-concurrent safe)
|
hasher crypto.KeccakState // Keccak256 hasher instance shared across tracer needs (non-concurrent safe)
|
||||||
hasherBuf common.Hash // Keccak256 hasher result array shared across tracer needs (non-concurrent safe)
|
hasherBuf common.Hash // Keccak256 hasher result array shared across tracer needs (non-concurrent safe)
|
||||||
tracerID string
|
tracerID string
|
||||||
|
concurrentFlushQueue *ConcurrentFlushQueue
|
||||||
|
concurrentFlushBufferSize int
|
||||||
// The FirehoseTracer is used in multiple chains, some for which were produced using a legacy version
|
// The FirehoseTracer is used in multiple chains, some for which were produced using a legacy version
|
||||||
// of the whole tracing infrastructure. This legacy version had many small bugs here and there that
|
// of the whole tracing infrastructure. This legacy version had many small bugs here and there that
|
||||||
// we must "reproduce" on some chain to ensure that the FirehoseTracer produces the same output
|
// we must "reproduce" on some chain to ensure that the FirehoseTracer produces the same output
|
||||||
|
|
@ -199,8 +201,6 @@ type Firehose struct {
|
||||||
blockReorderOrdinalSnapshot uint64
|
blockReorderOrdinalSnapshot uint64
|
||||||
blockReorderOrdinalOnce sync.Once
|
blockReorderOrdinalOnce sync.Once
|
||||||
blockIsGenesis bool
|
blockIsGenesis bool
|
||||||
BlockFlushQueue *BlockFlushQueue
|
|
||||||
blockFlushBufferSize int
|
|
||||||
|
|
||||||
// Transaction state
|
// Transaction state
|
||||||
evm *tracing.VMContext
|
evm *tracing.VMContext
|
||||||
|
|
@ -260,10 +260,10 @@ func NewFirehose(config *FirehoseConfig) *Firehose {
|
||||||
concurrentBlockFlushing: config.ConcurrentBlockFlushing,
|
concurrentBlockFlushing: config.ConcurrentBlockFlushing,
|
||||||
|
|
||||||
// Block state
|
// Block state
|
||||||
blockOrdinal: &Ordinal{},
|
blockOrdinal: &Ordinal{},
|
||||||
blockFinality: &FinalityStatus{},
|
blockFinality: &FinalityStatus{},
|
||||||
blockReorderOrdinal: false,
|
blockReorderOrdinal: false,
|
||||||
blockFlushBufferSize: 100,
|
concurrentFlushBufferSize: 100,
|
||||||
|
|
||||||
// Transaction state
|
// Transaction state
|
||||||
transactionLogIndex: 0,
|
transactionLogIndex: 0,
|
||||||
|
|
@ -375,13 +375,13 @@ func (f *Firehose) OnBlockchainInit(chainConfig *params.ChainConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.config.ConcurrentBlockFlushing > 0 {
|
if f.config.ConcurrentBlockFlushing > 0 {
|
||||||
log.Info("Firehose concurrent block flushing enabled, starting goroutines")
|
log.Info("Firehose concurrent block flushing enabled, starting goroutine")
|
||||||
f.BlockFlushQueue = NewBlockFlushQueue(
|
f.concurrentFlushQueue = NewConcurrentFlushQueue(
|
||||||
f.config.ConcurrentBlockFlushing,
|
f.concurrentFlushBufferSize,
|
||||||
f.blockFlushBufferSize,
|
|
||||||
f.printBlockToFirehose,
|
f.printBlockToFirehose,
|
||||||
f.flushToFirehose,
|
f.flushToFirehose,
|
||||||
)
|
)
|
||||||
|
f.concurrentFlushQueue.Start(f.config.ConcurrentBlockFlushing)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Firehose tracer initialized",
|
log.Info("Firehose tracer initialized",
|
||||||
|
|
@ -530,7 +530,7 @@ func (f *Firehose) OnBlockEnd(err error) {
|
||||||
|
|
||||||
// Flush block to firehose and optionally use goroutine
|
// Flush block to firehose and optionally use goroutine
|
||||||
if f.concurrentBlockFlushing > 0 {
|
if f.concurrentBlockFlushing > 0 {
|
||||||
f.BlockFlushQueue.Enqueue(f.block, f.blockFinality)
|
f.concurrentFlushQueue.Enqueue(f.block, f.blockFinality)
|
||||||
} else {
|
} else {
|
||||||
f.printBlockToFirehose(f.block, f.blockFinality)
|
f.printBlockToFirehose(f.block, f.blockFinality)
|
||||||
}
|
}
|
||||||
|
|
@ -653,9 +653,9 @@ func (f *Firehose) reorderCallOrdinals(call *pbeth.Call, ordinalBase uint64) (or
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Firehose) OnClose() {
|
func (f *Firehose) OnClose() {
|
||||||
if f.BlockFlushQueue != nil {
|
if f.concurrentFlushQueue != nil {
|
||||||
log.Info("Firehose closing, flushing queued blocks to standard output")
|
log.Info("Firehose closing, flushing queued blocks to standard output")
|
||||||
f.BlockFlushQueue.Close()
|
f.concurrentFlushQueue.CloseChannels()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1949,7 +1949,7 @@ func (f *Firehose) printBlockToFirehose(block *pbeth.Block, finalityStatus *Fina
|
||||||
buf.WriteString("\n")
|
buf.WriteString("\n")
|
||||||
|
|
||||||
if f.concurrentBlockFlushing > 0 {
|
if f.concurrentBlockFlushing > 0 {
|
||||||
f.BlockFlushQueue.outputQueue <- &outputJob{
|
f.concurrentFlushQueue.outputQueue <- &outputJob{
|
||||||
blockNum: block.Number,
|
blockNum: block.Number,
|
||||||
data: buf.Bytes(),
|
data: buf.Bytes(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type outputJob struct {
|
||||||
data []byte
|
data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlockFlushQueue struct {
|
type ConcurrentFlushQueue struct {
|
||||||
bufferSize int
|
bufferSize int
|
||||||
|
|
||||||
startSignal chan uint64
|
startSignal chan uint64
|
||||||
|
|
@ -29,12 +29,8 @@ type BlockFlushQueue struct {
|
||||||
closeOnce sync.Once
|
closeOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBlockFlushQueue(concurrency int, bufferSize int, printBlockFunc func(*pbeth.Block, *FinalityStatus), outputFunc func([]byte)) *BlockFlushQueue {
|
func NewConcurrentFlushQueue(bufferSize int, printBlockFunc func(*pbeth.Block, *FinalityStatus), outputFunc func([]byte)) *ConcurrentFlushQueue {
|
||||||
if concurrency <= 0 {
|
return &ConcurrentFlushQueue{
|
||||||
panic("BlockFlushQueue requires concurrency > 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
q := &BlockFlushQueue{
|
|
||||||
startSignal: make(chan uint64, 1),
|
startSignal: make(chan uint64, 1),
|
||||||
jobQueue: make(chan *blockPrintJob, bufferSize),
|
jobQueue: make(chan *blockPrintJob, bufferSize),
|
||||||
outputQueue: make(chan *outputJob, bufferSize),
|
outputQueue: make(chan *outputJob, bufferSize),
|
||||||
|
|
@ -42,7 +38,9 @@ func NewBlockFlushQueue(concurrency int, bufferSize int, printBlockFunc func(*pb
|
||||||
bufferSize: bufferSize,
|
bufferSize: bufferSize,
|
||||||
printBlockFunc: printBlockFunc,
|
printBlockFunc: printBlockFunc,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *ConcurrentFlushQueue) Start(concurrency int) {
|
||||||
for i := 0; i < concurrency; i++ {
|
for i := 0; i < concurrency; i++ {
|
||||||
q.jobWG.Add(1)
|
q.jobWG.Add(1)
|
||||||
go q.worker()
|
go q.worker()
|
||||||
|
|
@ -50,11 +48,9 @@ func NewBlockFlushQueue(concurrency int, bufferSize int, printBlockFunc func(*pb
|
||||||
|
|
||||||
q.outputWG.Add(1)
|
q.outputWG.Add(1)
|
||||||
go q.outputOrderer()
|
go q.outputOrderer()
|
||||||
|
|
||||||
return q
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *BlockFlushQueue) Enqueue(block *pbeth.Block, finality *FinalityStatus) {
|
func (q *ConcurrentFlushQueue) Enqueue(block *pbeth.Block, finality *FinalityStatus) {
|
||||||
select {
|
select {
|
||||||
case q.startSignal <- block.Number:
|
case q.startSignal <- block.Number:
|
||||||
default:
|
default:
|
||||||
|
|
@ -66,10 +62,10 @@ func (q *BlockFlushQueue) Enqueue(block *pbeth.Block, finality *FinalityStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close CloseBlockPrintQueue signals block printing goroutines to shut down and waits for them.
|
// CloseChannels signals goroutines to shut down and waits for them.
|
||||||
// It blocks until all concurrent block flushing operations are completed, ensuring a clean
|
// It blocks until all concurrent block flushing operations are completed, ensuring a clean
|
||||||
// shutdown of the printing pipeline.
|
// shutdown of the printing pipeline.
|
||||||
func (q *BlockFlushQueue) Close() {
|
func (q *ConcurrentFlushQueue) CloseChannels() {
|
||||||
q.closeOnce.Do(func() {
|
q.closeOnce.Do(func() {
|
||||||
close(q.jobQueue)
|
close(q.jobQueue)
|
||||||
q.jobWG.Wait()
|
q.jobWG.Wait()
|
||||||
|
|
@ -79,7 +75,7 @@ func (q *BlockFlushQueue) Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instantiates a worker that listens for jobs
|
// Instantiates a worker that listens for jobs
|
||||||
func (q *BlockFlushQueue) worker() {
|
func (q *ConcurrentFlushQueue) worker() {
|
||||||
defer q.jobWG.Done()
|
defer q.jobWG.Done()
|
||||||
for job := range q.jobQueue {
|
for job := range q.jobQueue {
|
||||||
q.printBlockFunc(job.block, job.finality)
|
q.printBlockFunc(job.block, job.finality)
|
||||||
|
|
@ -87,7 +83,7 @@ func (q *BlockFlushQueue) worker() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Channel ensuring that blocks are linearly flushed out in order
|
// Channel ensuring that blocks are linearly flushed out in order
|
||||||
func (q *BlockFlushQueue) outputOrderer() {
|
func (q *ConcurrentFlushQueue) outputOrderer() {
|
||||||
defer q.outputWG.Done()
|
defer q.outputWG.Done()
|
||||||
buffer := make(map[uint64][]byte)
|
buffer := make(map[uint64][]byte)
|
||||||
next := <-q.startSignal
|
next := <-q.startSignal
|
||||||
|
|
|
||||||
|
|
@ -55,15 +55,11 @@ func TestFirehosePrestate(t *testing.T) {
|
||||||
ConcurrentBlockFlushing: concurrent,
|
ConcurrentBlockFlushing: concurrent,
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer, tracingHooks, onClose := newFirehoseTestTracer(t, model, config)
|
tracer, tracingHooks, _ := newFirehoseTestTracer(t, model, config)
|
||||||
defer onClose()
|
|
||||||
|
|
||||||
runPrestateBlock(t, filepath.Join(folder, "prestate.json"), tracingHooks)
|
runPrestateBlock(t, filepath.Join(folder, "prestate.json"), tracingHooks)
|
||||||
|
|
||||||
if tracer.BlockFlushQueue != nil {
|
tracer.OnClose()
|
||||||
tracer.BlockFlushQueue.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
genesisLine, blockLines, unknownLines := readTracerFirehoseLines(t, tracer)
|
genesisLine, blockLines, unknownLines := readTracerFirehoseLines(t, tracer)
|
||||||
require.Len(t, unknownLines, 0, "Lines:\n%s", strings.Join(
|
require.Len(t, unknownLines, 0, "Lines:\n%s", strings.Join(
|
||||||
slicesMap(unknownLines, func(l unknownLine) string { return "- '" + string(l) + "'" }), "\n"))
|
slicesMap(unknownLines, func(l unknownLine) string { return "- '" + string(l) + "'" }), "\n"))
|
||||||
|
|
@ -214,8 +210,7 @@ func testBlockTracesCorrectly(t *testing.T, genesisSpec *core.Genesis, engine co
|
||||||
ConcurrentBlockFlushing: concurrent,
|
ConcurrentBlockFlushing: concurrent,
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer, tracingHooks, onClose := newFirehoseTestTracer(t, model, config)
|
tracer, tracingHooks, _ := newFirehoseTestTracer(t, model, config)
|
||||||
defer onClose()
|
|
||||||
|
|
||||||
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesisSpec, nil, engine, vm.Config{Tracer: tracingHooks}, nil)
|
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesisSpec, nil, engine, vm.Config{Tracer: tracingHooks}, nil)
|
||||||
require.NoError(t, err, "failed to create tester chain")
|
require.NoError(t, err, "failed to create tester chain")
|
||||||
|
|
@ -229,10 +224,7 @@ func testBlockTracesCorrectly(t *testing.T, genesisSpec *core.Genesis, engine co
|
||||||
n, err := chain.InsertChain(blocks)
|
n, err := chain.InsertChain(blocks)
|
||||||
require.NoError(t, err, "failed to insert chain block %d", n)
|
require.NoError(t, err, "failed to insert chain block %d", n)
|
||||||
|
|
||||||
if tracer.BlockFlushQueue != nil {
|
tracer.OnClose()
|
||||||
tracer.BlockFlushQueue.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
assertBlockEquals(t, tracer, filepath.Join("testdata", goldenDir, string(model)), len(blocks))
|
assertBlockEquals(t, tracer, filepath.Join("testdata", goldenDir, string(model)), len(blocks))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue