396db9f20a
* miner namespace * SetGasPrice call * Added note plus fixed error logging * Refactor to use the keyring in the miner namespace * Changed keyring function return * Added more detailed logs to unsupported functions * Reverted changes on ethapi and just using a refrence to it on miner * Creating a transaction * fix condition * Error string not capitalized * suggested changes to setEtherbase * change log level * minor changes * minor changes * Sending tx to test the endpoint * get tx nonce * Using aphoton const and changing the logger to debug * Using default RPC gas limit constant * Apply suggestions from code review Renames and log changes Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * pair programming session * get gas * Set gas prices note added * Setting fess and max gas * delete unnecessary log * Apply suggestions from code review return false in case of error Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Suggested changes applied * Updated changelog and json_rpc docs * Update CHANGELOG.md Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Update ethereum/rpc/namespaces/miner/api.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Update ethereum/rpc/namespaces/miner/api.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Update ethereum/rpc/namespaces/miner/api.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Update ethereum/rpc/namespaces/miner/api.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> * Using the same coin denom as the gas price for the fee Co-authored-by: ramacarlucho <ramirocarlucho@gmail.com> Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Federico Kunze <federico.kunze94@gmail.com>
192 lines
6.0 KiB
Go
192 lines
6.0 KiB
Go
package miner
|
|
|
|
import (
|
|
"errors"
|
|
"math/big"
|
|
|
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
|
"github.com/cosmos/cosmos-sdk/client/tx"
|
|
"github.com/cosmos/cosmos-sdk/server"
|
|
"github.com/cosmos/cosmos-sdk/server/config"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
|
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
|
|
"github.com/tendermint/tendermint/libs/log"
|
|
tmtypes "github.com/tendermint/tendermint/types"
|
|
|
|
"github.com/tharsis/ethermint/ethereum/rpc/backend"
|
|
"github.com/tharsis/ethermint/ethereum/rpc/namespaces/eth"
|
|
rpctypes "github.com/tharsis/ethermint/ethereum/rpc/types"
|
|
)
|
|
|
|
// API is the miner prefixed set of APIs in the Miner JSON-RPC spec.
|
|
type API struct {
|
|
ctx *server.Context
|
|
logger log.Logger
|
|
ethAPI *eth.PublicAPI
|
|
backend backend.Backend
|
|
}
|
|
|
|
// NewMinerAPI creates an instance of the Miner API.
|
|
func NewMinerAPI(
|
|
ctx *server.Context,
|
|
ethAPI *eth.PublicAPI,
|
|
backend backend.Backend,
|
|
) *API {
|
|
return &API{
|
|
ctx: ctx,
|
|
ethAPI: ethAPI,
|
|
logger: ctx.Logger.With("api", "miner"),
|
|
backend: backend,
|
|
}
|
|
}
|
|
|
|
// SetEtherbase sets the etherbase of the miner
|
|
func (api *API) SetEtherbase(etherbase common.Address) bool {
|
|
api.logger.Debug("miner_setEtherbase")
|
|
|
|
delAddr, err := api.backend.GetCoinbase()
|
|
if err != nil {
|
|
api.logger.Debug("failed to get coinbase address", "error", err.Error())
|
|
return false
|
|
}
|
|
|
|
withdrawAddr := sdk.AccAddress(etherbase.Bytes())
|
|
msg := distributiontypes.NewMsgSetWithdrawAddress(delAddr, withdrawAddr)
|
|
|
|
if err := msg.ValidateBasic(); err != nil {
|
|
api.logger.Debug("tx failed basic validation", "error", err.Error())
|
|
return false
|
|
}
|
|
|
|
// Assemble transaction from fields
|
|
builder, ok := api.ethAPI.ClientCtx().TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder)
|
|
if !ok {
|
|
api.logger.Debug("clientCtx.TxConfig.NewTxBuilder returns unsupported builder", "error", err.Error())
|
|
return false
|
|
}
|
|
|
|
err = builder.SetMsgs(msg)
|
|
if err != nil {
|
|
api.logger.Error("builder.SetMsgs failed", "error", err.Error())
|
|
return false
|
|
}
|
|
|
|
// Fetch minimun gas price to calculate fees using the configuration.
|
|
appConf, err := config.ParseConfig(api.ctx.Viper)
|
|
if err != nil {
|
|
api.logger.Error("failed to parse file.", "file", api.ctx.Viper.ConfigFileUsed(), "error:", err.Error())
|
|
return false
|
|
}
|
|
|
|
minGasPrices := appConf.GetMinGasPrices()
|
|
if len(minGasPrices) == 0 || minGasPrices.Empty() {
|
|
api.logger.Debug("the minimun fee is not set")
|
|
return false
|
|
}
|
|
minGasPriceValue := minGasPrices[0].Amount
|
|
denom := minGasPrices[0].Denom
|
|
|
|
delCommonAddr := common.BytesToAddress(delAddr.Bytes())
|
|
nonce, err := api.ethAPI.GetTransactionCount(delCommonAddr, rpctypes.EthPendingBlockNumber)
|
|
if err != nil {
|
|
api.logger.Debug("failed to get nonce", "error", err.Error())
|
|
return false
|
|
}
|
|
|
|
txFactory := tx.Factory{}
|
|
txFactory = txFactory.
|
|
WithChainID(api.ethAPI.ClientCtx().ChainID).
|
|
WithKeybase(api.ethAPI.ClientCtx().Keyring).
|
|
WithTxConfig(api.ethAPI.ClientCtx().TxConfig).
|
|
WithSequence(uint64(*nonce)).
|
|
WithGasAdjustment(1.11)
|
|
|
|
_, gas, err := tx.CalculateGas(api.ethAPI.ClientCtx(), txFactory, msg)
|
|
if err != nil {
|
|
api.logger.Debug("failed to calculate gas", "error", err.Error())
|
|
return false
|
|
}
|
|
|
|
txFactory = txFactory.WithGas(gas)
|
|
|
|
value := new(big.Int).SetUint64(gas * minGasPriceValue.Ceil().TruncateInt().Uint64())
|
|
fees := sdk.Coins{sdk.NewCoin(denom, sdk.NewIntFromBigInt(value))}
|
|
builder.SetFeeAmount(fees)
|
|
builder.SetGasLimit(gas)
|
|
|
|
keyInfo, err := api.ethAPI.ClientCtx().Keyring.KeyByAddress(delAddr)
|
|
if err != nil {
|
|
api.logger.Debug("failed to get the wallet address using the keyring", "error", err.Error())
|
|
return false
|
|
}
|
|
|
|
if err := tx.Sign(txFactory, keyInfo.GetName(), builder, false); err != nil {
|
|
api.logger.Debug("failed to sign tx", "error", err.Error())
|
|
return false
|
|
}
|
|
|
|
// Encode transaction by default Tx encoder
|
|
txEncoder := api.ethAPI.ClientCtx().TxConfig.TxEncoder()
|
|
txBytes, err := txEncoder(builder.GetTx())
|
|
if err != nil {
|
|
api.logger.Debug("failed to encode eth tx using default encoder", "error", err.Error())
|
|
return false
|
|
}
|
|
|
|
tmHash := common.BytesToHash(tmtypes.Tx(txBytes).Hash())
|
|
|
|
// Broadcast transaction in sync mode (default)
|
|
// NOTE: If error is encountered on the node, the broadcast will not return an error
|
|
syncCtx := api.ethAPI.ClientCtx().WithBroadcastMode(flags.BroadcastSync)
|
|
rsp, err := syncCtx.BroadcastTx(txBytes)
|
|
if err != nil || rsp.Code != 0 {
|
|
if err == nil {
|
|
err = errors.New(rsp.RawLog)
|
|
}
|
|
api.logger.Debug("failed to broadcast tx", "error", err.Error())
|
|
return false
|
|
}
|
|
|
|
api.logger.Debug("broadcasted tx to set miner withdraw address (etherbase)", "hash", tmHash.String())
|
|
return true
|
|
}
|
|
|
|
// SetGasPrice sets the minimum accepted gas price for the miner.
|
|
// NOTE: this function accepts only integers to have the same interface than go-eth
|
|
// to use float values, the gas prices must be configured using the configuration file
|
|
func (api *API) SetGasPrice(gasPrice hexutil.Big) bool {
|
|
api.logger.Info(api.ctx.Viper.ConfigFileUsed())
|
|
appConf, err := config.ParseConfig(api.ctx.Viper)
|
|
if err != nil {
|
|
api.logger.Debug("failed to parse config file", "file", api.ctx.Viper.ConfigFileUsed(), "error", err.Error())
|
|
return false
|
|
}
|
|
|
|
var unit string
|
|
minGasPrices := appConf.GetMinGasPrices()
|
|
|
|
// fetch the base denom from the sdk Config in case it's not currently defined on the node config
|
|
if len(minGasPrices) == 0 || minGasPrices.Empty() {
|
|
unit, err = sdk.GetBaseDenom()
|
|
if err != nil {
|
|
api.logger.Debug("could not get the denom of smallest unit registered", "error", err.Error())
|
|
return false
|
|
}
|
|
} else {
|
|
unit = minGasPrices[0].Denom
|
|
}
|
|
|
|
c := sdk.NewDecCoin(unit, sdk.NewIntFromBigInt(gasPrice.ToInt()))
|
|
|
|
appConf.SetMinGasPrices(sdk.DecCoins{c})
|
|
config.WriteConfigFile(api.ctx.Viper.ConfigFileUsed(), appConf)
|
|
api.logger.Info("Your configuration file was modified. Please RESTART your node.", "gas-price", c.String())
|
|
return true
|
|
}
|