From 5dbc701e8d658eecd1392e5dac1539948ed72981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20M=C3=A4kel=C3=A4?= Date: Wed, 20 Nov 2019 19:09:01 +0200 Subject: [PATCH] Extra receipt for internal EVM call when finalizing blocks (#584) --- consensus/istanbul/backend/engine.go | 7 +++++++ core/blockchain.go | 17 +++++++++++++++-- core/state_processor.go | 12 ++++++++++++ miner/worker.go | 15 +++++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/consensus/istanbul/backend/engine.go b/consensus/istanbul/backend/engine.go index 17277d7aef..afe56a0693 100644 --- a/consensus/istanbul/backend/engine.go +++ b/consensus/istanbul/backend/engine.go @@ -495,6 +495,13 @@ func (sb *Backend) Finalize(chain consensus.ChainReader, header *types.Header, s header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = nilUncleHash + if len(state.GetLogs(common.Hash{})) > 0 { + receipt := types.NewReceipt(nil, false, 0) + receipt.Logs = state.GetLogs(common.Hash{}) + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipts = append(receipts, receipt) + } + // Assemble and return the final block for sealing return types.NewBlock(header, txs, nil, receipts, randomness), nil } diff --git a/core/blockchain.go b/core/blockchain.go index 87334607b7..93ad8b098b 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -786,11 +786,12 @@ func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts ty signer := types.MakeSigner(config, block.Number()) transactions, logIndex := block.Transactions(), uint(0) - if len(transactions) != len(receipts) { + // The receipts may include an additional "block finalization" receipt + if len(transactions) != len(receipts) && len(transactions)+1 != len(receipts) { return errors.New("transaction and receipt count mismatch") } - for j := 0; j < len(receipts); j++ { + for j := 0; j < len(transactions); j++ { // The transaction hash can be retrieved from the transaction itself receipts[j].TxHash = transactions[j].Hash() @@ -816,6 +817,18 @@ func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts ty logIndex++ } } + // Handle block finalization receipt + if len(transactions)+1 == len(receipts) { + j := len(transactions) + for k := 0; k < len(receipts[j].Logs); k++ { + receipts[j].Logs[k].BlockNumber = block.NumberU64() + receipts[j].Logs[k].BlockHash = block.Hash() + receipts[j].Logs[k].TxHash = block.Hash() + receipts[j].Logs[k].TxIndex = uint(j) + receipts[j].Logs[k].Index = logIndex + logIndex++ + } + } return nil } diff --git a/core/state_processor.go b/core/state_processor.go index c3456cb57b..c1620bdda8 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -84,8 +84,20 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg allLogs = append(allLogs, receipt.Logs...) } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) + statedb.Prepare(common.Hash{}, block.Hash(), len(block.Transactions())) p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), receipts, block.Randomness()) + if len(statedb.GetLogs(common.Hash{})) > 0 { + receipt := types.NewReceipt(nil, false, 0) + receipt.Logs = statedb.GetLogs(common.Hash{}) + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + for i := range receipt.Logs { + receipt.Logs[i].TxIndex = uint(len(receipts)) + receipt.Logs[i].TxHash = block.Hash() + } + receipts = append(receipts, receipt) + } + return receipts, allLogs, *usedGas, nil } diff --git a/miner/worker.go b/miner/worker.go index 66e71b8ef1..9bc420a8fe 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -614,6 +614,10 @@ func (w *worker) resultLoop() { // receipt/log of individual transactions were created. for _, log := range receipt.Logs { log.BlockHash = hash + // Handle block finalization receipt + if (log.TxHash == common.Hash{}) { + log.TxHash = hash + } } logs = append(logs, receipt.Logs...) } @@ -1068,6 +1072,17 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st } block, err := w.engine.Finalize(w.chain, w.current.header, s, w.current.txs, uncles, w.current.receipts, w.current.randomness) + + if len(s.GetLogs(common.Hash{})) > 0 { + receipt := types.NewReceipt(nil, false, 0) + receipt.Logs = s.GetLogs(common.Hash{}) + for i := range receipt.Logs { + receipt.Logs[i].TxIndex = uint(len(receipts)) + } + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipts = append(receipts, receipt) + } + if err != nil { log.Error("Unable to finalize block", "err", err) return err