mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-17 12:21:38 +00:00
core/rawdb: remove BAL from chain freezer
This commit is contained in:
parent
50e5b7b60a
commit
34a09b1aaf
6 changed files with 14 additions and 142 deletions
|
|
@ -1476,7 +1476,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
// Ensure genesis is in the ancient store
|
// Ensure genesis is in the ancient store
|
||||||
if blockChain[0].NumberU64() == 1 {
|
if blockChain[0].NumberU64() == 1 {
|
||||||
if frozen, _ := bc.db.Ancients(); frozen == 0 {
|
if frozen, _ := bc.db.Ancients(); frozen == 0 {
|
||||||
writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList}, nil)
|
writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error writing genesis to ancients", "err", err)
|
log.Error("Error writing genesis to ancients", "err", err)
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
@ -1486,7 +1486,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Write all chain data to ancients.
|
// Write all chain data to ancients.
|
||||||
writeSize, err := rawdb.WriteAncientBlocks(bc.db, blockChain, receiptChain, nil)
|
writeSize, err := rawdb.WriteAncientBlocks(bc.db, blockChain, receiptChain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error importing chain data to ancients", "err", err)
|
log.Error("Error importing chain data to ancients", "err", err)
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
@ -2907,7 +2907,7 @@ func (bc *BlockChain) InsertHeadersBeforeCutoff(headers []*types.Header) (int, e
|
||||||
first = headers[0].Number.Uint64()
|
first = headers[0].Number.Uint64()
|
||||||
)
|
)
|
||||||
if first == 1 && frozen == 0 {
|
if first == 1 && frozen == 0 {
|
||||||
_, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList}, nil)
|
_, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error writing genesis to ancients", "err", err)
|
log.Error("Error writing genesis to ancients", "err", err)
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
|
||||||
|
|
@ -611,41 +611,9 @@ func HasAccessList(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||||
return len(ReadAccessListRLP(db, hash, number)) > 0
|
return len(ReadAccessListRLP(db, hash, number)) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadAccessListRLP retrieves the RLP-encoded block access list for a block.
|
// ReadAccessListRLP retrieves the RLP-encoded block access list for a block from KV.
|
||||||
func ReadAccessListRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
func ReadAccessListRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||||
var data []byte
|
data, _ := db.Get(balKey(number, hash))
|
||||||
err := db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
|
||||||
if isCanon(reader, number, hash) {
|
|
||||||
data, _ = reader.Ancient(ChainFreezerBALTable, number)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data, _ = db.Get(balKey(number, hash))
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Crit("error reading from ancient store", "err", err)
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadCanonicalAccessListRLP retrieves the BAL RLP for the canonical block at number.
|
|
||||||
// Optionally takes the block hash to avoid looking it up.
|
|
||||||
func ReadCanonicalAccessListRLP(db ethdb.Reader, number uint64, hash *common.Hash) rlp.RawValue {
|
|
||||||
var data []byte
|
|
||||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
|
||||||
data, _ = reader.Ancient(ChainFreezerBALTable, number)
|
|
||||||
if len(data) > 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// BAL is not in ancients, read from db by hash and number.
|
|
||||||
if hash != nil {
|
|
||||||
data, _ = db.Get(balKey(number, *hash))
|
|
||||||
} else {
|
|
||||||
hashBytes, _ := db.Get(headerHashKey(number))
|
|
||||||
data, _ = db.Get(balKey(number, common.BytesToHash(hashBytes)))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -760,15 +728,11 @@ func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteAncientBlocks writes entire block data into ancient store and returns the total written size.
|
// WriteAncientBlocks writes entire block data into ancient store and returns the total written size.
|
||||||
func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts []rlp.RawValue, bals []rlp.RawValue) (int64, error) {
|
func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts []rlp.RawValue) (int64, error) {
|
||||||
return db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
|
return db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
|
||||||
for i, block := range blocks {
|
for i, block := range blocks {
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
var bal rlp.RawValue
|
if err := writeAncientBlock(op, block, header, receipts[i]); err != nil {
|
||||||
if bals != nil {
|
|
||||||
bal = bals[i]
|
|
||||||
}
|
|
||||||
if err := writeAncientBlock(op, block, header, receipts[i], bal); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -776,7 +740,7 @@ func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts rlp.RawValue, bal rlp.RawValue) error {
|
func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts rlp.RawValue) error {
|
||||||
num := block.NumberU64()
|
num := block.NumberU64()
|
||||||
if err := op.AppendRaw(ChainFreezerHashTable, num, block.Hash().Bytes()); err != nil {
|
if err := op.AppendRaw(ChainFreezerHashTable, num, block.Hash().Bytes()); err != nil {
|
||||||
return fmt.Errorf("can't add block %d hash: %v", num, err)
|
return fmt.Errorf("can't add block %d hash: %v", num, err)
|
||||||
|
|
@ -790,9 +754,6 @@ func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *type
|
||||||
if err := op.Append(ChainFreezerReceiptTable, num, receipts); err != nil {
|
if err := op.Append(ChainFreezerReceiptTable, num, receipts); err != nil {
|
||||||
return fmt.Errorf("can't append block %d receipts: %v", num, err)
|
return fmt.Errorf("can't append block %d receipts: %v", num, err)
|
||||||
}
|
}
|
||||||
if err := op.AppendRaw(ChainFreezerBALTable, num, bal); err != nil {
|
|
||||||
return fmt.Errorf("can't append block %d BAL: %v", num, err)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -815,9 +776,6 @@ func WriteAncientHeaderChain(db ethdb.AncientWriter, headers []*types.Header) (i
|
||||||
if err := op.AppendRaw(ChainFreezerReceiptTable, num, nil); err != nil {
|
if err := op.AppendRaw(ChainFreezerReceiptTable, num, nil); err != nil {
|
||||||
return fmt.Errorf("can't append block %d receipts: %v", num, err)
|
return fmt.Errorf("can't append block %d receipts: %v", num, err)
|
||||||
}
|
}
|
||||||
if err := op.AppendRaw(ChainFreezerBALTable, num, nil); err != nil {
|
|
||||||
return fmt.Errorf("can't append block %d BAL: %v", num, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
@ -826,7 +784,6 @@ func WriteAncientHeaderChain(db ethdb.AncientWriter, headers []*types.Header) (i
|
||||||
// DeleteBlock removes all block data associated with a hash.
|
// DeleteBlock removes all block data associated with a hash.
|
||||||
func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||||
DeleteReceipts(db, hash, number)
|
DeleteReceipts(db, hash, number)
|
||||||
DeleteAccessList(db, hash, number)
|
|
||||||
DeleteHeader(db, hash, number)
|
DeleteHeader(db, hash, number)
|
||||||
DeleteBody(db, hash, number)
|
DeleteBody(db, hash, number)
|
||||||
}
|
}
|
||||||
|
|
@ -835,7 +792,6 @@ func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||||
// the hash to number mapping.
|
// the hash to number mapping.
|
||||||
func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||||
DeleteReceipts(db, hash, number)
|
DeleteReceipts(db, hash, number)
|
||||||
DeleteAccessList(db, hash, number)
|
|
||||||
deleteHeaderWithoutNumber(db, hash, number)
|
deleteHeaderWithoutNumber(db, hash, number)
|
||||||
DeleteBody(db, hash, number)
|
DeleteBody(db, hash, number)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -433,7 +433,7 @@ func TestAncientStorage(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write and verify the header in the database
|
// Write and verify the header in the database
|
||||||
WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil}), nil)
|
WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil}))
|
||||||
|
|
||||||
if blob := ReadHeaderRLP(db, hash, number); len(blob) == 0 {
|
if blob := ReadHeaderRLP(db, hash, number); len(blob) == 0 {
|
||||||
t.Fatalf("no header returned")
|
t.Fatalf("no header returned")
|
||||||
|
|
@ -563,7 +563,7 @@ func BenchmarkWriteAncientBlocks(b *testing.B) {
|
||||||
|
|
||||||
blocks := allBlocks[i : i+length]
|
blocks := allBlocks[i : i+length]
|
||||||
receipts := batchReceipts[:length]
|
receipts := batchReceipts[:length]
|
||||||
writeSize, err := WriteAncientBlocks(db, blocks, types.EncodeBlockReceiptLists(receipts), nil)
|
writeSize, err := WriteAncientBlocks(db, blocks, types.EncodeBlockReceiptLists(receipts))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -868,7 +868,7 @@ func TestHeadersRLPStorage(t *testing.T) {
|
||||||
}
|
}
|
||||||
receipts := make([]types.Receipts, 100)
|
receipts := make([]types.Receipts, 100)
|
||||||
// Write first half to ancients
|
// Write first half to ancients
|
||||||
WriteAncientBlocks(db, chain[:50], types.EncodeBlockReceiptLists(receipts[:50]), nil)
|
WriteAncientBlocks(db, chain[:50], types.EncodeBlockReceiptLists(receipts[:50]))
|
||||||
// Write second half to db
|
// Write second half to db
|
||||||
for i := 50; i < 100; i++ {
|
for i := 50; i < 100; i++ {
|
||||||
WriteCanonicalHash(db, chain[i].Hash(), chain[i].NumberU64())
|
WriteCanonicalHash(db, chain[i].Hash(), chain[i].NumberU64())
|
||||||
|
|
@ -977,80 +977,4 @@ func TestBALStorage(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestBALFreezer tests that BALs are frozen alongside other block data
|
|
||||||
// and can be read from the freezer.
|
|
||||||
func TestBALFreezer(t *testing.T) {
|
|
||||||
frdir := t.TempDir()
|
|
||||||
db, err := Open(NewMemoryDatabase(), OpenOptions{Ancient: frdir})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create database with ancient backend: %v", err)
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
// Create a test block.
|
|
||||||
block := types.NewBlockWithHeader(&types.Header{
|
|
||||||
Number: big.NewInt(0),
|
|
||||||
Extra: []byte("test block"),
|
|
||||||
UncleHash: types.EmptyUncleHash,
|
|
||||||
TxHash: types.EmptyTxsHash,
|
|
||||||
ReceiptHash: types.EmptyReceiptsHash,
|
|
||||||
})
|
|
||||||
hash, number := block.Hash(), block.NumberU64()
|
|
||||||
|
|
||||||
// Verify no BAL exists before writing.
|
|
||||||
if blob := ReadAccessListRLP(db, hash, number); len(blob) > 0 {
|
|
||||||
t.Fatalf("non existent BAL returned")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write a BAL to KV first, then freeze.
|
|
||||||
balRLP, testBAL := makeTestBAL(t)
|
|
||||||
|
|
||||||
// Freeze via WriteAncientBlocks.
|
|
||||||
WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil}), []rlp.RawValue{balRLP})
|
|
||||||
|
|
||||||
// Verify the BAL can be read from the freezer.
|
|
||||||
if blob := ReadAccessListRLP(db, hash, number); len(blob) == 0 {
|
|
||||||
t.Fatal("no BAL returned from freezer")
|
|
||||||
}
|
|
||||||
if b := ReadAccessList(db, hash, number); b == nil {
|
|
||||||
t.Fatal("ReadAccessList returned nil from freezer")
|
|
||||||
} else if b.Hash() != testBAL.Hash() {
|
|
||||||
t.Fatalf("frozen BAL hash mismatch: got %x, want %x", b.Hash(), testBAL.Hash())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify ReadCanonicalAccessListRLP works.
|
|
||||||
if blob := ReadCanonicalAccessListRLP(db, number, &hash); len(blob) == 0 {
|
|
||||||
t.Fatal("ReadCanonicalAccessListRLP returned empty for frozen block")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestBALEmptyFreezer tests that pre-EIP-8189 blocks without BALs have empty
|
|
||||||
// freezer entries.
|
|
||||||
func TestBALEmptyFreezer(t *testing.T) {
|
|
||||||
frdir := t.TempDir()
|
|
||||||
db, err := Open(NewMemoryDatabase(), OpenOptions{Ancient: frdir})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create database with ancient backend: %v", err)
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
// Create and freeze a block with no BAL.
|
|
||||||
block := types.NewBlockWithHeader(&types.Header{
|
|
||||||
Number: big.NewInt(0),
|
|
||||||
Extra: []byte("no bal block"),
|
|
||||||
UncleHash: types.EmptyUncleHash,
|
|
||||||
TxHash: types.EmptyTxsHash,
|
|
||||||
ReceiptHash: types.EmptyReceiptsHash,
|
|
||||||
})
|
|
||||||
hash, number := block.Hash(), block.NumberU64()
|
|
||||||
|
|
||||||
WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil}), nil)
|
|
||||||
|
|
||||||
// HasAccessList should return false for a block with an empty freezer entry.
|
|
||||||
if HasAccessList(db, hash, number) {
|
|
||||||
t.Fatal("HasAccessList returned true for block with no BAL")
|
|
||||||
}
|
|
||||||
if b := ReadAccessList(db, hash, number); b != nil {
|
|
||||||
t.Fatalf("ReadAccessList returned non-nil for block with no BAL: %v", b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,6 @@ const (
|
||||||
|
|
||||||
// ChainFreezerReceiptTable indicates the name of the freezer receipts table.
|
// ChainFreezerReceiptTable indicates the name of the freezer receipts table.
|
||||||
ChainFreezerReceiptTable = "receipts"
|
ChainFreezerReceiptTable = "receipts"
|
||||||
|
|
||||||
// ChainFreezerBALTable indicates the name of the freezer block access list table.
|
|
||||||
ChainFreezerBALTable = "bals"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// chainFreezerTableConfigs configures the settings for tables in the chain freezer.
|
// chainFreezerTableConfigs configures the settings for tables in the chain freezer.
|
||||||
|
|
@ -49,7 +46,6 @@ var chainFreezerTableConfigs = map[string]freezerTableConfig{
|
||||||
ChainFreezerHashTable: {noSnappy: true, prunable: false},
|
ChainFreezerHashTable: {noSnappy: true, prunable: false},
|
||||||
ChainFreezerBodiesTable: {noSnappy: false, prunable: true},
|
ChainFreezerBodiesTable: {noSnappy: false, prunable: true},
|
||||||
ChainFreezerReceiptTable: {noSnappy: false, prunable: true},
|
ChainFreezerReceiptTable: {noSnappy: false, prunable: true},
|
||||||
ChainFreezerBALTable: {noSnappy: false, prunable: true},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// freezerTableConfig contains the settings for a freezer table.
|
// freezerTableConfig contains the settings for a freezer table.
|
||||||
|
|
|
||||||
|
|
@ -327,7 +327,6 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash
|
||||||
if len(receipts) == 0 {
|
if len(receipts) == 0 {
|
||||||
return fmt.Errorf("block receipts missing, can't freeze block %d", number)
|
return fmt.Errorf("block receipts missing, can't freeze block %d", number)
|
||||||
}
|
}
|
||||||
bal := ReadAccessListRLP(nfdb, hash, number)
|
|
||||||
// Write to the batch.
|
// Write to the batch.
|
||||||
if err := op.AppendRaw(ChainFreezerHashTable, number, hash[:]); err != nil {
|
if err := op.AppendRaw(ChainFreezerHashTable, number, hash[:]); err != nil {
|
||||||
return fmt.Errorf("can't write hash to Freezer: %v", err)
|
return fmt.Errorf("can't write hash to Freezer: %v", err)
|
||||||
|
|
@ -341,9 +340,6 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash
|
||||||
if err := op.AppendRaw(ChainFreezerReceiptTable, number, receipts); err != nil {
|
if err := op.AppendRaw(ChainFreezerReceiptTable, number, receipts); err != nil {
|
||||||
return fmt.Errorf("can't write receipts to Freezer: %v", err)
|
return fmt.Errorf("can't write receipts to Freezer: %v", err)
|
||||||
}
|
}
|
||||||
if err := op.AppendRaw(ChainFreezerBALTable, number, bal); err != nil {
|
|
||||||
return fmt.Errorf("can't write BAL to Freezer: %v", err)
|
|
||||||
}
|
|
||||||
hashes = append(hashes, hash)
|
hashes = append(hashes, hash)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ func TestTxIndexer(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
||||||
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...)), nil)
|
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...)))
|
||||||
|
|
||||||
// Index the initial blocks from ancient store
|
// Index the initial blocks from ancient store
|
||||||
indexer := &txIndexer{
|
indexer := &txIndexer{
|
||||||
|
|
@ -237,7 +237,7 @@ func TestTxIndexerRepair(t *testing.T) {
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
||||||
encReceipts := types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...))
|
encReceipts := types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...))
|
||||||
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), encReceipts, nil)
|
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), encReceipts)
|
||||||
|
|
||||||
// Index the initial blocks from ancient store
|
// Index the initial blocks from ancient store
|
||||||
indexer := &txIndexer{
|
indexer := &txIndexer{
|
||||||
|
|
@ -428,7 +428,7 @@ func TestTxIndexerReport(t *testing.T) {
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
||||||
encReceipts := types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...))
|
encReceipts := types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...))
|
||||||
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), encReceipts, nil)
|
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), encReceipts)
|
||||||
|
|
||||||
// Index the initial blocks from ancient store
|
// Index the initial blocks from ancient store
|
||||||
indexer := &txIndexer{
|
indexer := &txIndexer{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue