go-ethereum/internal/ethapi/bor_api.go
Pratik Patil 67fc4d87fb
Added a new RPC endpoint (bor_sendRawTransactionConditional) to support EIP-4337 Bundled Transactions (#945)
* added new api to support conditional transactions (EIP-4337) (#700)

* Refactored the code and updated the miner to check for the validity of options (#793)

* refactored the code and updated the miner to check for the validity of options

* added new errors -32003 and -32005

* added unit tests

* addressed comments

* Aa 4337 update generics (#799)

* poc

* minor bug fix

* use common.Hash

* updated UnmarshalJSON function (reference - tynes)

* fix

* done

* linters

* with test

* undo some unintentional changes

---------

Co-authored-by: Pratik Patil <pratikspatil024@gmail.com>

* handelling the block range and timestamp range, also made timestamp a pointer

---------

Co-authored-by: Evgeny Danilenko <6655321@bk.ru>

* Added filtering of conditional transactions in txpool (#920)

* added filtering of conditional transactions in txpool

* minor fix in ValidateKnownAccounts

* bug fix

* Supporting nil knownAccounts

* lints

* bundled transactions are not announced/broadcasted to the peers

* fixed after upstream merge

* few fixes

* sentry reject conditional transaction

* Changed the namespace of conditional transaction API from `eth` to `bor` (#985)

* added conditional transaction to bor namespace

* test comit

* test comit

* added conditional transaction

* namespapce changed to bor

* cleanup

* cleanup

* addressed comments

* reverted changes in ValidateKnownAccounts

* addressed comments and removed unwanted code

* addressed comments

* bug fix

* lint

* removed licence from core/types/transaction_conditional_test.go

---------

Co-authored-by: Evgeny Danilenko <6655321@bk.ru>
2023-09-13 08:28:00 +05:30

106 lines
3.9 KiB
Go

package ethapi
import (
"context"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
)
// GetRootHash returns root hash for given start and end block
func (s *BlockChainAPI) 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 *BlockChainAPI) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
return s.b.GetBorBlockReceipt(ctx, hash)
}
func (s *BlockChainAPI) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
return s.b.GetVoteOnHash(ctx, starBlockNr, endBlockNr, hash, milestoneId)
}
//
// Bor transaction utils
//
func (s *BlockChainAPI) 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.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash())
if borTx != nil {
formattedTxs := fields["transactions"].([]interface{})
if fullTx {
marshalledTx := newRPCTransaction(borTx, blockHash, blockNumber, txIndex, block.BaseFee(), s.b.ChainConfig())
// 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
}
// BorAPI provides an API to access Bor related information.
type BorAPI struct {
b Backend
}
// NewBorAPI creates a new Bor protocol API.
func NewBorAPI(b Backend) *BorAPI {
return &BorAPI{b}
}
// SendRawTransactionConditional will add the signed transaction to the transaction pool.
// The sender/bundler is responsible for signing the transaction
func (api *BorAPI) SendRawTransactionConditional(ctx context.Context, input hexutil.Bytes, options types.OptionsAA4337) (common.Hash, error) {
tx := new(types.Transaction)
if err := tx.UnmarshalBinary(input); err != nil {
return common.Hash{}, err
}
currentHeader := api.b.CurrentHeader()
currentState, _, _ := api.b.StateAndHeaderByNumber(ctx, rpc.BlockNumber(currentHeader.Number.Int64()))
// check block number range
if err := currentHeader.ValidateBlockNumberOptions4337(options.BlockNumberMin, options.BlockNumberMax); err != nil {
return common.Hash{}, &rpc.OptionsValidateError{Message: "out of block range. err: " + err.Error()}
}
// check timestamp range
if err := currentHeader.ValidateTimestampOptions4337(options.TimestampMin, options.TimestampMax); err != nil {
return common.Hash{}, &rpc.OptionsValidateError{Message: "out of time range. err: " + err.Error()}
}
// check knownAccounts length (number of slots/accounts) should be less than 1000
if err := options.KnownAccounts.ValidateLength(); err != nil {
return common.Hash{}, &rpc.KnownAccountsLimitExceededError{Message: "limit exceeded. err: " + err.Error()}
}
// check knownAccounts
if err := currentState.ValidateKnownAccounts(options.KnownAccounts); err != nil {
return common.Hash{}, &rpc.OptionsValidateError{Message: "storage error. err: " + err.Error()}
}
// put options data in Tx, to use it later while block building
tx.PutOptions(&options)
return SubmitTransaction(ctx, api.b, tx)
}
func (api *BorAPI) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
return api.b.GetVoteOnHash(ctx, starBlockNr, endBlockNr, hash, milestoneId)
}