mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-11 14:33:52 +00:00
new: add bor block tx/receipt/logs as normal entities
This commit is contained in:
parent
eeecd69289
commit
30708baafd
17 changed files with 271 additions and 131 deletions
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/maticnetwork/bor/core/types"
|
"github.com/maticnetwork/bor/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (fb *filterBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
func (fb *filterBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
||||||
number := rawdb.ReadHeaderNumber(fb.db, hash)
|
number := rawdb.ReadHeaderNumber(fb.db, hash)
|
||||||
if number == nil {
|
if number == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
||||||
|
|
@ -497,6 +497,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
|
||||||
// removed in the hc.SetHead function.
|
// removed in the hc.SetHead function.
|
||||||
rawdb.DeleteBody(db, hash, num)
|
rawdb.DeleteBody(db, hash, num)
|
||||||
rawdb.DeleteReceipts(db, hash, num)
|
rawdb.DeleteReceipts(db, hash, num)
|
||||||
|
rawdb.DeleteBorReceipt(db, hash, num)
|
||||||
}
|
}
|
||||||
// Todo(rjl493456442) txlookup, bloombits, etc
|
// Todo(rjl493456442) txlookup, bloombits, etc
|
||||||
}
|
}
|
||||||
|
|
@ -509,6 +510,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
|
||||||
bc.blockCache.Purge()
|
bc.blockCache.Purge()
|
||||||
bc.txLookupCache.Purge()
|
bc.txLookupCache.Purge()
|
||||||
bc.futureBlocks.Purge()
|
bc.futureBlocks.Purge()
|
||||||
|
bc.borReceiptsCache.Purge()
|
||||||
|
|
||||||
return bc.loadLastState()
|
return bc.loadLastState()
|
||||||
}
|
}
|
||||||
|
|
@ -1460,8 +1462,9 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(blockLogs) > len(logs) {
|
if len(blockLogs) > len(logs) {
|
||||||
rawdb.WriteBorReceipt(blockBatch, block.Hash(), block.NumberU64(), &types.BorReceiptForStorage{
|
rawdb.WriteBorReceipt(blockBatch, block.Hash(), block.NumberU64(), &types.ReceiptForStorage{
|
||||||
Logs: blockLogs[len(logs):], // get state-sync logs from `state.Logs()`
|
Status: types.ReceiptStatusSuccessful, // make receipt status successful
|
||||||
|
Logs: blockLogs[len(logs):], // get state-sync logs from `state.Logs()`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetBorReceiptByHash retrieves the bor block receipt in a given block.
|
// GetBorReceiptByHash retrieves the bor block receipt in a given block.
|
||||||
func (bc *BlockChain) GetBorReceiptByHash(hash common.Hash) *types.BorReceipt {
|
func (bc *BlockChain) GetBorReceiptByHash(hash common.Hash) *types.Receipt {
|
||||||
if receipt, ok := bc.borReceiptsCache.Get(hash); ok {
|
if receipt, ok := bc.borReceiptsCache.Get(hash); ok {
|
||||||
return receipt.(*types.BorReceipt)
|
return receipt.(*types.Receipt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// read header from hash
|
// read header from hash
|
||||||
|
|
|
||||||
|
|
@ -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, borReceipt *types.BorReceipt) int {
|
func WriteAncientBlock(db ethdb.AncientWriter, block *types.Block, receipts types.Receipts, td *big.Int, borReceipt *types.Receipt) 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 {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package rawdb
|
package rawdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/maticnetwork/bor/common"
|
"github.com/maticnetwork/bor/common"
|
||||||
"github.com/maticnetwork/bor/core/types"
|
"github.com/maticnetwork/bor/core/types"
|
||||||
"github.com/maticnetwork/bor/ethdb"
|
"github.com/maticnetwork/bor/ethdb"
|
||||||
|
|
@ -9,15 +11,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
borReceiptPrefix = []byte("bor-receipt-") // borReceiptPrefix + number + block hash -> bor block receipt
|
// bor receipt key
|
||||||
|
borReceiptKey = types.BorReceiptKey
|
||||||
|
|
||||||
|
// borTxLookupPrefix + hash -> transaction/receipt lookup metadata
|
||||||
|
borTxLookupPrefix = []byte("matic-bor-tx-lookup-")
|
||||||
|
|
||||||
// freezerBorReceiptTable indicates the name of the freezer bor receipts table.
|
// freezerBorReceiptTable indicates the name of the freezer bor receipts table.
|
||||||
freezerBorReceiptTable = "bor-receipts"
|
freezerBorReceiptTable = "matic-bor-receipts"
|
||||||
)
|
)
|
||||||
|
|
||||||
// borReceiptKey = borReceiptPrefix + num (uint64 big endian) + hash
|
// borTxLookupKey = borTxLookupPrefix + hash
|
||||||
func borReceiptKey(number uint64, hash common.Hash) []byte {
|
func borTxLookupKey(hash common.Hash) []byte {
|
||||||
return append(append(borReceiptPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
|
return append(borTxLookupPrefix, hash.Bytes()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasBorReceipt verifies the existence of all block receipt belonging
|
// HasBorReceipt verifies the existence of all block receipt belonging
|
||||||
|
|
@ -68,7 +74,7 @@ func ReadBorReceiptRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.Raw
|
||||||
// ReadRawBorReceipt retrieves the block receipt belonging to a block.
|
// ReadRawBorReceipt retrieves the block receipt belonging to a block.
|
||||||
// The receipt metadata fields are not guaranteed to be populated, so they
|
// The receipt metadata fields are not guaranteed to be populated, so they
|
||||||
// should not be used. Use ReadBorReceipt instead if the metadata is needed.
|
// should not be used. Use ReadBorReceipt instead if the metadata is needed.
|
||||||
func ReadRawBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) *types.BorReceipt {
|
func ReadRawBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) *types.Receipt {
|
||||||
// Retrieve the flattened receipt slice
|
// Retrieve the flattened receipt slice
|
||||||
data := ReadBorReceiptRLP(db, hash, number)
|
data := ReadBorReceiptRLP(db, hash, number)
|
||||||
if data == nil || len(data) == 0 {
|
if data == nil || len(data) == 0 {
|
||||||
|
|
@ -76,32 +82,38 @@ func ReadRawBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) *types.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the receipts from their storage form to their internal representation
|
// Convert the receipts from their storage form to their internal representation
|
||||||
var storageReceipt types.BorReceiptForStorage
|
var storageReceipt types.ReceiptForStorage
|
||||||
if err := rlp.DecodeBytes(data, &storageReceipt); err != nil {
|
if err := rlp.DecodeBytes(data, &storageReceipt); err != nil {
|
||||||
log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
|
log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return (*types.BorReceipt)(&storageReceipt)
|
return (*types.Receipt)(&storageReceipt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadBorReceipt retrieves all the bor block receipts belonging to a block, including
|
// ReadBorReceipt retrieves all the bor block receipts belonging to a block, including
|
||||||
// its correspoinding metadata fields. If it is unable to populate these metadata
|
// its correspoinding metadata fields. If it is unable to populate these metadata
|
||||||
// fields then nil is returned.
|
// fields then nil is returned.
|
||||||
func ReadBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) *types.BorReceipt {
|
func ReadBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) *types.Receipt {
|
||||||
// We're deriving many fields from the block body, retrieve beside the receipt
|
// We're deriving many fields from the block body, retrieve beside the receipt
|
||||||
borReceipt := ReadRawBorReceipt(db, hash, number)
|
borReceipt := ReadRawBorReceipt(db, hash, number)
|
||||||
if borReceipt == nil {
|
if borReceipt == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We're deriving many fields from the block body, retrieve beside the receipt
|
||||||
|
receipts := ReadRawReceipts(db, hash, number)
|
||||||
|
if receipts == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
body := ReadBody(db, hash, number)
|
body := ReadBody(db, hash, number)
|
||||||
if body == nil {
|
if body == nil {
|
||||||
log.Error("Missing body but have bor receipt", "hash", hash, "number", number)
|
log.Error("Missing body but have bor receipt", "hash", hash, "number", number)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := borReceipt.DeriveFields(hash, number); err != nil {
|
if err := types.DeriveFieldsForBorReceipt(borReceipt, hash, number, receipts); err != nil {
|
||||||
log.Error("Failed to derive bor receipt fields", "hash", hash, "number", number, "err", err)
|
log.Error("Failed to derive bor receipt fields", "hash", hash, "number", number, "err", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -109,7 +121,7 @@ func ReadBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) *types.Bor
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteBorReceipt stores all the bor receipt belonging to a block.
|
// WriteBorReceipt stores all the bor receipt belonging to a block.
|
||||||
func WriteBorReceipt(db ethdb.KeyValueWriter, hash common.Hash, number uint64, borReceipt *types.BorReceiptForStorage) {
|
func WriteBorReceipt(db ethdb.KeyValueWriter, hash common.Hash, number uint64, borReceipt *types.ReceiptForStorage) {
|
||||||
// Convert the bor receipt into their storage form and serialize them
|
// Convert the bor receipt into their storage form and serialize them
|
||||||
bytes, err := rlp.EncodeToBytes(borReceipt)
|
bytes, err := rlp.EncodeToBytes(borReceipt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -117,14 +129,73 @@ func WriteBorReceipt(db ethdb.KeyValueWriter, hash common.Hash, number uint64, b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the flattened receipt slice
|
// Store the flattened receipt slice
|
||||||
if err := db.Put(borReceiptKey(number, hash), bytes); err != nil {
|
key := borReceiptKey(number, hash)
|
||||||
|
if err := db.Put(key, bytes); err != nil {
|
||||||
log.Crit("Failed to store bor receipt", "err", err)
|
log.Crit("Failed to store bor receipt", "err", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write bor tx reverse lookup
|
||||||
|
WriteBorTxLookupEntry(db, types.GetDerivedBorTxHash(key), big.NewInt(0).SetUint64(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteBorReceipt removes receipt data associated with a block hash.
|
// DeleteBorReceipt removes receipt data associated with a block hash.
|
||||||
func DeleteBorReceipt(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
func DeleteBorReceipt(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||||
if err := db.Delete(borReceiptKey(number, hash)); err != nil {
|
key := borReceiptKey(number, hash)
|
||||||
|
|
||||||
|
if err := db.Delete(key); err != nil {
|
||||||
log.Crit("Failed to delete bor receipt", "err", err)
|
log.Crit("Failed to delete bor receipt", "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadBorTransaction retrieves a specific bor (fake) transaction, along with
|
||||||
|
// its added positional metadata.
|
||||||
|
func ReadBorTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) {
|
||||||
|
blockNumber := ReadBorTxLookupEntry(db, hash)
|
||||||
|
if blockNumber == nil {
|
||||||
|
return nil, common.Hash{}, 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
blockHash := ReadCanonicalHash(db, *blockNumber)
|
||||||
|
if blockHash == (common.Hash{}) {
|
||||||
|
return nil, common.Hash{}, 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
body := ReadBody(db, blockHash, *blockNumber)
|
||||||
|
if body == nil {
|
||||||
|
log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash)
|
||||||
|
return nil, common.Hash{}, 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch receipt and return it
|
||||||
|
return types.NewBorTransaction(), blockHash, *blockNumber, uint64(len(body.Transactions))
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indexes for reverse lookup
|
||||||
|
//
|
||||||
|
|
||||||
|
// ReadBorTxLookupEntry retrieves the positional metadata associated with a transaction
|
||||||
|
// hash to allow retrieving the bor transaction or bor receipt by hash.
|
||||||
|
func ReadBorTxLookupEntry(db ethdb.Reader, hash common.Hash) *uint64 {
|
||||||
|
data, _ := db.Get(borTxLookupKey(hash))
|
||||||
|
if len(data) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
number := new(big.Int).SetBytes(data).Uint64()
|
||||||
|
return &number
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteBorTxLookupEntry stores a positional metadata for bor transaction.
|
||||||
|
func WriteBorTxLookupEntry(db ethdb.KeyValueWriter, hash common.Hash, number *big.Int) {
|
||||||
|
if err := db.Put(borTxLookupKey(hash), number.Bytes()); err != nil {
|
||||||
|
log.Crit("Failed to store bor transaction lookup entry", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteBorTxLookupEntry removes bor transaction data associated with a hash.
|
||||||
|
func DeleteBorTxLookupEntry(db ethdb.KeyValueWriter, hash common.Hash) {
|
||||||
|
if err := db.Delete(borTxLookupKey(hash)); err != nil {
|
||||||
|
log.Crit("Failed to delete bor transaction lookup entry", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,109 +1,73 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"encoding/binary"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/maticnetwork/bor/common"
|
"github.com/maticnetwork/bor/common"
|
||||||
"github.com/maticnetwork/bor/rlp"
|
"github.com/maticnetwork/bor/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BorReceipt represents the results of a block state syncs
|
var (
|
||||||
type BorReceipt struct {
|
borReceiptPrefix = []byte("matic-bor-receipt-") // borReceiptPrefix + number + block hash -> bor block receipt
|
||||||
// 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
|
// SystemAddress address for system sender
|
||||||
// transaction corresponding to this receipt.
|
SystemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE")
|
||||||
BlockHash common.Hash `json:"blockHash,omitempty"`
|
)
|
||||||
BlockNumber *big.Int `json:"blockNumber,omitempty"`
|
|
||||||
|
// BorReceiptKey = borReceiptPrefix + num (uint64 big endian) + hash
|
||||||
|
func BorReceiptKey(number uint64, hash common.Hash) []byte {
|
||||||
|
enc := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(enc, number)
|
||||||
|
return append(append(borReceiptPrefix, enc...), hash.Bytes()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// borReceiptRLP is the consensus encoding of a block receipt.
|
// GetDerivedBorTxHash get derived tx hash from receipt key
|
||||||
type borReceiptRLP struct {
|
func GetDerivedBorTxHash(receiptKey []byte) common.Hash {
|
||||||
Bloom Bloom
|
return common.BytesToHash(crypto.Keccak256(receiptKey))
|
||||||
Logs []*Log
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// storedBorReceiptRLP is the storage encoding of a block receipt.
|
// NewBorTransaction create new bor transaction for bor receipt
|
||||||
type storedBorReceiptRLP struct {
|
func NewBorTransaction() *Transaction {
|
||||||
Logs []*LogForStorage
|
return NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), make([]byte, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a block receipt
|
// DeriveFieldsForBorReceipt fills the receipts with their computed fields based on consensus
|
||||||
// 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.
|
// data and contextual infos like containing block and transactions.
|
||||||
func (r *BorReceipt) DeriveFields(hash common.Hash, number uint64) error {
|
func DeriveFieldsForBorReceipt(receipt *Receipt, hash common.Hash, number uint64, receipts Receipts) error {
|
||||||
// txHash := common.BytesToHash(crypto.Keccak256(append([]byte("bor-receipt-"), hash.Bytes()...)))
|
// get derived tx hash
|
||||||
|
txHash := GetDerivedBorTxHash(BorReceiptKey(number, hash))
|
||||||
|
txIndex := uint(len(receipts))
|
||||||
|
|
||||||
|
// set tx hash and tx index
|
||||||
|
receipt.TxHash = txHash
|
||||||
|
receipt.TransactionIndex = txIndex
|
||||||
|
receipt.BlockHash = hash
|
||||||
|
receipt.BlockNumber = big.NewInt(0).SetUint64(number)
|
||||||
|
|
||||||
|
logIndex := 0
|
||||||
|
for i := 0; i < len(receipts); i++ {
|
||||||
|
logIndex += len(receipts[i].Logs)
|
||||||
|
}
|
||||||
|
|
||||||
// The derived log fields can simply be set from the block and transaction
|
// The derived log fields can simply be set from the block and transaction
|
||||||
for j := 0; j < len(r.Logs); j++ {
|
for j := 0; j < len(receipt.Logs); j++ {
|
||||||
r.Logs[j].BlockNumber = number
|
receipt.Logs[j].BlockNumber = number
|
||||||
r.Logs[j].BlockHash = hash
|
receipt.Logs[j].BlockHash = hash
|
||||||
// r.Logs[j].TxHash = txHash
|
receipt.Logs[j].TxHash = txHash
|
||||||
r.Logs[j].TxIndex = uint(0)
|
receipt.Logs[j].TxIndex = txIndex
|
||||||
r.Logs[j].Index = uint(j)
|
receipt.Logs[j].Index = uint(logIndex)
|
||||||
|
logIndex++
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MergeBorLogs merges receipt logs and block receipt logs
|
||||||
|
func MergeBorLogs(logs []*Log, borLogs []*Log) []*Log {
|
||||||
|
result := append(logs, borLogs...)
|
||||||
|
sort.SliceStable(result, func(i int, j int) bool {
|
||||||
|
return (result[i].BlockNumber*100000 + uint64(result[i].Index)) < (result[j].BlockNumber*100000 + uint64(result[j].Index))
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -704,6 +704,16 @@ func (api *PrivateDebugAPI) computeStateDB(block *types.Block, reexec uint64) (*
|
||||||
func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
|
func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
|
||||||
// Retrieve the transaction and assemble its EVM context
|
// Retrieve the transaction and assemble its EVM context
|
||||||
tx, blockHash, _, index := rawdb.ReadTransaction(api.eth.ChainDb(), hash)
|
tx, blockHash, _, index := rawdb.ReadTransaction(api.eth.ChainDb(), hash)
|
||||||
|
if tx == nil {
|
||||||
|
// For BorTransaction, there will be no trace available
|
||||||
|
tx, _, _, _ = rawdb.ReadBorTransaction(api.eth.ChainDb(), hash)
|
||||||
|
if tx != nil {
|
||||||
|
return ðapi.ExecutionResult{
|
||||||
|
StructLogs: make([]ethapi.StructLogRes, 0),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if tx == nil {
|
if tx == nil {
|
||||||
return nil, fmt.Errorf("transaction %#x not found", hash)
|
return nil, fmt.Errorf("transaction %#x not found", hash)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
ethereum "github.com/maticnetwork/bor"
|
ethereum "github.com/maticnetwork/bor"
|
||||||
"github.com/maticnetwork/bor/common"
|
"github.com/maticnetwork/bor/common"
|
||||||
"github.com/maticnetwork/bor/consensus/bor"
|
"github.com/maticnetwork/bor/consensus/bor"
|
||||||
|
"github.com/maticnetwork/bor/core/rawdb"
|
||||||
"github.com/maticnetwork/bor/core/types"
|
"github.com/maticnetwork/bor/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -24,7 +25,7 @@ func (b *EthAPIBackend) GetRootHash(ctx context.Context, starBlockNr uint64, end
|
||||||
return root, nil
|
return root, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
func (b *EthAPIBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
||||||
receipt := b.eth.blockchain.GetBorReceiptByHash(hash)
|
receipt := b.eth.blockchain.GetBorReceiptByHash(hash)
|
||||||
if receipt == nil {
|
if receipt == nil {
|
||||||
return nil, ethereum.NotFound
|
return nil, ethereum.NotFound
|
||||||
|
|
@ -40,3 +41,8 @@ func (b *EthAPIBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) (
|
||||||
}
|
}
|
||||||
return receipt.Logs, nil
|
return receipt.Logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *EthAPIBackend) GetBorBlockTransaction(ctx context.Context, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
|
||||||
|
tx, blockHash, blockNumber, index := rawdb.ReadBorTransaction(b.eth.ChainDb(), hash)
|
||||||
|
return tx, blockHash, blockNumber, index, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -357,9 +357,12 @@ func (api *PublicFilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) {
|
||||||
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs
|
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs
|
||||||
func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
|
func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
|
||||||
var filter *Filter
|
var filter *Filter
|
||||||
|
var borLogsFilter *BorBlockLogsFilter
|
||||||
if crit.BlockHash != nil {
|
if crit.BlockHash != nil {
|
||||||
// Block filter requested, construct a single-shot filter
|
// Block filter requested, construct a single-shot filter
|
||||||
filter = NewBlockFilter(api.backend, *crit.BlockHash, crit.Addresses, crit.Topics)
|
filter = NewBlockFilter(api.backend, *crit.BlockHash, crit.Addresses, crit.Topics)
|
||||||
|
// Block bor filter
|
||||||
|
borLogsFilter = NewBorBlockLogsFilter(api.backend, *crit.BlockHash, crit.Addresses, crit.Topics)
|
||||||
} else {
|
} else {
|
||||||
// Convert the RPC block numbers into internal representations
|
// Convert the RPC block numbers into internal representations
|
||||||
begin := rpc.LatestBlockNumber.Int64()
|
begin := rpc.LatestBlockNumber.Int64()
|
||||||
|
|
@ -372,13 +375,23 @@ func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([
|
||||||
}
|
}
|
||||||
// Construct the range filter
|
// Construct the range filter
|
||||||
filter = NewRangeFilter(api.backend, begin, end, crit.Addresses, crit.Topics)
|
filter = NewRangeFilter(api.backend, begin, end, crit.Addresses, crit.Topics)
|
||||||
|
// Block bor filter
|
||||||
|
borLogsFilter = NewBorBlockLogsRangeFilter(api.backend, begin, end, crit.Addresses, crit.Topics)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the filter and return all the logs
|
// Run the filter and return all the logs
|
||||||
logs, err := filter.Logs(ctx)
|
logs, err := filter.Logs(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return returnLogs(logs), err
|
// Run the filter and return all the logs
|
||||||
|
borBlockLogs, err := borLogsFilter.Logs(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge bor block logs and receipt logs and return it
|
||||||
|
return returnLogs(types.MergeBorLogs(logs, borBlockLogs)), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UninstallFilter removes the filter with the given filter id.
|
// UninstallFilter removes the filter with the given filter id.
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ func (f *BorBlockLogsFilter) Logs(ctx context.Context) ([]*types.Log, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjust begin for sprint
|
// adjust begin for sprint
|
||||||
f.begin = nextSprintEnd(f.begin)
|
f.begin = currentSprintEnd(f.begin)
|
||||||
|
|
||||||
end := f.end
|
end := f.end
|
||||||
if f.end == -1 {
|
if f.end == -1 {
|
||||||
|
|
@ -136,15 +136,14 @@ func (f *BorBlockLogsFilter) unindexedLogs(ctx context.Context, end uint64) ([]*
|
||||||
}
|
}
|
||||||
|
|
||||||
// borBlockLogs returns the logs matching the filter criteria within a single block.
|
// borBlockLogs returns the logs matching the filter criteria within a single block.
|
||||||
func (f *BorBlockLogsFilter) borBlockLogs(ctx context.Context, receipt *types.BorReceipt) (logs []*types.Log, err error) {
|
func (f *BorBlockLogsFilter) borBlockLogs(ctx context.Context, receipt *types.Receipt) (logs []*types.Log, err error) {
|
||||||
if bloomFilter(receipt.Bloom, f.addresses, f.topics) {
|
if bloomFilter(receipt.Bloom, f.addresses, f.topics) {
|
||||||
found := filterLogs(receipt.Logs, nil, nil, f.addresses, f.topics)
|
logs = filterLogs(receipt.Logs, nil, nil, f.addresses, f.topics)
|
||||||
logs = append(logs, found...)
|
|
||||||
}
|
}
|
||||||
return logs, nil
|
return logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func nextSprintEnd(n int64) int64 {
|
func currentSprintEnd(n int64) int64 {
|
||||||
m := n % 64
|
m := n % 64
|
||||||
if m == 0 {
|
if m == 0 {
|
||||||
return n
|
return n
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/maticnetwork/bor/core/types"
|
"github.com/maticnetwork/bor/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *testBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
func (b *testBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
||||||
number := rawdb.ReadHeaderNumber(b.db, hash)
|
number := rawdb.ReadHeaderNumber(b.db, hash)
|
||||||
if number == nil {
|
if number == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ type Backend interface {
|
||||||
HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error)
|
HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error)
|
||||||
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
|
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
|
||||||
GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error)
|
GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error)
|
||||||
GetBorBlockReceipt(ctx context.Context, blockHash common.Hash) (*types.BorReceipt, error)
|
GetBorBlockReceipt(ctx context.Context, blockHash common.Hash) (*types.Receipt, error)
|
||||||
GetBorBlockLogs(ctx context.Context, blockHash common.Hash) ([]*types.Log, error)
|
GetBorBlockLogs(ctx context.Context, blockHash common.Hash) ([]*types.Log, error)
|
||||||
|
|
||||||
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
|
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ func (ec *Client) GetRootHash(ctx context.Context, startBlockNumber uint64, endB
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBorBlockReceipt returns bor block receipt
|
// GetBorBlockReceipt returns bor block receipt
|
||||||
func (ec *Client) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
func (ec *Client) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
||||||
var r *types.BorReceipt
|
var r *types.Receipt
|
||||||
err := ec.c.CallContext(ctx, &r, "eth_getBorBlockReceipt", hash)
|
err := ec.c.CallContext(ctx, &r, "eth_getBorBlockReceipt", hash)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
|
|
|
||||||
|
|
@ -661,6 +661,12 @@ func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.B
|
||||||
response[field] = nil
|
response[field] = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// append marshalled bor transaction
|
||||||
|
if err == nil && response != nil {
|
||||||
|
response = s.appendRPCMarshalBorTransaction(ctx, block, response, fullTx)
|
||||||
|
}
|
||||||
|
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -671,7 +677,12 @@ func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.B
|
||||||
func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
|
func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
|
||||||
block, err := s.b.BlockByHash(ctx, hash)
|
block, err := s.b.BlockByHash(ctx, hash)
|
||||||
if block != nil {
|
if block != nil {
|
||||||
return s.rpcMarshalBlock(block, true, fullTx)
|
response, err := s.rpcMarshalBlock(block, true, fullTx)
|
||||||
|
// append marshalled bor transaction
|
||||||
|
if err == nil && response != nil {
|
||||||
|
return s.appendRPCMarshalBorTransaction(ctx, block, response, fullTx), err
|
||||||
|
}
|
||||||
|
return response, err
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -1357,14 +1368,33 @@ func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr
|
||||||
|
|
||||||
// GetTransactionByHash returns the transaction for the given hash
|
// GetTransactionByHash returns the transaction for the given hash
|
||||||
func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
|
func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
|
||||||
|
borTx := false
|
||||||
|
|
||||||
// Try to return an already finalized transaction
|
// Try to return an already finalized transaction
|
||||||
tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
|
tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if tx != nil {
|
|
||||||
return newRPCTransaction(tx, blockHash, blockNumber, index), nil
|
// fetch bor block tx if necessary
|
||||||
|
if tx == nil {
|
||||||
|
if tx, blockHash, blockNumber, index, err = s.b.GetBorBlockTransaction(ctx, hash); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
borTx = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tx != nil {
|
||||||
|
resultTx := newRPCTransaction(tx, blockHash, blockNumber, index)
|
||||||
|
if borTx {
|
||||||
|
// newRPCTransaction calculates hash based on RLP of the transaction data.
|
||||||
|
// In case of bor block tx, we need simple derived tx hash (same as function argument) instead of RLP hash
|
||||||
|
resultTx.Hash = hash
|
||||||
|
}
|
||||||
|
return resultTx, nil
|
||||||
|
}
|
||||||
|
|
||||||
// No finalized transaction, try to retrieve it from the pool
|
// No finalized transaction, try to retrieve it from the pool
|
||||||
if tx := s.b.GetPoolTransaction(hash); tx != nil {
|
if tx := s.b.GetPoolTransaction(hash); tx != nil {
|
||||||
return newRPCPendingTransaction(tx), nil
|
return newRPCPendingTransaction(tx), nil
|
||||||
|
|
@ -1393,18 +1423,33 @@ func (s *PublicTransactionPoolAPI) GetRawTransactionByHash(ctx context.Context,
|
||||||
|
|
||||||
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
|
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
|
||||||
func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
|
func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
|
||||||
|
borTx := false
|
||||||
|
|
||||||
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(s.b.ChainDb(), hash)
|
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(s.b.ChainDb(), hash)
|
||||||
|
if tx == nil {
|
||||||
|
tx, blockHash, blockNumber, index = rawdb.ReadBorTransaction(s.b.ChainDb(), hash)
|
||||||
|
borTx = true
|
||||||
|
}
|
||||||
|
|
||||||
if tx == nil {
|
if tx == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
receipts, err := s.b.GetReceipts(ctx, blockHash)
|
|
||||||
if err != nil {
|
var receipt *types.Receipt
|
||||||
return nil, err
|
|
||||||
|
if borTx {
|
||||||
|
// Fetch bor block receipt
|
||||||
|
receipt = rawdb.ReadBorReceipt(s.b.ChainDb(), blockHash, blockNumber)
|
||||||
|
} else {
|
||||||
|
receipts, err := s.b.GetReceipts(ctx, blockHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(receipts) <= int(index) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
receipt = receipts[index]
|
||||||
}
|
}
|
||||||
if len(receipts) <= int(index) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
receipt := receipts[index]
|
|
||||||
|
|
||||||
var signer types.Signer = types.FrontierSigner{}
|
var signer types.Signer = types.FrontierSigner{}
|
||||||
if tx.Protected() {
|
if tx.Protected() {
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,9 @@ type Backend interface {
|
||||||
|
|
||||||
// Bor API
|
// 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)
|
GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error)
|
||||||
GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error)
|
GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error)
|
||||||
|
GetBorBlockTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
||||||
|
|
||||||
// Transaction pool API
|
// Transaction pool API
|
||||||
SendTx(ctx context.Context, signedTx *types.Transaction) error
|
SendTx(ctx context.Context, signedTx *types.Transaction) error
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,30 @@ func (s *PublicBlockChainAPI) GetRootHash(ctx context.Context, starBlockNr uint6
|
||||||
return root, nil
|
return root, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublicBlockChainAPI) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
func (s *PublicBlockChainAPI) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
||||||
return s.b.GetBorBlockReceipt(ctx, hash)
|
return s.b.GetBorBlockReceipt(ctx, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Bor transaction utils
|
||||||
|
//
|
||||||
|
|
||||||
|
func (s *PublicBlockChainAPI) appendRPCMarshalBorTransaction(ctx context.Context, block *types.Block, fields map[string]interface{}, fullTx bool) map[string]interface{} {
|
||||||
|
if block != nil {
|
||||||
|
txHash := types.GetDerivedBorTxHash(types.BorReceiptKey(block.Number().Uint64(), block.Hash()))
|
||||||
|
borTx, blockHash, blockNumber, txIndex, _ := s.b.GetBorBlockTransaction(ctx, txHash)
|
||||||
|
if borTx != nil {
|
||||||
|
formattedTxs := fields["transactions"].([]interface{})
|
||||||
|
if fullTx {
|
||||||
|
marshalledTx := newRPCTransaction(borTx, blockHash, blockNumber, txIndex)
|
||||||
|
// newRPCTransaction calculates hash based on RLP of the transaction data.
|
||||||
|
// In case of bor block tx, we need simple derived tx hash (same as function argument) instead of RLP hash
|
||||||
|
marshalledTx.Hash = txHash
|
||||||
|
fields["transactions"] = append(formattedTxs, marshalledTx)
|
||||||
|
} else {
|
||||||
|
fields["transactions"] = append(formattedTxs, txHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -288,10 +288,14 @@ func (b *LesApiBackend) GetRootHash(ctx context.Context, starBlockNr uint64, end
|
||||||
return "", errors.New("Not implemented")
|
return "", errors.New("Not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
|
func (b *LesApiBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
||||||
return nil, errors.New("Not implemented")
|
return nil, errors.New("Not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
|
func (b *LesApiBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
|
||||||
return nil, errors.New("Not implemented")
|
return nil, errors.New("Not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) GetBorBlockTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
|
||||||
|
return nil, common.Hash{}, 0, 0, errors.New("Not implemented")
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue