fix: add block receipt

This commit is contained in:
Jaynti Kanani 2020-10-17 13:52:07 +05:30
parent 93e2ac2733
commit 45230abb63
No known key found for this signature in database
GPG key ID: 4396982C976BAE5E
19 changed files with 427 additions and 43 deletions

View file

@ -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
View 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
}

View file

@ -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

View file

@ -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
View 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)
}
}

View file

@ -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
} }

View file

@ -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)

View file

@ -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,
} }

View file

@ -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
View 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
}

View file

@ -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
View 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
// }

View 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
}

View file

@ -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,

View file

@ -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

View file

@ -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"`

View file

@ -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

View 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)
}

View file

@ -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")
}