mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-24 12:37:16 +00:00
8749fb4a70
* cmd: make sure chain config is initialied before accessing it * cmd: avoid using lazy field directly
105 lines
3.6 KiB
Go
105 lines
3.6 KiB
Go
package commands
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
|
|
txPoolProto "github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
|
|
"github.com/ledgerwatch/erigon/common"
|
|
"github.com/ledgerwatch/erigon/common/hexutil"
|
|
"github.com/ledgerwatch/erigon/core/rawdb"
|
|
"github.com/ledgerwatch/erigon/core/types"
|
|
"github.com/ledgerwatch/erigon/crypto"
|
|
"github.com/ledgerwatch/erigon/eth/ethconfig"
|
|
"github.com/ledgerwatch/erigon/params"
|
|
"github.com/ledgerwatch/erigon/rlp"
|
|
"github.com/ledgerwatch/log/v3"
|
|
)
|
|
|
|
// SendRawTransaction implements eth_sendRawTransaction. Creates new message call transaction or a contract creation for previously-signed transactions.
|
|
func (api *APIImpl) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) {
|
|
txn, err := types.DecodeTransaction(rlp.NewStream(bytes.NewReader(encodedTx), uint64(len(encodedTx))))
|
|
if err != nil {
|
|
return common.Hash{}, err
|
|
}
|
|
|
|
// 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 {
|
|
return common.Hash{}, err
|
|
}
|
|
if !txn.Protected() {
|
|
return common.Hash{}, errors.New("only replay-protected (EIP-155) transactions allowed over RPC")
|
|
}
|
|
hash := txn.Hash()
|
|
res, err := api.txPool.Add(ctx, &txPoolProto.AddRequest{RlpTxs: [][]byte{encodedTx}})
|
|
if err != nil {
|
|
return common.Hash{}, err
|
|
}
|
|
|
|
if res.Imported[0] != txPoolProto.ImportResult_SUCCESS {
|
|
return hash, fmt.Errorf("%s: %s", txPoolProto.ImportResult_name[int32(res.Imported[0])], res.Errors[0])
|
|
}
|
|
|
|
tx, err := api.db.BeginRo(ctx)
|
|
if err != nil {
|
|
return common.Hash{}, err
|
|
}
|
|
defer tx.Rollback()
|
|
|
|
// Print a log with full txn details for manual investigations and interventions
|
|
blockNum := rawdb.ReadCurrentBlockNumber(tx)
|
|
if blockNum == nil {
|
|
return common.Hash{}, err
|
|
}
|
|
cc, err := api.chainConfig(tx)
|
|
if err != nil {
|
|
return common.Hash{}, err
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
signer := types.MakeSigner(cc, *blockNum)
|
|
from, err := txn.Sender(*signer)
|
|
if err != nil {
|
|
return common.Hash{}, err
|
|
}
|
|
|
|
if txn.GetTo() == nil {
|
|
addr := crypto.CreateAddress(from, txn.GetNonce())
|
|
log.Info("Submitted contract creation", "hash", txn.Hash().Hex(), "from", from, "nonce", txn.GetNonce(), "contract", addr.Hex(), "value", txn.GetValue())
|
|
} else {
|
|
log.Info("Submitted transaction", "hash", txn.Hash().Hex(), "from", from, "nonce", txn.GetNonce(), "recipient", txn.GetTo(), "value", txn.GetValue())
|
|
}
|
|
|
|
return txn.Hash(), nil
|
|
}
|
|
|
|
// SendTransaction implements eth_sendTransaction. Creates new message call transaction or a contract creation if the data field contains code.
|
|
func (api *APIImpl) SendTransaction(_ context.Context, txObject interface{}) (common.Hash, error) {
|
|
return common.Hash{0}, fmt.Errorf(NotImplemented, "eth_sendTransaction")
|
|
}
|
|
|
|
// checkTxFee is an internal function used to check whether the fee of
|
|
// the given transaction is _reasonable_(under the cap).
|
|
func checkTxFee(gasPrice *big.Int, gas uint64, cap float64) error {
|
|
// Short circuit if there is no cap for transaction fee at all.
|
|
if cap == 0 {
|
|
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()
|
|
if feeFloat > cap {
|
|
return fmt.Errorf("tx fee (%.2f ether) exceeds the configured cap (%.2f ether)", feeFloat, cap)
|
|
}
|
|
return nil
|
|
}
|