Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

Miner namespace #377

Merged
merged 39 commits into from
Aug 4, 2021
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
7ef52ce
miner namespace
ramacarlucho Jul 26, 2021
dce20db
SetGasPrice call
hanchon Jul 26, 2021
60808e0
Added note plus fixed error logging
hanchon Jul 26, 2021
609677e
Refactor to use the keyring in the miner namespace
hanchon Jul 26, 2021
e22252b
Merge branch 'tharsis:main' into miner_namespace
hanchon Jul 27, 2021
f9d4a01
Changed keyring function return
hanchon Jul 27, 2021
bfc58d8
Added more detailed logs to unsupported functions
hanchon Jul 27, 2021
b479e04
Merge branch 'miner_namespace' of github.com:hanchon/ethermint into m…
hanchon Jul 27, 2021
d7b5f87
Reverted changes on ethapi and just using a refrence to it on miner
hanchon Jul 27, 2021
61742f7
Creating a transaction
hanchon Jul 27, 2021
292ccfc
fix condition
ramacarlucho Jul 27, 2021
0e527ce
Error string not capitalized
hanchon Jul 27, 2021
0af193d
suggested changes to setEtherbase
ramacarlucho Jul 28, 2021
37c1950
change log level
ramacarlucho Jul 28, 2021
6efe47c
minor changes
ramacarlucho Jul 28, 2021
b10cc83
minor changes
ramacarlucho Jul 28, 2021
5fc883e
Merge branch 'tharsis:main' into miner_corrections
hanchon Jul 28, 2021
b6ffa96
Merge branch 'tharsis:main' into miner_namespace
hanchon Jul 28, 2021
78e0a46
Sending tx to test the endpoint
hanchon Jul 28, 2021
66c9aa4
get tx nonce
ramacarlucho Jul 28, 2021
4807d4d
Using aphoton const and changing the logger to debug
hanchon Jul 28, 2021
235a3a6
Merge pull request #1 from hanchon/miner_corrections
hanchon Jul 28, 2021
6179c5b
Using default RPC gas limit constant
hanchon Jul 28, 2021
5e025d6
Apply suggestions from code review
ramacarlucho Jul 29, 2021
e89bc48
pair programming session
fedekunze Jul 30, 2021
f243ad8
get gas
ramacarlucho Jul 30, 2021
ef576c5
Set gas prices note added
hanchon Aug 2, 2021
adb4cf9
Setting fess and max gas
hanchon Aug 2, 2021
0faf64e
delete unnecessary log
ramacarlucho Aug 2, 2021
7757254
Apply suggestions from code review
ramacarlucho Aug 3, 2021
1a09f3f
Suggested changes applied
hanchon Aug 3, 2021
2987a8b
Updated changelog and json_rpc docs
hanchon Aug 3, 2021
6acf94c
Update CHANGELOG.md
ramacarlucho Aug 3, 2021
11c56f9
Update ethereum/rpc/namespaces/miner/api.go
hanchon Aug 4, 2021
106d709
Update ethereum/rpc/namespaces/miner/api.go
hanchon Aug 4, 2021
bbd1567
Update ethereum/rpc/namespaces/miner/api.go
hanchon Aug 4, 2021
a5e5fd3
Update ethereum/rpc/namespaces/miner/api.go
hanchon Aug 4, 2021
41b51f6
Using the same coin denom as the gas price for the fee
hanchon Aug 4, 2021
430bfe2
Merge branch 'tharsis:main' into miner_namespace
hanchon Aug 4, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions ethereum/rpc/apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/tharsis/ethermint/ethereum/rpc/namespaces/debug"
"github.com/tharsis/ethermint/ethereum/rpc/namespaces/eth"
"github.com/tharsis/ethermint/ethereum/rpc/namespaces/eth/filters"
"github.com/tharsis/ethermint/ethereum/rpc/namespaces/miner"
"github.com/tharsis/ethermint/ethereum/rpc/namespaces/net"
"github.com/tharsis/ethermint/ethereum/rpc/namespaces/personal"
"github.com/tharsis/ethermint/ethereum/rpc/namespaces/txpool"
Expand All @@ -27,6 +28,7 @@ const (
NetNamespace = "net"
TxPoolNamespace = "txpool"
DebugNamespace = "debug"
MinerNamespace = "miner"

apiVersion = "1.0"
)
Expand Down Expand Up @@ -104,6 +106,15 @@ func GetRPCAPIs(ctx *server.Context, clientCtx client.Context, tmWSClient *rpccl
Public: true,
},
)
case MinerNamespace:
apis = append(apis,
rpc.API{
Namespace: MinerNamespace,
Version: apiVersion,
Service: miner.NewMinerAPI(ctx, ethAPI, evmBackend),
Public: true,
},
)
default:
ctx.Logger.Error("invalid namespace value", "namespace", selectedAPIs[index])
}
Expand Down
27 changes: 27 additions & 0 deletions ethereum/rpc/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ type Backend interface {
// Used by log filter
GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, error)
BloomStatus() (uint64, uint64)

GetCoinbase() (sdk.AccAddress, error)
}

var _ Backend = (*EVMBackend)(nil)
Expand Down Expand Up @@ -417,3 +419,28 @@ func (e *EVMBackend) GetLogsByNumber(blockNum types.BlockNumber) ([][]*ethtypes.
func (e *EVMBackend) BloomStatus() (uint64, uint64) {
return 4096, 0
}

// GetCoinbase is the address that staking rewards will be send to (alias for Etherbase).
func (e *EVMBackend) GetCoinbase() (sdk.AccAddress, error) {
node, err := e.clientCtx.GetNode()
if err != nil {
return nil, err
}

status, err := node.Status(e.ctx)
if err != nil {
return nil, err
}

req := &evmtypes.QueryValidatorAccountRequest{
ConsAddress: sdk.ConsAddress(status.ValidatorInfo.Address).String(),
}

res, err := e.queryClient.ValidatorAccount(e.ctx, req)
if err != nil {
return nil, err
}

address, _ := sdk.AccAddressFromBech32(res.AccountAddress)
return address, nil
}
32 changes: 12 additions & 20 deletions ethereum/rpc/namespaces/eth/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ func (e *PublicAPI) ClientCtx() client.Context {
return e.clientCtx
}

func (e *PublicAPI) QueryClient() *rpctypes.QueryClient {
return e.queryClient
}

func (e *PublicAPI) Ctx() context.Context {
return e.ctx
}

// ProtocolVersion returns the supported Ethereum protocol version.
func (e *PublicAPI) ProtocolVersion() hexutil.Uint {
e.logger.Debug("eth_protocolVersion")
Expand Down Expand Up @@ -137,26 +145,10 @@ func (e *PublicAPI) Syncing() (interface{}, error) {
func (e *PublicAPI) Coinbase() (string, error) {
e.logger.Debug("eth_coinbase")

node, err := e.clientCtx.GetNode()
if err != nil {
return "", err
}

status, err := node.Status(e.ctx)
toAddr, err := e.backend.GetCoinbase()
ramacarlucho marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return "", err
}

req := &evmtypes.QueryValidatorAccountRequest{
ConsAddress: sdk.ConsAddress(status.ValidatorInfo.Address).String(),
}

res, err := e.queryClient.ValidatorAccount(e.ctx, req)
if err != nil {
return "", err
}

toAddr, _ := sdk.AccAddressFromBech32(res.AccountAddress)
ethAddr := common.BytesToAddress(toAddr.Bytes())
ramacarlucho marked this conversation as resolved.
Show resolved Hide resolved
return ethAddr.Hex(), nil
}
Expand Down Expand Up @@ -373,7 +365,7 @@ func (e *PublicAPI) SendTransaction(args rpctypes.SendTxArgs) (common.Hash, erro
return common.Hash{}, fmt.Errorf("%s; %s", keystore.ErrNoMatch, err.Error())
}

args, err = e.setTxDefaults(args)
args, err = e.SetTxDefaults(args)
if err != nil {
return common.Hash{}, err
}
Expand Down Expand Up @@ -991,9 +983,9 @@ func (e *PublicAPI) GetProof(address common.Address, storageKeys []string, block
}, nil
}

// setTxDefaults populates tx message with default values in case they are not
// SetTxDefaults populates tx message with default values in case they are not
// provided on the args
func (e *PublicAPI) setTxDefaults(args rpctypes.SendTxArgs) (rpctypes.SendTxArgs, error) {
func (e *PublicAPI) SetTxDefaults(args rpctypes.SendTxArgs) (rpctypes.SendTxArgs, error) {
hanchon marked this conversation as resolved.
Show resolved Hide resolved

if args.GasPrice == nil {
// TODO: Change to either:
Expand Down
164 changes: 164 additions & 0 deletions ethereum/rpc/namespaces/miner/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
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"
ethermint "github.com/tharsis/ethermint/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("module", "miner"),
hanchon marked this conversation as resolved.
Show resolved Hide resolved
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 address")
ramacarlucho marked this conversation as resolved.
Show resolved Hide resolved
return false
}

api.logger.Debug("Etherbase account ", delAddr.String())
ramacarlucho marked this conversation as resolved.
Show resolved Hide resolved

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())
ramacarlucho marked this conversation as resolved.
Show resolved Hide resolved
}

err = builder.SetMsgs(msg)
if err != nil {
api.logger.Error("builder.SetMsgs failed", "error", err.Error())
ramacarlucho marked this conversation as resolved.
Show resolved Hide resolved
}

denom, err := sdk.GetBaseDenom()
if err != nil {
api.logger.Debug("Could not get the denom of smallest unit registered.")
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
return false
}
hanchon marked this conversation as resolved.
Show resolved Hide resolved

// TODO: is there a way to calculate this message fee and gas limit?
value := big.NewInt(10000)
fees := sdk.Coins{sdk.NewCoin(denom, sdk.NewIntFromBigInt(value))}
builder.SetFeeAmount(fees)
builder.SetGasLimit(ethermint.DefaultRPCGasLimit)
fedekunze marked this conversation as resolved.
Show resolved Hide resolved

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))

keyInfo, err := api.ethAPI.ClientCtx().Keyring.KeyByAddress(delAddr)
if err != nil {
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
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.Info("Broadcasted tx to set delegator's withdraw address.", "hash", tmHash)
ramacarlucho marked this conversation as resolved.
Show resolved Hide resolved
return true
}

// SetGasPrice sets the minimum accepted gas price for the miner.
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.Error("failed to parse file.", "file", api.ctx.Viper.ConfigFileUsed(), "error:", err.Error())
hanchon marked this conversation as resolved.
Show resolved Hide resolved
return false
}
// NOTE: To allow values less that 1 aphoton, we need to divide the gasPrice here using some constant
// If we want to function the same as go-eth we should just use the gasPrice as an int without converting it
coinsValue := gasPrice.ToInt().String()
unit, err := sdk.GetBaseDenom()
if err != nil {
api.logger.Debug("Could not get the denom of smallest unit registered.")
return false
}
c, err := sdk.ParseDecCoins(coinsValue + unit)
if err != nil {
api.logger.Error("failed to parse coins", "coins", coinsValue, "error", err.Error())
return false
}
appConf.SetMinGasPrices(c)
config.WriteConfigFile(api.ctx.Viper.ConfigFileUsed(), appConf)
api.logger.Info("Your configuration file was modified. Please RESTART your node.", "value", coinsValue+unit)
return true
}
51 changes: 51 additions & 0 deletions ethereum/rpc/namespaces/miner/unsupported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package miner

import (
"errors"

"github.com/ethereum/go-ethereum/common/hexutil"
)

// GetHashrate returns the current hashrate for local CPU miner and remote miner.
// Unsupported in Ethermint
func (api *API) GetHashrate() uint64 {
api.logger.Debug("miner_getHashrate")
api.logger.Debug("Unsupported rpc function: miner_getHashrate")
return 0
}

// SetExtra sets the extra data string that is included when this miner mines a block.
// Unsupported in Ethermint
func (api *API) SetExtra(extra string) (bool, error) {
api.logger.Debug("miner_setExtra")
api.logger.Debug("Unsupported rpc function: miner_setExtra")
return false, errors.New("unsupported rpc function: miner_setExtra")
}

// SetGasLimit sets the gaslimit to target towards during mining.
// Unsupported in Ethermint
func (api *API) SetGasLimit(gasLimit hexutil.Uint64) bool {
api.logger.Debug("miner_setGasLimit")
api.logger.Debug("Unsupported rpc function: miner_setGasLimit")
return false
}

// Start starts the miner with the given number of threads. If threads is nil,
// the number of workers started is equal to the number of logical CPUs that are
// usable by this process. If mining is already running, this method adjust the
// number of threads allowed to use and updates the minimum price required by the
// transaction pool.
// Unsupported in Ethermint
func (api *API) Start(threads *int) error {
api.logger.Debug("miner_start")
api.logger.Debug("Unsupported rpc function: miner_start")
return errors.New("unsupported rpc function: miner_start")
}

// Stop terminates the miner, both at the consensus engine level as well as at
// the block creation level.
// Unsupported in Ethermint
func (api *API) Stop() {
api.logger.Debug("miner_stop")
api.logger.Debug("Unsupported rpc function: miner_stop")
}
2 changes: 1 addition & 1 deletion init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,4 @@ if [[ $1 == "pending" ]]; then
fi

# Start the node (remove the --pruning=nothing flag if historical queries are not needed)
ethermintd start --pruning=nothing $TRACE --log_level $LOGLEVEL --minimum-gas-prices=0.0001aphoton --evm-rpc.api eth,txpool,personal,net,debug,web3
ethermintd start --pruning=nothing $TRACE --log_level $LOGLEVEL --minimum-gas-prices=0.0001aphoton --evm-rpc.api eth,txpool,personal,net,debug,web3,miner