diff --git a/core/blockchain.go b/core/blockchain.go index 2521e0cd8e58d2df9c20ac2465e5a0a7e770aa49..2fd91de3ab38a11421a76e41bcdbbc550c3acb22 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1445,18 +1445,25 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. rawdb.WriteBlock(blockBatch, block) rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts) - // storing bor block receipt + // System call appends state-sync logs into state. So, `state.Logs()` contains + // all logs including system-call logs (state sync logs) while `logs` contains + // only logs generated by transactions (receipts). + // + // That means that state.Logs() can have more logs than receipt logs. + // In that case, we can safely assume that extra logs are from state sync logs. + // + // block logs = receipt logs + state sync logs = `state.Logs()` blockLogs := state.Logs() if len(blockLogs) > 0 { sort.SliceStable(blockLogs, func(i, j int) bool { return blockLogs[i].Index < blockLogs[j].Index }) - } - if len(blockLogs) > len(logs) { - rawdb.WriteBorReceipt(blockBatch, block.Hash(), block.NumberU64(), &types.BorReceiptForStorage{ - Logs: blockLogs[len(logs):], - }) + if len(blockLogs) > len(logs) { + rawdb.WriteBorReceipt(blockBatch, block.Hash(), block.NumberU64(), &types.BorReceiptForStorage{ + Logs: blockLogs[len(logs):], // get state-sync logs from `state.Logs()` + }) + } } rawdb.WritePreimages(blockBatch, state.Preimages()) diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go index 3690dde9af56f9f70e9e06de5b38b8372d17bcd8..cd0bd3b9708f8fec2e5517611f5ff8cb6bc27d1b 100644 --- a/core/rawdb/freezer.go +++ b/core/rawdb/freezer.go @@ -115,6 +115,19 @@ func newFreezer(datadir string, namespace string) (*freezer, error) { } freezer.tables[name] = table } + + // Adjust table length for bor-receipt freezer for already synced nodes. + // + // Since, table only supports sequential data, this will fill empty-data upto current + // synced block (till current total header number). + // + // This way they don't have to sync again from block 0 and still be compatible + // for block logs for future blocks. Note that already synced nodes + // won't have past block logs. Newly synced node will have all the data. + if err := freezer.tables[freezerBorReceiptTable].Fill(freezer.tables[freezerHeaderTable].items); err != nil { + return nil, err + } + if err := freezer.repair(); err != nil { for _, table := range freezer.tables { table.Close() diff --git a/core/rawdb/freezer_table.go b/core/rawdb/freezer_table.go index ae7ee0cf3b17fb67c35c8acd7f207d58dd2bc496..cfbff058ce9a8df5c2072f2b04718977bc97350a 100644 --- a/core/rawdb/freezer_table.go +++ b/core/rawdb/freezer_table.go @@ -648,3 +648,21 @@ func (t *freezerTable) printIndex() { } fmt.Printf("|-----------------|\n") } + +// +// Bor related changes +// + +// Fill adds empty data till given number (convenience method for backward compatibilty) +func (t *freezerTable) Fill(number uint64) error { + if t.items < number { + log.Info("Filling all data into freezer for backward compatablity", "name", t.name, "items", t.items, "number", number) + for t.items < number { + if err := t.Append(t.items, nil); err != nil { + log.Error("Failed to fill data into freezer", "name", t.name, "items", t.items, "number", number, "err", err) + return err + } + } + } + return nil +}