mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-15 00:13:46 +00:00
fix: add block receipt
This commit is contained in:
parent
93e2ac2733
commit
45230abb63
19 changed files with 427 additions and 43 deletions
|
|
@ -196,6 +196,8 @@ type BlockChain struct {
|
||||||
badBlocks *lru.Cache // Bad block cache
|
badBlocks *lru.Cache // Bad block cache
|
||||||
shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block.
|
shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block.
|
||||||
terminateInsert func(common.Hash, uint64) bool // Testing hook used to terminate ancient receipt chain insertion.
|
terminateInsert func(common.Hash, uint64) bool // Testing hook used to terminate ancient receipt chain insertion.
|
||||||
|
|
||||||
|
borReceiptsCache *lru.Cache // Cache for the most recent bor receipt receipts per block
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockChain returns a fully initialised block chain using information
|
// NewBlockChain returns a fully initialised block chain using information
|
||||||
|
|
@ -219,6 +221,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
||||||
futureBlocks, _ := lru.New(maxFutureBlocks)
|
futureBlocks, _ := lru.New(maxFutureBlocks)
|
||||||
badBlocks, _ := lru.New(badBlockLimit)
|
badBlocks, _ := lru.New(badBlockLimit)
|
||||||
|
|
||||||
|
borReceiptsCache, _ := lru.New(receiptsCacheLimit)
|
||||||
|
|
||||||
bc := &BlockChain{
|
bc := &BlockChain{
|
||||||
chainConfig: chainConfig,
|
chainConfig: chainConfig,
|
||||||
cacheConfig: cacheConfig,
|
cacheConfig: cacheConfig,
|
||||||
|
|
@ -236,6 +240,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
||||||
engine: engine,
|
engine: engine,
|
||||||
vmConfig: vmConfig,
|
vmConfig: vmConfig,
|
||||||
badBlocks: badBlocks,
|
badBlocks: badBlocks,
|
||||||
|
|
||||||
|
borReceiptsCache: borReceiptsCache,
|
||||||
}
|
}
|
||||||
bc.validator = NewBlockValidator(chainConfig, bc, engine)
|
bc.validator = NewBlockValidator(chainConfig, bc, engine)
|
||||||
bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine)
|
bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine)
|
||||||
|
|
@ -1155,7 +1161,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
}
|
}
|
||||||
h := rawdb.ReadCanonicalHash(bc.db, frozen)
|
h := rawdb.ReadCanonicalHash(bc.db, frozen)
|
||||||
b := rawdb.ReadBlock(bc.db, h, frozen)
|
b := rawdb.ReadBlock(bc.db, h, frozen)
|
||||||
size += rawdb.WriteAncientBlock(bc.db, b, rawdb.ReadReceipts(bc.db, h, frozen, bc.chainConfig), rawdb.ReadTd(bc.db, h, frozen))
|
size += rawdb.WriteAncientBlock(bc.db, b, rawdb.ReadReceipts(bc.db, h, frozen, bc.chainConfig), rawdb.ReadTd(bc.db, h, frozen), rawdb.ReadBorReceipt(bc.db, h, frozen))
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
// Always keep genesis block in active database.
|
// Always keep genesis block in active database.
|
||||||
|
|
@ -1198,7 +1204,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
log.Info("Migrated ancient blocks", "count", count, "elapsed", common.PrettyDuration(time.Since(start)))
|
log.Info("Migrated ancient blocks", "count", count, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
}
|
}
|
||||||
// Flush data into ancient database.
|
// Flush data into ancient database.
|
||||||
size += rawdb.WriteAncientBlock(bc.db, block, receiptChain[i], bc.GetTd(block.Hash(), block.NumberU64()))
|
size += rawdb.WriteAncientBlock(bc.db, block, receiptChain[i], bc.GetTd(block.Hash(), block.NumberU64()), bc.GetBorReceiptByHash(block.Hash()))
|
||||||
|
|
||||||
// Write tx indices if any condition is satisfied:
|
// Write tx indices if any condition is satisfied:
|
||||||
// * If user requires to reserve all tx indices(txlookuplimit=0)
|
// * If user requires to reserve all tx indices(txlookuplimit=0)
|
||||||
|
|
@ -1438,6 +1444,15 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), externTd)
|
rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), externTd)
|
||||||
rawdb.WriteBlock(blockBatch, block)
|
rawdb.WriteBlock(blockBatch, block)
|
||||||
rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts)
|
rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts)
|
||||||
|
|
||||||
|
// storing bor block receipt
|
||||||
|
blockLogs := state.Logs()
|
||||||
|
if len(blockLogs) > len(logs) {
|
||||||
|
rawdb.WriteBorReceipt(blockBatch, block.Hash(), block.NumberU64(), &types.BorReceiptForStorage{
|
||||||
|
Logs: blockLogs[len(logs):],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
rawdb.WritePreimages(blockBatch, state.Preimages())
|
rawdb.WritePreimages(blockBatch, state.Preimages())
|
||||||
if err := blockBatch.Write(); err != nil {
|
if err := blockBatch.Write(); err != nil {
|
||||||
log.Crit("Failed to write block into disk", "err", err)
|
log.Crit("Failed to write block into disk", "err", err)
|
||||||
|
|
|
||||||
30
core/bor_blockchain.go
Normal file
30
core/bor_blockchain.go
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/maticnetwork/bor/common"
|
||||||
|
"github.com/maticnetwork/bor/core/rawdb"
|
||||||
|
"github.com/maticnetwork/bor/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetBorReceiptByHash retrieves the bor block receipt in a given block.
|
||||||
|
func (bc *BlockChain) GetBorReceiptByHash(hash common.Hash) *types.BorReceipt {
|
||||||
|
if receipt, ok := bc.borReceiptsCache.Get(hash); ok {
|
||||||
|
return receipt.(*types.BorReceipt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read header from hash
|
||||||
|
number := rawdb.ReadHeaderNumber(bc.db, hash)
|
||||||
|
if number == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// read bor reciept by hash and number
|
||||||
|
receipt := rawdb.ReadBorReceipt(bc.db, hash, *number)
|
||||||
|
if receipt == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// add into bor receipt cache
|
||||||
|
bc.borReceiptsCache.Add(hash, receipt)
|
||||||
|
return receipt
|
||||||
|
}
|
||||||
|
|
@ -596,7 +596,7 @@ func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteAncientBlock writes entire block data into ancient store and returns the total written size.
|
// WriteAncientBlock writes entire block data into ancient store and returns the total written size.
|
||||||
func WriteAncientBlock(db ethdb.AncientWriter, block *types.Block, receipts types.Receipts, td *big.Int) int {
|
func WriteAncientBlock(db ethdb.AncientWriter, block *types.Block, receipts types.Receipts, td *big.Int, borReceipt *types.BorReceipt) int {
|
||||||
// Encode all block components to RLP format.
|
// Encode all block components to RLP format.
|
||||||
headerBlob, err := rlp.EncodeToBytes(block.Header())
|
headerBlob, err := rlp.EncodeToBytes(block.Header())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -618,8 +618,17 @@ func WriteAncientBlock(db ethdb.AncientWriter, block *types.Block, receipts type
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Crit("Failed to RLP encode block total difficulty", "err", err)
|
log.Crit("Failed to RLP encode block total difficulty", "err", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
borReceiptBlob := make([]byte, 0)
|
||||||
|
if borReceipt != nil {
|
||||||
|
borReceiptBlob, err = rlp.EncodeToBytes(borReceipt)
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("Failed to RLP encode bor block receipt", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write all blob to flatten files.
|
// Write all blob to flatten files.
|
||||||
err = db.AppendAncient(block.NumberU64(), block.Hash().Bytes(), headerBlob, bodyBlob, receiptBlob, tdBlob)
|
err = db.AppendAncient(block.NumberU64(), block.Hash().Bytes(), headerBlob, bodyBlob, receiptBlob, tdBlob, borReceiptBlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Crit("Failed to write block data to ancient store", "err", err)
|
log.Crit("Failed to write block data to ancient store", "err", err)
|
||||||
}
|
}
|
||||||
|
|
@ -632,6 +641,9 @@ func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||||
DeleteHeader(db, hash, number)
|
DeleteHeader(db, hash, number)
|
||||||
DeleteBody(db, hash, number)
|
DeleteBody(db, hash, number)
|
||||||
DeleteTd(db, hash, number)
|
DeleteTd(db, hash, number)
|
||||||
|
|
||||||
|
// delete bor receipt
|
||||||
|
DeleteBorReceipt(db, hash, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteBlockWithoutNumber removes all block data associated with a hash, except
|
// DeleteBlockWithoutNumber removes all block data associated with a hash, except
|
||||||
|
|
@ -641,6 +653,9 @@ func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number
|
||||||
deleteHeaderWithoutNumber(db, hash, number)
|
deleteHeaderWithoutNumber(db, hash, number)
|
||||||
DeleteBody(db, hash, number)
|
DeleteBody(db, hash, number)
|
||||||
DeleteTd(db, hash, number)
|
DeleteTd(db, hash, number)
|
||||||
|
|
||||||
|
// delete bor receipt
|
||||||
|
DeleteBorReceipt(db, hash, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindCommonAncestor returns the last common ancestor of two block headers
|
// FindCommonAncestor returns the last common ancestor of two block headers
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,7 @@ func TestAncientStorage(t *testing.T) {
|
||||||
t.Fatalf("non existent td returned")
|
t.Fatalf("non existent td returned")
|
||||||
}
|
}
|
||||||
// Write and verify the header in the database
|
// Write and verify the header in the database
|
||||||
WriteAncientBlock(db, block, nil, big.NewInt(100))
|
WriteAncientBlock(db, block, nil, big.NewInt(100), 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")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
133
core/rawdb/bor_receipt.go
Normal file
133
core/rawdb/bor_receipt.go
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
package rawdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/maticnetwork/bor/common"
|
||||||
|
"github.com/maticnetwork/bor/core/types"
|
||||||
|
"github.com/maticnetwork/bor/ethdb"
|
||||||
|
"github.com/maticnetwork/bor/log"
|
||||||
|
"github.com/maticnetwork/bor/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
borReceiptPrefix = []byte("bor-receipt-") // borReceiptPrefix + number + block hash -> bor block receipt
|
||||||
|
|
||||||
|
// freezerReceiptTable indicates the name of the freezer bor receipts table.
|
||||||
|
freezerBorReceiptTable = "bor-receipts"
|
||||||
|
)
|
||||||
|
|
||||||
|
// borReceiptKey = borReceiptPrefix + num (uint64 big endian) + hash
|
||||||
|
func borReceiptKey(number uint64, hash common.Hash) []byte {
|
||||||
|
return append(append(borReceiptPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasBorReceipt verifies the existence of all block receipt belonging
|
||||||
|
// to a block.
|
||||||
|
func HasBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||||
|
if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if has, err := db.Has(borReceiptKey(number, hash)); !has || err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadBorReceiptRLP retrieves all the transaction receipts belonging to a block in RLP encoding.
|
||||||
|
func ReadBorReceiptRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||||
|
// First try to look up the data in ancient database. Extra hash
|
||||||
|
// comparison is necessary since ancient database only maintains
|
||||||
|
// the canonical data.
|
||||||
|
data, _ := db.Ancient(freezerBorReceiptTable, number)
|
||||||
|
if len(data) > 0 {
|
||||||
|
h, _ := db.Ancient(freezerHashTable, number)
|
||||||
|
if common.BytesToHash(h) == hash {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Then try to look up the data in leveldb.
|
||||||
|
data, _ = db.Get(borReceiptKey(number, hash))
|
||||||
|
if len(data) > 0 {
|
||||||
|
fmt.Println("==> RAWDB IN ReadBorReceiptRLP", common.Bytes2Hex(data))
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
// In the background freezer is moving data from leveldb to flatten files.
|
||||||
|
// So during the first check for ancient db, the data is not yet in there,
|
||||||
|
// but when we reach into leveldb, the data was already moved. That would
|
||||||
|
// result in a not found error.
|
||||||
|
data, _ = db.Ancient(freezerReceiptTable, number)
|
||||||
|
if len(data) > 0 {
|
||||||
|
h, _ := db.Ancient(freezerHashTable, number)
|
||||||
|
if common.BytesToHash(h) == hash {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil // Can't find the data anywhere.
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadRawBorReceipt retrieves the block receipt belonging to a block.
|
||||||
|
// The receipt metadata fields are not guaranteed to be populated, so they
|
||||||
|
// should not be used. Use ReadBorReceipt instead if the metadata is needed.
|
||||||
|
func ReadRawBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) *types.BorReceipt {
|
||||||
|
// Retrieve the flattened receipt slice
|
||||||
|
data := ReadBorReceiptRLP(db, hash, number)
|
||||||
|
if data == nil || len(data) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the receipts from their storage form to their internal representation
|
||||||
|
var storageReceipt types.BorReceiptForStorage
|
||||||
|
if err := rlp.DecodeBytes(data, &storageReceipt); err != nil {
|
||||||
|
log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*types.BorReceipt)(&storageReceipt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadBorReceipt retrieves all the bor block receipts belonging to a block, including
|
||||||
|
// its correspoinding metadata fields. If it is unable to populate these metadata
|
||||||
|
// fields then nil is returned.
|
||||||
|
func ReadBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) *types.BorReceipt {
|
||||||
|
// We're deriving many fields from the block body, retrieve beside the receipt
|
||||||
|
borReceipt := ReadRawBorReceipt(db, hash, number)
|
||||||
|
if borReceipt == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
body := ReadBody(db, hash, number)
|
||||||
|
if body == nil {
|
||||||
|
log.Error("Missing body but have bor receipt", "hash", hash, "number", number)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := borReceipt.DeriveFields(hash, number); err != nil {
|
||||||
|
log.Error("Failed to derive bor receipt fields", "hash", hash, "number", number, "err", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return borReceipt
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteBorReceipt stores all the bor receipt belonging to a block.
|
||||||
|
func WriteBorReceipt(db ethdb.KeyValueWriter, hash common.Hash, number uint64, borReceipt *types.BorReceiptForStorage) {
|
||||||
|
// Convert the bor receipt into their storage form and serialize them
|
||||||
|
bytes, err := rlp.EncodeToBytes(borReceipt)
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("Failed to encode bor receipt", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the flattened receipt slice
|
||||||
|
if err := db.Put(borReceiptKey(number, hash), bytes); err != nil {
|
||||||
|
log.Crit("Failed to store bor receipt", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteBorReceipt removes receipt data associated with a block hash.
|
||||||
|
func DeleteBorReceipt(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||||
|
if err := db.Delete(borReceiptKey(number, hash)); err != nil {
|
||||||
|
log.Crit("Failed to delete bor receipt", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -79,7 +79,7 @@ func (db *nofreezedb) AncientSize(kind string) (uint64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendAncient returns an error as we don't have a backing chain freezer.
|
// AppendAncient returns an error as we don't have a backing chain freezer.
|
||||||
func (db *nofreezedb) AppendAncient(number uint64, hash, header, body, receipts, td []byte) error {
|
func (db *nofreezedb) AppendAncient(number uint64, hash, header, body, receipts, td, borBlockReceipt []byte) error {
|
||||||
return errNotSupported
|
return errNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ func (f *freezer) AncientSize(kind string) (uint64, error) {
|
||||||
// Notably, this function is lock free but kind of thread-safe. All out-of-order
|
// Notably, this function is lock free but kind of thread-safe. All out-of-order
|
||||||
// injection will be rejected. But if two injections with same number happen at
|
// injection will be rejected. But if two injections with same number happen at
|
||||||
// the same time, we can get into the trouble.
|
// the same time, we can get into the trouble.
|
||||||
func (f *freezer) AppendAncient(number uint64, hash, header, body, receipts, td []byte) (err error) {
|
func (f *freezer) AppendAncient(number uint64, hash, header, body, receipts, td, borBlockReceipt []byte) (err error) {
|
||||||
// Ensure the binary blobs we are appending is continuous with freezer.
|
// Ensure the binary blobs we are appending is continuous with freezer.
|
||||||
if atomic.LoadUint64(&f.frozen) != number {
|
if atomic.LoadUint64(&f.frozen) != number {
|
||||||
return errOutOrderInsertion
|
return errOutOrderInsertion
|
||||||
|
|
@ -217,6 +217,11 @@ func (f *freezer) AppendAncient(number uint64, hash, header, body, receipts, td
|
||||||
log.Error("Failed to append ancient difficulty", "number", f.frozen, "hash", hash, "err", err)
|
log.Error("Failed to append ancient difficulty", "number", f.frozen, "hash", hash, "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := f.tables[freezerBorReceiptTable].Append(f.frozen, borBlockReceipt); err != nil {
|
||||||
|
log.Error("Failed to append bor block receipt", "number", f.frozen, "hash", hash, "err", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
atomic.AddUint64(&f.frozen, 1) // Only modify atomically
|
atomic.AddUint64(&f.frozen, 1) // Only modify atomically
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -340,9 +345,13 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) {
|
||||||
log.Error("Total difficulty missing, can't freeze", "number", f.frozen, "hash", hash)
|
log.Error("Total difficulty missing, can't freeze", "number", f.frozen, "hash", hash)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bor block receipt
|
||||||
|
borBlockReceipt := ReadBorReceiptRLP(nfdb, hash, f.frozen)
|
||||||
|
|
||||||
log.Trace("Deep froze ancient block", "number", f.frozen, "hash", hash)
|
log.Trace("Deep froze ancient block", "number", f.frozen, "hash", hash)
|
||||||
// Inject all the components into the relevant data tables
|
// Inject all the components into the relevant data tables
|
||||||
if err := f.AppendAncient(f.frozen, hash[:], header, body, receipts, td); err != nil {
|
if err := f.AppendAncient(f.frozen, hash[:], header, body, receipts, td, borBlockReceipt); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ancients = append(ancients, hash)
|
ancients = append(ancients, hash)
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ var freezerNoSnappy = map[string]bool{
|
||||||
freezerHashTable: true,
|
freezerHashTable: true,
|
||||||
freezerBodiesTable: false,
|
freezerBodiesTable: false,
|
||||||
freezerReceiptTable: false,
|
freezerReceiptTable: false,
|
||||||
|
freezerBorReceiptTable: false,
|
||||||
freezerDifficultyTable: true,
|
freezerDifficultyTable: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,8 @@ func (t *table) AncientSize(kind string) (uint64, error) {
|
||||||
|
|
||||||
// AppendAncient is a noop passthrough that just forwards the request to the underlying
|
// AppendAncient is a noop passthrough that just forwards the request to the underlying
|
||||||
// database.
|
// database.
|
||||||
func (t *table) AppendAncient(number uint64, hash, header, body, receipts, td []byte) error {
|
func (t *table) AppendAncient(number uint64, hash, header, body, receipts, td, borBlockReceipt []byte) error {
|
||||||
return t.db.AppendAncient(number, hash, header, body, receipts, td)
|
return t.db.AppendAncient(number, hash, header, body, receipts, td, borBlockReceipt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TruncateAncients is a noop passthrough that just forwards the request to the underlying
|
// TruncateAncients is a noop passthrough that just forwards the request to the underlying
|
||||||
|
|
|
||||||
110
core/types/bor_receipt.go
Normal file
110
core/types/bor_receipt.go
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/maticnetwork/bor/common"
|
||||||
|
"github.com/maticnetwork/bor/crypto"
|
||||||
|
"github.com/maticnetwork/bor/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BorReceipt represents the results of a block state syncs
|
||||||
|
type BorReceipt struct {
|
||||||
|
// Consensus fields
|
||||||
|
Bloom Bloom `json:"logsBloom" gencodec:"required"`
|
||||||
|
Logs []*Log `json:"logs" gencodec:"required"`
|
||||||
|
|
||||||
|
// Inclusion information: These fields provide information about the inclusion of the
|
||||||
|
// transaction corresponding to this receipt.
|
||||||
|
BlockHash common.Hash `json:"blockHash,omitempty"`
|
||||||
|
BlockNumber *big.Int `json:"blockNumber,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// borReceiptRLP is the consensus encoding of a block receipt.
|
||||||
|
type borReceiptRLP struct {
|
||||||
|
Bloom Bloom
|
||||||
|
Logs []*Log
|
||||||
|
}
|
||||||
|
|
||||||
|
// storedBorReceiptRLP is the storage encoding of a block receipt.
|
||||||
|
type storedBorReceiptRLP struct {
|
||||||
|
Logs []*LogForStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a block receipt
|
||||||
|
// into an RLP stream. If no post state is present, byzantium fork is assumed.
|
||||||
|
func (r *BorReceipt) EncodeRLP(w io.Writer) error {
|
||||||
|
return rlp.Encode(w, &borReceiptRLP{r.Bloom, r.Logs})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a block receipt
|
||||||
|
// from an RLP stream.
|
||||||
|
func (r *BorReceipt) DecodeRLP(s *rlp.Stream) error {
|
||||||
|
var dec receiptRLP
|
||||||
|
if err := s.Decode(&dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.Bloom, r.Logs = dec.Bloom, dec.Logs
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BorReceiptForStorage is a wrapper around a Bor Receipt that flattens and parses the
|
||||||
|
// entire content of a receipt, as opposed to only the consensus fields originally.
|
||||||
|
type BorReceiptForStorage BorReceipt
|
||||||
|
|
||||||
|
// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
|
||||||
|
// into an RLP stream.
|
||||||
|
func (r *BorReceiptForStorage) EncodeRLP(w io.Writer) error {
|
||||||
|
enc := &storedBorReceiptRLP{
|
||||||
|
Logs: make([]*LogForStorage, len(r.Logs)),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, log := range r.Logs {
|
||||||
|
enc.Logs[i] = (*LogForStorage)(log)
|
||||||
|
}
|
||||||
|
return rlp.Encode(w, enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
|
||||||
|
// fields of a receipt from an RLP stream.
|
||||||
|
func (r *BorReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
|
||||||
|
// Retrieve the entire receipt blob as we need to try multiple decoders
|
||||||
|
blob, err := s.Raw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return decodeStoredBorReceiptRLP(r, blob)
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeStoredBorReceiptRLP(r *BorReceiptForStorage, blob []byte) error {
|
||||||
|
var stored storedBorReceiptRLP
|
||||||
|
if err := rlp.DecodeBytes(blob, &stored); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Logs = make([]*Log, len(stored.Logs))
|
||||||
|
for i, log := range stored.Logs {
|
||||||
|
r.Logs[i] = (*Log)(log)
|
||||||
|
}
|
||||||
|
r.Bloom = BytesToBloom(LogsBloom(r.Logs).Bytes())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeriveFields fills the receipts with their computed fields based on consensus
|
||||||
|
// data and contextual infos like containing block and transactions.
|
||||||
|
func (r *BorReceipt) DeriveFields(hash common.Hash, number uint64) error {
|
||||||
|
txHash := common.BytesToHash(crypto.Keccak256(append([]byte("matic-receipt-"), hash.Bytes()...)))
|
||||||
|
|
||||||
|
// The derived log fields can simply be set from the block and transaction
|
||||||
|
for j := 0; j < len(r.Logs); j++ {
|
||||||
|
r.Logs[j].BlockNumber = number
|
||||||
|
r.Logs[j].BlockHash = hash
|
||||||
|
r.Logs[j].TxHash = txHash
|
||||||
|
r.Logs[j].TxIndex = uint(0)
|
||||||
|
r.Logs[j].Index = uint(j)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
|
|
||||||
"github.com/maticnetwork/bor/accounts"
|
"github.com/maticnetwork/bor/accounts"
|
||||||
"github.com/maticnetwork/bor/common"
|
"github.com/maticnetwork/bor/common"
|
||||||
"github.com/maticnetwork/bor/consensus/bor"
|
|
||||||
"github.com/maticnetwork/bor/core"
|
"github.com/maticnetwork/bor/core"
|
||||||
"github.com/maticnetwork/bor/core/bloombits"
|
"github.com/maticnetwork/bor/core/bloombits"
|
||||||
"github.com/maticnetwork/bor/core/rawdb"
|
"github.com/maticnetwork/bor/core/rawdb"
|
||||||
|
|
@ -312,17 +311,3 @@ func (b *EthAPIBackend) ServiceFilter(ctx context.Context, session *bloombits.Ma
|
||||||
go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests)
|
go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
|
|
||||||
var api *bor.API
|
|
||||||
for _, _api := range b.eth.Engine().APIs(b.eth.BlockChain()) {
|
|
||||||
if _api.Namespace == "bor" {
|
|
||||||
api = _api.Service.(*bor.API)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
root, err := api.GetRootHash(starBlockNr, endBlockNr)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return root, nil
|
|
||||||
}
|
|
||||||
|
|
|
||||||
46
eth/bor_api_backend.go
Normal file
46
eth/bor_api_backend.go
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
package eth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
ethereum "github.com/maticnetwork/bor"
|
||||||
|
"github.com/maticnetwork/bor/common"
|
||||||
|
"github.com/maticnetwork/bor/consensus/bor"
|
||||||
|
"github.com/maticnetwork/bor/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (b *EthAPIBackend) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
|
||||||
|
var api *bor.API
|
||||||
|
for _, _api := range b.eth.Engine().APIs(b.eth.BlockChain()) {
|
||||||
|
if _api.Namespace == "bor" {
|
||||||
|
api = _api.Service.(*bor.API)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
root, err := api.GetRootHash(starBlockNr, endBlockNr)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return root, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *EthAPIBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
||||||
|
receipt := b.eth.blockchain.GetBorReceiptByHash(hash)
|
||||||
|
if receipt == nil {
|
||||||
|
return nil, ethereum.NotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return receipt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (b *EthAPIBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
|
||||||
|
// receipts := b.eth.blockchain.GetReceiptsByHash(hash)
|
||||||
|
// if receipts == nil {
|
||||||
|
// return nil, nil
|
||||||
|
// }
|
||||||
|
// logs := make([][]*types.Log, len(receipts))
|
||||||
|
// for i, receipt := range receipts {
|
||||||
|
// logs[i] = receipt.Logs
|
||||||
|
// }
|
||||||
|
// return logs, nil
|
||||||
|
// }
|
||||||
30
ethclient/bor_ethclient.go
Normal file
30
ethclient/bor_ethclient.go
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
package ethclient
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
ethereum "github.com/maticnetwork/bor"
|
||||||
|
"github.com/maticnetwork/bor/common"
|
||||||
|
"github.com/maticnetwork/bor/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetRootHash returns the merkle root of the block headers
|
||||||
|
func (ec *Client) GetRootHash(ctx context.Context, startBlockNumber uint64, endBlockNumber uint64) (string, error) {
|
||||||
|
var rootHash string
|
||||||
|
if err := ec.c.CallContext(ctx, &rootHash, "eth_getRootHash", startBlockNumber, endBlockNumber); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return rootHash, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBorBlockReceipt returns bor block receipt
|
||||||
|
func (ec *Client) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
||||||
|
var r *types.BorReceipt
|
||||||
|
err := ec.c.CallContext(ctx, &r, "eth_getBorBlockReceipt", hash)
|
||||||
|
if err == nil {
|
||||||
|
if r == nil {
|
||||||
|
return nil, ethereum.NotFound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
|
@ -522,15 +522,6 @@ func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) er
|
||||||
return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data))
|
return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRootHash returns the merkle root of the block headers
|
|
||||||
func (ec *Client) GetRootHash(ctx context.Context, startBlockNumber uint64, endBlockNumber uint64) (string, error) {
|
|
||||||
var rootHash string
|
|
||||||
if err := ec.c.CallContext(ctx, &rootHash, "eth_getRootHash", startBlockNumber, endBlockNumber); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return rootHash, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func toCallArg(msg ethereum.CallMsg) interface{} {
|
func toCallArg(msg ethereum.CallMsg) interface{} {
|
||||||
arg := map[string]interface{}{
|
arg := map[string]interface{}{
|
||||||
"from": msg.From,
|
"from": msg.From,
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ type AncientReader interface {
|
||||||
type AncientWriter interface {
|
type AncientWriter interface {
|
||||||
// AppendAncient injects all binary blobs belong to block at the end of the
|
// AppendAncient injects all binary blobs belong to block at the end of the
|
||||||
// append-only immutable table files.
|
// append-only immutable table files.
|
||||||
AppendAncient(number uint64, hash, header, body, receipt, td []byte) error
|
AppendAncient(number uint64, hash, header, body, receipt, td, borBlockReceipt []byte) error
|
||||||
|
|
||||||
// TruncateAncients discards all but the first n ancient data from the ancient store.
|
// TruncateAncients discards all but the first n ancient data from the ancient store.
|
||||||
TruncateAncients(n uint64) error
|
TruncateAncients(n uint64) error
|
||||||
|
|
|
||||||
|
|
@ -748,14 +748,6 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A
|
||||||
return res[:], state.Error()
|
return res[:], state.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublicBlockChainAPI) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
|
|
||||||
root, err := s.b.GetRootHash(ctx, starBlockNr, endBlockNr)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return root, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CallArgs represents the arguments for a call.
|
// CallArgs represents the arguments for a call.
|
||||||
type CallArgs struct {
|
type CallArgs struct {
|
||||||
From *common.Address `json:"from"`
|
From *common.Address `json:"from"`
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,10 @@ type Backend interface {
|
||||||
SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription
|
SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription
|
||||||
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
|
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
|
||||||
SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription
|
SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription
|
||||||
|
|
||||||
|
// Bor API
|
||||||
GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error)
|
GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error)
|
||||||
|
GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error)
|
||||||
|
|
||||||
// Transaction pool API
|
// Transaction pool API
|
||||||
SendTx(ctx context.Context, signedTx *types.Transaction) error
|
SendTx(ctx context.Context, signedTx *types.Transaction) error
|
||||||
|
|
|
||||||
20
internal/ethapi/bor_api.go
Normal file
20
internal/ethapi/bor_api.go
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
package ethapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/maticnetwork/bor/common"
|
||||||
|
"github.com/maticnetwork/bor/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *PublicBlockChainAPI) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
|
||||||
|
root, err := s.b.GetRootHash(ctx, starBlockNr, endBlockNr)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return root, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublicBlockChainAPI) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
||||||
|
return s.b.GetBorBlockReceipt(ctx, hash)
|
||||||
|
}
|
||||||
|
|
@ -287,3 +287,7 @@ func (b *LesApiBackend) ServiceFilter(ctx context.Context, session *bloombits.Ma
|
||||||
func (b *LesApiBackend) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
|
func (b *LesApiBackend) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
|
||||||
return "", errors.New("Not implemented")
|
return "", errors.New("Not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
||||||
|
return nil, errors.New("Not implemented")
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue