new: add bor block tx/receipt/logs as normal entities

This commit is contained in:
Jaynti Kanani 2020-10-26 15:43:07 +05:30
parent eeecd69289
commit 30708baafd
No known key found for this signature in database
GPG key ID: 4396982C976BAE5E
17 changed files with 271 additions and 131 deletions

View file

@ -8,7 +8,7 @@ import (
"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)
if number == nil {
return nil, nil

View file

@ -497,6 +497,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
// removed in the hc.SetHead function.
rawdb.DeleteBody(db, hash, num)
rawdb.DeleteReceipts(db, hash, num)
rawdb.DeleteBorReceipt(db, hash, num)
}
// Todo(rjl493456442) txlookup, bloombits, etc
}
@ -509,6 +510,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
bc.blockCache.Purge()
bc.txLookupCache.Purge()
bc.futureBlocks.Purge()
bc.borReceiptsCache.Purge()
return bc.loadLastState()
}
@ -1460,8 +1462,9 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
})
if len(blockLogs) > len(logs) {
rawdb.WriteBorReceipt(blockBatch, block.Hash(), block.NumberU64(), &types.BorReceiptForStorage{
Logs: blockLogs[len(logs):], // get state-sync logs from `state.Logs()`
rawdb.WriteBorReceipt(blockBatch, block.Hash(), block.NumberU64(), &types.ReceiptForStorage{
Status: types.ReceiptStatusSuccessful, // make receipt status successful
Logs: blockLogs[len(logs):], // get state-sync logs from `state.Logs()`
})
}
}

View file

@ -7,9 +7,9 @@ import (
)
// 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 {
return receipt.(*types.BorReceipt)
return receipt.(*types.Receipt)
}
// read header from hash

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.
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.
headerBlob, err := rlp.EncodeToBytes(block.Header())
if err != nil {

View file

@ -1,6 +1,8 @@
package rawdb
import (
"math/big"
"github.com/maticnetwork/bor/common"
"github.com/maticnetwork/bor/core/types"
"github.com/maticnetwork/bor/ethdb"
@ -9,15 +11,19 @@ import (
)
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 = "bor-receipts"
freezerBorReceiptTable = "matic-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()...)
// borTxLookupKey = borTxLookupPrefix + hash
func borTxLookupKey(hash common.Hash) []byte {
return append(borTxLookupPrefix, hash.Bytes()...)
}
// 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.
// 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 {
func ReadRawBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) *types.Receipt {
// Retrieve the flattened receipt slice
data := ReadBorReceiptRLP(db, hash, number)
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
var storageReceipt types.BorReceiptForStorage
var storageReceipt types.ReceiptForStorage
if err := rlp.DecodeBytes(data, &storageReceipt); err != nil {
log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
return nil
}
return (*types.BorReceipt)(&storageReceipt)
return (*types.Receipt)(&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 {
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
borReceipt := ReadRawBorReceipt(db, hash, number)
if borReceipt == 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)
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 {
if err := types.DeriveFieldsForBorReceipt(borReceipt, hash, number, receipts); err != nil {
log.Error("Failed to derive bor receipt fields", "hash", hash, "number", number, "err", err)
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.
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
bytes, err := rlp.EncodeToBytes(borReceipt)
if err != nil {
@ -117,14 +129,73 @@ func WriteBorReceipt(db ethdb.KeyValueWriter, hash common.Hash, number uint64, b
}
// 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)
}
// Write bor tx reverse lookup
WriteBorTxLookupEntry(db, types.GetDerivedBorTxHash(key), big.NewInt(0).SetUint64(number))
}
// 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 {
key := borReceiptKey(number, hash)
if err := db.Delete(key); err != nil {
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)
}
}

View file

@ -1,109 +1,73 @@
package types
import (
"io"
"encoding/binary"
"math/big"
"sort"
"github.com/maticnetwork/bor/common"
"github.com/maticnetwork/bor/rlp"
"github.com/maticnetwork/bor/crypto"
)
// 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"`
var (
borReceiptPrefix = []byte("matic-bor-receipt-") // borReceiptPrefix + number + block hash -> bor block receipt
// 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"`
// SystemAddress address for system sender
SystemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE")
)
// 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.
type borReceiptRLP struct {
Bloom Bloom
Logs []*Log
// GetDerivedBorTxHash get derived tx hash from receipt key
func GetDerivedBorTxHash(receiptKey []byte) common.Hash {
return common.BytesToHash(crypto.Keccak256(receiptKey))
}
// storedBorReceiptRLP is the storage encoding of a block receipt.
type storedBorReceiptRLP struct {
Logs []*LogForStorage
// NewBorTransaction create new bor transaction for bor receipt
func NewBorTransaction() *Transaction {
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
// 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
// DeriveFieldsForBorReceipt 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("bor-receipt-"), hash.Bytes()...)))
func DeriveFieldsForBorReceipt(receipt *Receipt, hash common.Hash, number uint64, receipts Receipts) error {
// 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
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)
for j := 0; j < len(receipt.Logs); j++ {
receipt.Logs[j].BlockNumber = number
receipt.Logs[j].BlockHash = hash
receipt.Logs[j].TxHash = txHash
receipt.Logs[j].TxIndex = txIndex
receipt.Logs[j].Index = uint(logIndex)
logIndex++
}
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
}

View file

@ -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) {
// Retrieve the transaction and assemble its EVM context
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 &ethapi.ExecutionResult{
StructLogs: make([]ethapi.StructLogRes, 0),
}, nil
}
}
if tx == nil {
return nil, fmt.Errorf("transaction %#x not found", hash)
}

View file

@ -6,6 +6,7 @@ import (
ethereum "github.com/maticnetwork/bor"
"github.com/maticnetwork/bor/common"
"github.com/maticnetwork/bor/consensus/bor"
"github.com/maticnetwork/bor/core/rawdb"
"github.com/maticnetwork/bor/core/types"
)
@ -24,7 +25,7 @@ func (b *EthAPIBackend) GetRootHash(ctx context.Context, starBlockNr uint64, end
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)
if receipt == nil {
return nil, ethereum.NotFound
@ -40,3 +41,8 @@ func (b *EthAPIBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) (
}
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
}

View file

@ -357,9 +357,12 @@ func (api *PublicFilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) {
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs
func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
var filter *Filter
var borLogsFilter *BorBlockLogsFilter
if crit.BlockHash != nil {
// Block filter requested, construct a single-shot filter
filter = NewBlockFilter(api.backend, *crit.BlockHash, crit.Addresses, crit.Topics)
// Block bor filter
borLogsFilter = NewBorBlockLogsFilter(api.backend, *crit.BlockHash, crit.Addresses, crit.Topics)
} else {
// Convert the RPC block numbers into internal representations
begin := rpc.LatestBlockNumber.Int64()
@ -372,13 +375,23 @@ func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([
}
// Construct the range filter
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
logs, err := filter.Logs(ctx)
if err != nil {
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.

View file

@ -97,7 +97,7 @@ func (f *BorBlockLogsFilter) Logs(ctx context.Context) ([]*types.Log, error) {
}
// adjust begin for sprint
f.begin = nextSprintEnd(f.begin)
f.begin = currentSprintEnd(f.begin)
end := f.end
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.
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) {
found := filterLogs(receipt.Logs, nil, nil, f.addresses, f.topics)
logs = append(logs, found...)
logs = filterLogs(receipt.Logs, nil, nil, f.addresses, f.topics)
}
return logs, nil
}
func nextSprintEnd(n int64) int64 {
func currentSprintEnd(n int64) int64 {
m := n % 64
if m == 0 {
return n

View file

@ -8,7 +8,7 @@ import (
"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)
if number == nil {
return nil, nil

View file

@ -36,7 +36,7 @@ type Backend interface {
HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error)
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, 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)
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription

View file

@ -18,8 +18,8 @@ func (ec *Client) GetRootHash(ctx context.Context, startBlockNumber uint64, endB
}
// GetBorBlockReceipt returns bor block receipt
func (ec *Client) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.BorReceipt, error) {
var r *types.BorReceipt
func (ec *Client) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
var r *types.Receipt
err := ec.c.CallContext(ctx, &r, "eth_getBorBlockReceipt", hash)
if err == nil {
if r == nil {

View file

@ -661,6 +661,12 @@ func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.B
response[field] = nil
}
}
// append marshalled bor transaction
if err == nil && response != nil {
response = s.appendRPCMarshalBorTransaction(ctx, block, response, fullTx)
}
return response, 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) {
block, err := s.b.BlockByHash(ctx, hash)
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
}
@ -1357,14 +1368,33 @@ func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr
// GetTransactionByHash returns the transaction for the given hash
func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
borTx := false
// Try to return an already finalized transaction
tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
if err != nil {
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
if tx := s.b.GetPoolTransaction(hash); 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.
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)
if tx == nil {
tx, blockHash, blockNumber, index = rawdb.ReadBorTransaction(s.b.ChainDb(), hash)
borTx = true
}
if tx == nil {
return nil, nil
}
receipts, err := s.b.GetReceipts(ctx, blockHash)
if err != nil {
return nil, err
var receipt *types.Receipt
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{}
if tx.Protected() {

View file

@ -68,8 +68,9 @@ type Backend interface {
// Bor API
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)
GetBorBlockTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
// Transaction pool API
SendTx(ctx context.Context, signedTx *types.Transaction) error

View file

@ -15,6 +15,30 @@ func (s *PublicBlockChainAPI) GetRootHash(ctx context.Context, starBlockNr uint6
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)
}
//
// 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
}

View file

@ -288,10 +288,14 @@ func (b *LesApiBackend) GetRootHash(ctx context.Context, starBlockNr uint64, end
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")
}
func (b *LesApiBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
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")
}