2023-07-08 17:01:26 +00:00
package jsonrpc
2020-08-11 21:09:30 +00:00
import (
"context"
2021-05-04 01:37:17 +00:00
"errors"
2020-09-26 21:01:11 +00:00
"fmt"
2021-05-04 01:37:17 +00:00
"math/big"
2020-08-11 21:09:30 +00:00
2023-01-27 04:39:34 +00:00
"github.com/ledgerwatch/erigon-lib/common"
2023-04-13 11:19:02 +00:00
"github.com/ledgerwatch/erigon-lib/common/hexutility"
2021-10-28 14:18:34 +00:00
txPoolProto "github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
2023-01-13 18:12:18 +00:00
2021-05-20 18:25:53 +00:00
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/eth/ethconfig"
"github.com/ledgerwatch/erigon/params"
2020-08-11 21:09:30 +00:00
)
2020-10-24 17:03:52 +00:00
// SendRawTransaction implements eth_sendRawTransaction. Creates new message call transaction or a contract creation for previously-signed transactions.
2023-04-13 11:19:02 +00:00
func ( api * APIImpl ) SendRawTransaction ( ctx context . Context , encodedTx hexutility . Bytes ) ( common . Hash , error ) {
2023-05-09 17:44:53 +00:00
txn , err := types . DecodeWrappedTransaction ( encodedTx )
2021-05-04 01:37:17 +00:00
if err != nil {
2023-01-27 04:39:34 +00:00
return common . Hash { } , err
2020-09-26 21:01:11 +00:00
}
2021-05-04 01:37:17 +00:00
// If the transaction fee cap is already specified, ensure the
// fee of the given transaction is _reasonable_.
if err := checkTxFee ( txn . GetPrice ( ) . ToBig ( ) , txn . GetGas ( ) , ethconfig . Defaults . RPCTxFeeCap ) ; err != nil {
2023-01-27 04:39:34 +00:00
return common . Hash { } , err
2021-05-04 01:37:17 +00:00
}
2023-10-08 01:18:14 +00:00
if ! txn . Protected ( ) && ! api . AllowUnprotectedTxs {
2023-01-27 04:39:34 +00:00
return common . Hash { } , errors . New ( "only replay-protected (EIP-155) transactions allowed over RPC" )
2021-05-04 01:37:17 +00:00
}
2023-06-11 06:18:04 +00:00
// this has been moved to prior to adding of transactions to capture the
// pre state of the db - which is used for logging in the messages below
2021-09-18 13:58:23 +00:00
tx , err := api . db . BeginRo ( ctx )
if err != nil {
2023-01-27 04:39:34 +00:00
return common . Hash { } , err
2021-09-18 13:58:23 +00:00
}
2023-06-11 06:18:04 +00:00
2021-09-18 13:58:23 +00:00
defer tx . Rollback ( )
cc , err := api . chainConfig ( tx )
if err != nil {
2023-01-27 04:39:34 +00:00
return common . Hash { } , err
2021-09-18 13:58:23 +00:00
}
2022-08-11 16:44:11 +00:00
2023-10-08 20:59:49 +00:00
if txn . Protected ( ) {
txnChainId := txn . GetChainID ( )
chainId := cc . ChainID
if chainId . Cmp ( txnChainId . ToBig ( ) ) != 0 {
return common . Hash { } , fmt . Errorf ( "invalid chain id, expected: %d got: %d" , chainId , * txnChainId )
}
2022-08-11 16:44:11 +00:00
}
2023-06-11 06:18:04 +00:00
hash := txn . Hash ( )
res , err := api . txPool . Add ( ctx , & txPoolProto . AddRequest { RlpTxs : [ ] [ ] byte { encodedTx } } )
2021-09-18 13:58:23 +00:00
if err != nil {
2023-01-27 04:39:34 +00:00
return common . Hash { } , err
2021-09-18 13:58:23 +00:00
}
2023-06-11 06:18:04 +00:00
if res . Imported [ 0 ] != txPoolProto . ImportResult_SUCCESS {
return hash , fmt . Errorf ( "%s: %s" , txPoolProto . ImportResult_name [ int32 ( res . Imported [ 0 ] ) ] , res . Errors [ 0 ] )
2021-09-18 13:58:23 +00:00
}
2021-05-04 01:37:17 +00:00
return txn . Hash ( ) , nil
2020-08-11 21:09:30 +00:00
}
2020-10-24 17:03:52 +00:00
// SendTransaction implements eth_sendTransaction. Creates new message call transaction or a contract creation if the data field contains code.
2023-01-27 04:39:34 +00:00
func ( api * APIImpl ) SendTransaction ( _ context . Context , txObject interface { } ) ( common . Hash , error ) {
return common . Hash { 0 } , fmt . Errorf ( NotImplemented , "eth_sendTransaction" )
2020-11-09 08:52:18 +00:00
}
2021-05-04 01:37:17 +00:00
// checkTxFee is an internal function used to check whether the fee of
// the given transaction is _reasonable_(under the cap).
2023-03-25 05:13:27 +00:00
func checkTxFee ( gasPrice * big . Int , gas uint64 , gasCap float64 ) error {
// Short circuit if there is no gasCap for transaction fee at all.
if gasCap == 0 {
2021-05-04 01:37:17 +00:00
return nil
}
feeEth := new ( big . Float ) . Quo ( new ( big . Float ) . SetInt ( new ( big . Int ) . Mul ( gasPrice , new ( big . Int ) . SetUint64 ( gas ) ) ) , new ( big . Float ) . SetInt ( big . NewInt ( params . Ether ) ) )
feeFloat , _ := feeEth . Float64 ( )
2023-03-25 05:13:27 +00:00
if feeFloat > gasCap {
return fmt . Errorf ( "tx fee (%.2f ether) exceeds the configured cap (%.2f ether)" , feeFloat , gasCap )
2021-05-04 01:37:17 +00:00
}
return nil
}