From 1b758bbd7f84de1d678f5f2a656fb2bb5bf2d327 Mon Sep 17 00:00:00 2001 From: Kevin Yang <5478483+k-yang@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:39:01 -0700 Subject: [PATCH 1/2] refactor(localnet): preserve local keyring on make localnet (#1957) * refactor(localnet): preserve keyring on make localnet * refactor: rename FLAG_NO_BUILD to FLAG_SKIP_BUILD to avoid double negative phrasing * add localnet node config * force remove genesis file --- contrib/scripts/localnet.sh | 38 ++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/contrib/scripts/localnet.sh b/contrib/scripts/localnet.sh index df2c86e4f..fbcb0c8a5 100755 --- a/contrib/scripts/localnet.sh +++ b/contrib/scripts/localnet.sh @@ -54,9 +54,9 @@ echo_success() { echo_info "Parsing flags for the script..." -# $FLAG_NO_BUILD: toggles whether to build from source. The default -# behavior of the script is to run make install if the flag --no-build is not present. -FLAG_NO_BUILD=false +# $FLAG_SKIP_BUILD: toggles whether to build from source. The default +# behavior of the script is to run make install if the flag --no-build is omitted. +FLAG_SKIP_BUILD=false build_from_source() { @@ -81,7 +81,7 @@ enable_feature_flag() { while [[ $# -gt 0 ]]; do case $1 in --no-build) - FLAG_NO_BUILD=true + FLAG_SKIP_BUILD=true shift ;; --features) @@ -96,13 +96,13 @@ while [[ $# -gt 0 ]]; do done -# Check if FLAG_NO_BUILD was set to true -if ! $FLAG_NO_BUILD; then +# Check if FLAG_SKIP_BUILD was set to true +if ! $FLAG_SKIP_BUILD; then build_from_source fi echo_info "Features flags:" -echo "FLAG_NO_BUILD: $FLAG_NO_BUILD" +echo "FLAG_SKIP_BUILD: $FLAG_SKIP_BUILD" SEDOPTION="" if [[ "$OSTYPE" == "darwin"* ]]; then @@ -119,9 +119,11 @@ if pgrep -x "$BINARY" >/dev/null; then killall nibid fi -# Remove previous data +# Remove previous data, preserving keyring and config files echo_info "Removing previous chain data from $CHAIN_DIR..." -rm -rf "$CHAIN_DIR" +$BINARY tendermint unsafe-reset-all +rm -f "$CHAIN_DIR/config/genesis.json" +rm -rf "$CHAIN_DIR/config/gentx/" # Add directory for chain, exit if error if ! mkdir -p "$CHAIN_DIR" 2>/dev/null; then @@ -135,6 +137,7 @@ if $BINARY init $CHAIN_ID --chain-id $CHAIN_ID --overwrite; then echo_success "Successfully initialized $CHAIN_ID" else echo_error "Failed to initialize $CHAIN_ID" + exit 1 fi # nibid config @@ -143,6 +146,7 @@ $BINARY config keyring-backend test $BINARY config chain-id $CHAIN_ID $BINARY config broadcast-mode sync $BINARY config output json +$BINARY config node "http://localhost:26657" $BINARY config # Prints config. # Enable API Server @@ -165,15 +169,19 @@ echo_info "Adding genesis accounts..." val_key_name="validator" -echo "$MNEMONIC" | $BINARY keys add $val_key_name --recover -$BINARY add-genesis-account $($BINARY keys show $val_key_name -a) $GENESIS_COINS -# EVM encrypted nibi address for the same account -$BINARY add-genesis-account nibi1cr6tg4cjvux00pj6zjqkh6d0jzg7mksaywxyl3 $GENESIS_COINS -echo_success "Successfully added genesis account: $val_key_name" +if ! $BINARY keys show $val_key_name; then + echo "$MNEMONIC" | $BINARY keys add $val_key_name --recover + echo_success "Successfully added key: $val_key_name" +fi -val_address=$($BINARY keys list | jq -r '.[] | select(.name == "validator") | .address') +val_address=$($BINARY keys show $val_key_name -a) val_address=${val_address:-"nibi1zaavvzxez0elundtn32qnk9lkm8kmcsz44g7xl"} +$BINARY add-genesis-account $val_address $GENESIS_COINS +# EVM encoded nibi address for the same account +$BINARY add-genesis-account nibi1cr6tg4cjvux00pj6zjqkh6d0jzg7mksaywxyl3 $GENESIS_COINS +echo_success "Successfully added genesis account: $val_key_name" + # ------------------------------------------------------------------------ # Configure genesis params # ------------------------------------------------------------------------ From 2a6c81a75495e1bc44c7632855cb9d80706f2ce3 Mon Sep 17 00:00:00 2001 From: Oleg Nikonychev Date: Mon, 8 Jul 2024 04:06:57 +0400 Subject: [PATCH 2/2] chore(evm): wiped deprecated evm apis: miner, personal (#1958) * chore(evm): wiped miner api * chore: changelog update * chore(evm): removed personal api * chore(evm): removed miner and personal api methods --- CHANGELOG.md | 1 + app/server/config/server_config.go | 4 +- eth/rpc/backend/backend.go | 9 -- eth/rpc/backend/chain_info.go | 25 ---- eth/rpc/backend/chain_info_test.go | 57 -------- eth/rpc/backend/node_info.go | 223 ----------------------------- eth/rpc/backend/node_info_test.go | 192 ------------------------- eth/rpc/rpcapi/apis.go | 56 +------- eth/rpc/rpcapi/eth_api.go | 50 ------- eth/rpc/rpcapi/miner_api.go | 94 ------------ eth/rpc/rpcapi/personal_api.go | 207 -------------------------- x/evm/keeper/msg_server.go | 5 - 12 files changed, 8 insertions(+), 915 deletions(-) delete mode 100644 eth/rpc/rpcapi/miner_api.go delete mode 100644 eth/rpc/rpcapi/personal_api.go diff --git a/CHANGELOG.md b/CHANGELOG.md index cf9544830..573c73750 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#1936](https://github.com/NibiruChain/nibiru/pull/1936) - feat(evm): EVM fungible token protobufs and encoding tests - [#1947](https://github.com/NibiruChain/nibiru/pull/1947) - fix(evm): fix FunToken state marshalling - [#1949](https://github.com/NibiruChain/nibiru/pull/1949) - feat(evm): add fungible token mapping queries +- [#1958](https://github.com/NibiruChain/nibiru/pull/1958) - chore(evm): wiped deprecated evm apis: miner, personal #### Dapp modules: perp, spot, oracle, etc diff --git a/app/server/config/server_config.go b/app/server/config/server_config.go index 5b34d7a77..5484b7ac0 100644 --- a/app/server/config/server_config.go +++ b/app/server/config/server_config.go @@ -236,7 +236,7 @@ func GetDefaultAPINamespaces() []string { // GetAPINamespaces returns the all the available JSON-RPC API namespaces. func GetAPINamespaces() []string { - return []string{"web3", "eth", "personal", "net", "txpool", "debug", "miner"} + return []string{"web3", "eth", "net", "txpool", "debug"} } // DefaultJSONRPCConfig returns an EVM config with the JSON-RPC API enabled by default @@ -397,7 +397,7 @@ address = "{{ .JSONRPC.Address }}" ws-address = "{{ .JSONRPC.WsAddress }}" # API defines a list of JSON-RPC namespaces that should be enabled -# Example: "eth,txpool,personal,net,debug,web3" +# Example: "eth,txpool,net,debug,web3" api = "{{range $index, $elmt := .JSONRPC.API}}{{if $index}},{{$elmt}}{{else}}{{$elmt}}{{end}}{{end}}" # GasCap sets a cap on gas that can be used in eth_call/estimateGas (0=infinite). Default: 25,000,000. diff --git a/eth/rpc/backend/backend.go b/eth/rpc/backend/backend.go index 6976795fb..bebf53c10 100644 --- a/eth/rpc/backend/backend.go +++ b/eth/rpc/backend/backend.go @@ -9,7 +9,6 @@ import ( "github.com/cometbft/cometbft/libs/log" tmrpctypes "github.com/cometbft/cometbft/rpc/core/types" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" @@ -48,12 +47,6 @@ type EVMBackend interface { // Node specific queries Accounts() ([]common.Address, error) Syncing() (interface{}, error) - SetEtherbase(etherbase common.Address) bool - SetGasPrice(gasPrice hexutil.Big) bool - ImportRawKey(privkey, password string) (common.Address, error) - ListAccounts() ([]common.Address, error) - NewMnemonic(uid string, language keyring.Language, hdPath, bip39Passphrase string, algo keyring.SignatureAlgo) (*keyring.Record, error) - UnprotectedAllowed() bool RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection RPCEVMTimeout() time.Duration // global timeout for eth_call over rpc: DoS protection RPCTxFeeCap() float64 // RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for send-transaction variants. The unit is ether. @@ -94,11 +87,9 @@ type EVMBackend interface { ChainID() (*hexutil.Big, error) ChainConfig() *params.ChainConfig // TODO: feat: Dynamic fees - // GlobalMinGasPrice() (math.LegacyDec, error) BaseFee(blockRes *tmrpctypes.ResultBlockResults) (*big.Int, error) CurrentHeader() (*gethcore.Header, error) PendingTransactions() ([]*sdk.Tx, error) - GetCoinbase() (sdk.AccAddress, error) FeeHistory(blockCount gethrpc.DecimalOrHex, lastBlock gethrpc.BlockNumber, rewardPercentiles []float64) (*rpc.FeeHistoryResult, error) SuggestGasTipCap(baseFee *big.Int) (*big.Int, error) diff --git a/eth/rpc/backend/chain_info.go b/eth/rpc/backend/chain_info.go index 07969b346..1368d02ca 100644 --- a/eth/rpc/backend/chain_info.go +++ b/eth/rpc/backend/chain_info.go @@ -97,31 +97,6 @@ func (b *Backend) PendingTransactions() ([]*sdk.Tx, error) { return result, nil } -// GetCoinbase is the address that staking rewards will be send to (alias for Etherbase). -func (b *Backend) GetCoinbase() (sdk.AccAddress, error) { - node, err := b.clientCtx.GetNode() - if err != nil { - return nil, err - } - - status, err := node.Status(b.ctx) - if err != nil { - return nil, err - } - - req := &evm.QueryValidatorAccountRequest{ - ConsAddress: sdk.ConsAddress(status.ValidatorInfo.Address).String(), - } - - res, err := b.queryClient.ValidatorAccount(b.ctx, req) - if err != nil { - return nil, err - } - - address, _ := sdk.AccAddressFromBech32(res.AccountAddress) // #nosec G703 - return address, nil -} - // FeeHistory returns data relevant for fee estimation based on the specified range of blocks. func (b *Backend) FeeHistory( userBlockCount gethrpc.DecimalOrHex, // number blocks to fetch, maximum is 100 diff --git a/eth/rpc/backend/chain_info_test.go b/eth/rpc/backend/chain_info_test.go index c00932cea..f745a6c40 100644 --- a/eth/rpc/backend/chain_info_test.go +++ b/eth/rpc/backend/chain_info_test.go @@ -136,63 +136,6 @@ func (s *BackendSuite) TestChainId() { } } -func (s *BackendSuite) TestGetCoinbase() { - validatorAcc := sdk.AccAddress(evmtest.NewEthAccInfo().EthAddr.Bytes()) - testCases := []struct { - name string - registerMock func() - accAddr sdk.AccAddress - expPass bool - }{ - { - "fail - Can't retrieve status from node", - func() { - client := s.backend.clientCtx.Client.(*mocks.Client) - RegisterStatusError(client) - }, - validatorAcc, - false, - }, - { - "fail - Can't query validator account", - func() { - client := s.backend.clientCtx.Client.(*mocks.Client) - queryClient := s.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterStatus(client) - RegisterValidatorAccountError(queryClient) - }, - validatorAcc, - false, - }, - { - "pass - Gets coinbase account", - func() { - client := s.backend.clientCtx.Client.(*mocks.Client) - queryClient := s.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterStatus(client) - RegisterValidatorAccount(queryClient, validatorAcc) - }, - validatorAcc, - true, - }, - } - - for _, tc := range testCases { - s.Run(fmt.Sprintf("case %s", tc.name), func() { - s.SetupTest() // reset test and queries - tc.registerMock() - - accAddr, err := s.backend.GetCoinbase() - - if tc.expPass { - s.Require().Equal(tc.accAddr, accAddr) - } else { - s.Require().Error(err) - } - }) - } -} - func (s *BackendSuite) TestSuggestGasTipCap() { testCases := []struct { name string diff --git a/eth/rpc/backend/node_info.go b/eth/rpc/backend/node_info.go index e99cee5d9..266da954d 100644 --- a/eth/rpc/backend/node_info.go +++ b/eth/rpc/backend/node_info.go @@ -2,29 +2,12 @@ package backend import ( - "fmt" - "math/big" "time" - errorsmod "cosmossdk.io/errors" - sdkmath "cosmossdk.io/math" - tmtypes "github.com/cometbft/cometbft/types" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/tx" - sdkcrypto "github.com/cosmos/cosmos-sdk/crypto" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - sdkconfig "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/ethereum/go-ethereum/crypto" - "github.com/NibiruChain/nibiru/app/server/config" "github.com/NibiruChain/nibiru/eth" - "github.com/NibiruChain/nibiru/eth/crypto/ethsecp256k1" - "github.com/NibiruChain/nibiru/eth/rpc" "github.com/NibiruChain/nibiru/x/evm" ) @@ -75,212 +58,6 @@ func (b *Backend) Syncing() (interface{}, error) { }, nil } -// SetEtherbase sets the etherbase of the miner -func (b *Backend) SetEtherbase(etherbase common.Address) bool { - delAddr, err := b.GetCoinbase() - if err != nil { - b.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 { - b.logger.Debug("tx failed basic validation", "error", err.Error()) - return false - } - - // Assemble transaction from fields - builder, ok := b.clientCtx.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder) - if !ok { - b.logger.Debug("clientCtx.TxConfig.NewTxBuilder returns unsupported builder", "error", err.Error()) - return false - } - - err = builder.SetMsgs(msg) - if err != nil { - b.logger.Error("builder.SetMsgs failed", "error", err.Error()) - return false - } - - // Fetch minimun gas price to calculate fees using the configuration. - minGasPrices := b.cfg.GetMinGasPrices() - if len(minGasPrices) == 0 || minGasPrices.Empty() { - b.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 := b.GetTransactionCount(delCommonAddr, rpc.EthPendingBlockNumber) - if err != nil { - b.logger.Debug("failed to get nonce", "error", err.Error()) - return false - } - - txFactory := tx.Factory{} - txFactory = txFactory. - WithChainID(b.clientCtx.ChainID). - WithKeybase(b.clientCtx.Keyring). - WithTxConfig(b.clientCtx.TxConfig). - WithSequence(uint64(*nonce)). - WithGasAdjustment(1.25) - - _, gas, err := tx.CalculateGas(b.clientCtx, txFactory, msg) - if err != nil { - b.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, sdkmath.NewIntFromBigInt(value))} - builder.SetFeeAmount(fees) - builder.SetGasLimit(gas) - - keyInfo, err := b.clientCtx.Keyring.KeyByAddress(delAddr) - if err != nil { - b.logger.Debug("failed to get the wallet address using the keyring", "error", err.Error()) - return false - } - - if err := tx.Sign(txFactory, keyInfo.Name, builder, false); err != nil { - b.logger.Debug("failed to sign tx", "error", err.Error()) - return false - } - - // Encode transaction by default Tx encoder - txEncoder := b.clientCtx.TxConfig.TxEncoder() - txBytes, err := txEncoder(builder.GetTx()) - if err != nil { - b.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 := b.clientCtx.WithBroadcastMode(flags.BroadcastSync) - rsp, err := syncCtx.BroadcastTx(txBytes) - if rsp != nil && rsp.Code != 0 { - err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog) - } - if err != nil { - b.logger.Debug("failed to broadcast tx", "error", err.Error()) - return false - } - - b.logger.Debug("broadcasted tx to set miner withdraw address (etherbase)", "hash", tmHash.String()) - return true -} - -// ImportRawKey armors and encrypts a given raw hex encoded ECDSA key and stores it into the key directory. -// The name of the key will have the format "personal_", where is the total number of -// keys stored on the keyring. -// -// NOTE: The key will be both armored and encrypted using the same passphrase. -func (b *Backend) ImportRawKey(privkey, password string) (common.Address, error) { - priv, err := crypto.HexToECDSA(privkey) - if err != nil { - return common.Address{}, err - } - - privKey := ðsecp256k1.PrivKey{Key: crypto.FromECDSA(priv)} - - addr := sdk.AccAddress(privKey.PubKey().Address().Bytes()) - ethereumAddr := common.BytesToAddress(addr) - - // return if the key has already been imported - if _, err := b.clientCtx.Keyring.KeyByAddress(addr); err == nil { - return ethereumAddr, nil - } - - // ignore error as we only care about the length of the list - list, _ := b.clientCtx.Keyring.List() // #nosec G703 - privKeyName := fmt.Sprintf("personal_%d", len(list)) - - armor := sdkcrypto.EncryptArmorPrivKey(privKey, password, ethsecp256k1.KeyType) - - if err := b.clientCtx.Keyring.ImportPrivKey(privKeyName, armor, password); err != nil { - return common.Address{}, err - } - - b.logger.Info("key successfully imported", "name", privKeyName, "address", ethereumAddr.String()) - - return ethereumAddr, nil -} - -// ListAccounts will return a list of addresses for accounts this node manages. -func (b *Backend) ListAccounts() ([]common.Address, error) { - addrs := []common.Address{} - - list, err := b.clientCtx.Keyring.List() - if err != nil { - return nil, err - } - - for _, info := range list { - pubKey, err := info.GetPubKey() - if err != nil { - return nil, err - } - addrs = append(addrs, common.BytesToAddress(pubKey.Address())) - } - - return addrs, nil -} - -// NewAccount will create a new account and returns the address for the new account. -func (b *Backend) NewMnemonic(uid string, - _ keyring.Language, - hdPath, - bip39Passphrase string, - algo keyring.SignatureAlgo, -) (*keyring.Record, error) { - info, _, err := b.clientCtx.Keyring.NewMnemonic(uid, keyring.English, hdPath, bip39Passphrase, algo) - if err != nil { - return nil, err - } - return info, err -} - -// 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 (b *Backend) SetGasPrice(gasPrice hexutil.Big) bool { - appConf, err := config.GetConfig(b.clientCtx.Viper) - if err != nil { - b.logger.Debug("could not get the server config", "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() { - var err error - unit, err = sdk.GetBaseDenom() - if err != nil { - b.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, sdkmath.NewIntFromBigInt(gasPrice.ToInt())) - - appConf.SetMinGasPrices(sdk.DecCoins{c}) - sdkconfig.WriteConfigFile(b.clientCtx.Viper.ConfigFileUsed(), appConf) - b.logger.Info("Your configuration file was modified. Please RESTART your node.", "gas-price", c.String()) - return true -} - // UnprotectedAllowed returns the node configuration value for allowing // unprotected transactions (i.e not replay-protected) func (b Backend) UnprotectedAllowed() bool { diff --git a/eth/rpc/backend/node_info_test.go b/eth/rpc/backend/node_info_test.go index 87fe46b63..8bebeb429 100644 --- a/eth/rpc/backend/node_info_test.go +++ b/eth/rpc/backend/node_info_test.go @@ -2,19 +2,11 @@ package backend import ( "fmt" - "math/big" - "cosmossdk.io/math" - tmrpcclient "github.com/cometbft/cometbft/rpc/client" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/spf13/viper" - "google.golang.org/grpc/metadata" "github.com/NibiruChain/nibiru/eth" - "github.com/NibiruChain/nibiru/eth/crypto/ethsecp256k1" "github.com/NibiruChain/nibiru/eth/rpc/backend/mocks" ) @@ -60,76 +52,6 @@ func (s *BackendSuite) TestRPCMinGasPrice() { } } -func (s *BackendSuite) TestSetGasPrice() { - defaultGasPrice := (*hexutil.Big)(big.NewInt(1)) - testCases := []struct { - name string - registerMock func() - gasPrice hexutil.Big - expOutput bool - }{ - { - "pass - cannot get server config", - func() { - s.backend.clientCtx.Viper = viper.New() - }, - *defaultGasPrice, - false, - }, - { - "pass - cannot find coin denom", - func() { - s.backend.clientCtx.Viper = viper.New() - s.backend.clientCtx.Viper.Set("telemetry.global-labels", []interface{}{}) - }, - *defaultGasPrice, - false, - }, - } - - for _, tc := range testCases { - s.Run(fmt.Sprintf("case %s", tc.name), func() { - s.SetupTest() // reset test and queries - tc.registerMock() - output := s.backend.SetGasPrice(tc.gasPrice) - s.Require().Equal(tc.expOutput, output) - }) - } -} - -// TODO: Combine these 2 into one test since the code is identical -func (s *BackendSuite) TestListAccounts() { - testCases := []struct { - name string - registerMock func() - expAddr []common.Address - expPass bool - }{ - { - "pass - returns empty address", - func() {}, - []common.Address{}, - true, - }, - } - - for _, tc := range testCases { - s.Run(fmt.Sprintf("case %s", tc.name), func() { - s.SetupTest() // reset test and queries - tc.registerMock() - - output, err := s.backend.ListAccounts() - - if tc.expPass { - s.Require().NoError(err) - s.Require().Equal(tc.expAddr, output) - } else { - s.Require().Error(err) - } - }) - } -} - func (s *BackendSuite) TestAccounts() { testCases := []struct { name string @@ -219,117 +141,3 @@ func (s *BackendSuite) TestSyncing() { }) } } - -func (s *BackendSuite) TestSetEtherbase() { - testCases := []struct { - name string - registerMock func() - etherbase common.Address - expResult bool - }{ - { - "pass - Failed to get coinbase address", - func() { - client := s.backend.clientCtx.Client.(*mocks.Client) - RegisterStatusError(client) - }, - common.Address{}, - false, - }, - { - "pass - the minimum fee is not set", - func() { - client := s.backend.clientCtx.Client.(*mocks.Client) - queryClient := s.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterStatus(client) - RegisterValidatorAccount(queryClient, s.acc) - }, - common.Address{}, - false, - }, - { - "fail - error querying for account", - func() { - var header metadata.MD - client := s.backend.clientCtx.Client.(*mocks.Client) - queryClient := s.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterStatus(client) - RegisterValidatorAccount(queryClient, s.acc) - RegisterParams(queryClient, &header, 1) - c := sdk.NewDecCoin(eth.EthBaseDenom, math.NewIntFromBigInt(big.NewInt(1))) - s.backend.cfg.SetMinGasPrices(sdk.DecCoins{c}) - delAddr, _ := s.backend.GetCoinbase() - // account, _ := suite.backend.clientCtx.AccountRetriever.GetAccount(suite.backend.clientCtx, delAddr) - delCommonAddr := common.BytesToAddress(delAddr.Bytes()) - request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(delCommonAddr.Bytes()).String()} - requestMarshal, _ := request.Marshal() - RegisterABCIQueryWithOptionsError( - client, - "/cosmos.auth.v1beta1.Query/Account", - requestMarshal, - tmrpcclient.ABCIQueryOptions{Height: int64(1), Prove: false}, - ) - }, - common.Address{}, - false, - }, - } - - for _, tc := range testCases { - s.Run(fmt.Sprintf("case %s", tc.name), func() { - s.SetupTest() // reset test and queries - tc.registerMock() - - output := s.backend.SetEtherbase(tc.etherbase) - - s.Require().Equal(tc.expResult, output) - }) - } -} - -func (s *BackendSuite) TestImportRawKey() { - priv, _ := ethsecp256k1.GenerateKey() - privHex := common.Bytes2Hex(priv.Bytes()) - pubAddr := common.BytesToAddress(priv.PubKey().Address().Bytes()) - - testCases := []struct { - name string - registerMock func() - privKey string - password string - expAddr common.Address - expPass bool - }{ - { - "fail - not a valid private key", - func() {}, - "", - "", - common.Address{}, - false, - }, - { - "pass - returning correct address", - func() {}, - privHex, - "", - pubAddr, - true, - }, - } - - for _, tc := range testCases { - s.Run(fmt.Sprintf("case %s", tc.name), func() { - s.SetupTest() // reset test and queries - tc.registerMock() - - output, err := s.backend.ImportRawKey(tc.privKey, tc.password) - if tc.expPass { - s.Require().NoError(err) - s.Require().Equal(tc.expAddr, output) - } else { - s.Require().Error(err) - } - }) - } -} diff --git a/eth/rpc/rpcapi/apis.go b/eth/rpc/rpcapi/apis.go index 336674c1e..b499c88c2 100644 --- a/eth/rpc/rpcapi/apis.go +++ b/eth/rpc/rpcapi/apis.go @@ -23,29 +23,15 @@ const ( NamespaceCosmos = "cosmos" // Ethereum namespaces - NamespaceWeb3 = "web3" - NamespaceEth = "eth" - NamespacePersonal = "personal" - NamespaceNet = "net" - NamespaceTxPool = "txpool" - NamespaceDebug = "debug" - NamespaceMiner = "miner" + NamespaceWeb3 = "web3" + NamespaceEth = "eth" + NamespaceNet = "net" + NamespaceTxPool = "txpool" + NamespaceDebug = "debug" apiVersion = "1.0" ) -func EthereumNamespaces() []string { - return []string{ - NamespaceWeb3, - NamespaceEth, - NamespacePersonal, - NamespaceNet, - NamespaceTxPool, - NamespaceDebug, - NamespaceMiner, - } -} - // APICreator creates the JSON-RPC API implementations. type APICreator = func( ctx *server.Context, @@ -102,22 +88,6 @@ func init() { }, } }, - NamespacePersonal: func(ctx *server.Context, - clientCtx client.Context, - _ *rpcclient.WSClient, - allowUnprotectedTxs bool, - indexer eth.EVMTxIndexer, - ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer) - return []rpc.API{ - { - Namespace: NamespacePersonal, - Version: apiVersion, - Service: NewImplPersonalAPI(ctx.Logger, evmBackend), - Public: false, - }, - } - }, NamespaceTxPool: func(ctx *server.Context, _ client.Context, _ *rpcclient.WSClient, _ bool, _ eth.EVMTxIndexer) []rpc.API { return []rpc.API{ { @@ -144,22 +114,6 @@ func init() { }, } }, - NamespaceMiner: func(ctx *server.Context, - clientCtx client.Context, - _ *rpcclient.WSClient, - allowUnprotectedTxs bool, - indexer eth.EVMTxIndexer, - ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer) - return []rpc.API{ - { - Namespace: NamespaceMiner, - Version: apiVersion, - Service: NewImplMinerAPI(ctx, evmBackend), - Public: false, - }, - } - }, } } diff --git a/eth/rpc/rpcapi/eth_api.go b/eth/rpc/rpcapi/eth_api.go index 1283e47b6..e81468193 100644 --- a/eth/rpc/rpcapi/eth_api.go +++ b/eth/rpc/rpcapi/eth_api.go @@ -109,14 +109,8 @@ type IEthAPI interface { GetUncleCountByBlockHash(hash common.Hash) hexutil.Uint GetUncleCountByBlockNumber(blockNum rpc.BlockNumber) hexutil.Uint - // Proof of Work - Hashrate() hexutil.Uint64 - Mining() bool - // Other Syncing() (interface{}, error) - Coinbase() (string, error) - Sign(address common.Address, data hexutil.Bytes) (hexutil.Bytes, error) GetTransactionLogs(txHash common.Hash) ([]*gethcore.Log, error) SignTypedData( address common.Address, typedData apitypes.TypedData, @@ -129,14 +123,6 @@ type IEthAPI interface { gasPrice *hexutil.Big, gasLimit *hexutil.Uint64, ) (common.Hash, error) GetPendingTransactions() ([]*rpc.EthTxJsonRPC, error) - // eth_signTransaction (on Ethereum.org) - // eth_getCompilers (on Ethereum.org) - // eth_compileSolidity (on Ethereum.org) - // eth_compileLLL (on Ethereum.org) - // eth_compileSerpent (on Ethereum.org) - // eth_getWork (on Ethereum.org) - // eth_submitWork (on Ethereum.org) - // eth_submitHashrate (on Ethereum.org) } var _ IEthAPI = (*EthAPI)(nil) @@ -417,22 +403,6 @@ func (e *EthAPI) GetUncleCountByBlockNumber(_ rpc.BlockNumber) hexutil.Uint { return 0 } -// -------------------------------------------------------------------------- -// Proof of Work -// -------------------------------------------------------------------------- - -// Hashrate returns the current node's hashrate. Always 0. -func (e *EthAPI) Hashrate() hexutil.Uint64 { - e.logger.Debug("eth_hashrate") - return 0 -} - -// Mining returns whether or not this node is currently mining. Always false. -func (e *EthAPI) Mining() bool { - e.logger.Debug("eth_mining") - return false -} - // -------------------------------------------------------------------------- // Other // -------------------------------------------------------------------------- @@ -451,26 +421,6 @@ func (e *EthAPI) Syncing() (interface{}, error) { return e.backend.Syncing() } -// Coinbase is the address that staking rewards will be send to (alias for Etherbase). -func (e *EthAPI) Coinbase() (string, error) { - e.logger.Debug("eth_coinbase") - - coinbase, err := e.backend.GetCoinbase() - if err != nil { - return "", err - } - ethAddr := common.BytesToAddress(coinbase.Bytes()) - return ethAddr.Hex(), nil -} - -// Sign signs the provided data using the private key of address via Geth's signature standard. -func (e *EthAPI) Sign( - address common.Address, data hexutil.Bytes, -) (hexutil.Bytes, error) { - e.logger.Debug("eth_sign", "address", address.Hex(), "data", common.Bytes2Hex(data)) - return e.backend.Sign(address, data) -} - // GetTransactionLogs returns the logs given a transaction hash. func (e *EthAPI) GetTransactionLogs(txHash common.Hash) ([]*gethcore.Log, error) { e.logger.Debug("eth_getTransactionLogs", "hash", txHash) diff --git a/eth/rpc/rpcapi/miner_api.go b/eth/rpc/rpcapi/miner_api.go deleted file mode 100644 index 298d8c4a5..000000000 --- a/eth/rpc/rpcapi/miner_api.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2023-2024 Nibi, Inc. -package rpcapi - -import ( - "errors" - - "github.com/cosmos/cosmos-sdk/server" - - "github.com/NibiruChain/nibiru/eth/rpc/backend" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - - "github.com/cometbft/cometbft/libs/log" -) - -// MinerAPI is the private miner prefixed set of APIs in the Miner JSON-RPC spec. -type MinerAPI struct { - ctx *server.Context - logger log.Logger - backend backend.EVMBackend -} - -// NewImplMinerAPI creates an instance of the Miner API. -func NewImplMinerAPI( - ctx *server.Context, - backend backend.EVMBackend, -) *MinerAPI { - return &MinerAPI{ - ctx: ctx, - logger: ctx.Logger.With("api", "miner"), - backend: backend, - } -} - -// SetEtherbase sets the etherbase of the miner -func (api *MinerAPI) SetEtherbase(etherbase common.Address) bool { - api.logger.Debug("miner_setEtherbase") - return api.backend.SetEtherbase(etherbase) -} - -// SetGasPrice sets the minimum accepted gas price for the miner. -func (api *MinerAPI) SetGasPrice(gasPrice hexutil.Big) bool { - api.logger.Info(api.ctx.Viper.ConfigFileUsed()) - return api.backend.SetGasPrice(gasPrice) -} - -// ------------------------------------------------ -// Unsupported functions on the Miner API -// ------------------------------------------------ - -// GetHashrate returns the current hashrate for local CPU miner and remote miner. -// Unsupported in Ethermint -func (api *MinerAPI) 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 *MinerAPI) SetExtra(_ 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 *MinerAPI) SetGasLimit(_ 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 *MinerAPI) Start(_ *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 *MinerAPI) Stop() { - api.logger.Debug("miner_stop") - api.logger.Debug("Unsupported rpc function: miner_stop") -} diff --git a/eth/rpc/rpcapi/personal_api.go b/eth/rpc/rpcapi/personal_api.go deleted file mode 100644 index 1ea0f6f52..000000000 --- a/eth/rpc/rpcapi/personal_api.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (c) 2023-2024 Nibi, Inc. -package rpcapi - -import ( - "context" - "fmt" - "os" - "time" - - "github.com/NibiruChain/nibiru/app/appconst" - "github.com/NibiruChain/nibiru/eth/rpc/backend" - - "github.com/NibiruChain/nibiru/eth" - "github.com/NibiruChain/nibiru/eth/crypto/hd" - - "github.com/cometbft/cometbft/libs/log" - - "github.com/cosmos/cosmos-sdk/crypto/keyring" - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/crypto" - - "github.com/NibiruChain/nibiru/x/evm" -) - -// PersonalAPI is the personal_ prefixed set of APIs in the Web3 JSON-RPC spec. -type PersonalAPI struct { - backend backend.EVMBackend - logger log.Logger - hdPathIter eth.HDPathIterator -} - -// NewImplPersonalAPI creates an instance of the public Personal Eth API. -func NewImplPersonalAPI( - logger log.Logger, - backend backend.EVMBackend, -) *PersonalAPI { - cfg := sdk.GetConfig() - basePath := cfg.GetFullBIP44Path() - - iterator, err := eth.NewHDPathIterator(basePath, true) - if err != nil { - panic(err) - } - - return &PersonalAPI{ - logger: logger.With("api", "personal"), - hdPathIter: iterator, - backend: backend, - } -} - -// ImportRawKey armors and encrypts a given raw hex encoded ECDSA key and stores it into the key directory. -// The name of the key will have the format "personal_", where is the total number of -// keys stored on the keyring. -// -// NOTE: The key will be both armored and encrypted using the same passphrase. -func (api *PersonalAPI) ImportRawKey(privkey, password string) (common.Address, error) { - api.logger.Debug("personal_importRawKey") - return api.backend.ImportRawKey(privkey, password) -} - -// ListAccounts will return a list of addresses for accounts this node manages. -func (api *PersonalAPI) ListAccounts() ([]common.Address, error) { - api.logger.Debug("personal_listAccounts") - return api.backend.ListAccounts() -} - -// LockAccount will lock the account associated with the given address when it's unlocked. -// It removes the key corresponding to the given address from the API's local keys. -func (api *PersonalAPI) LockAccount(address common.Address) bool { - api.logger.Debug("personal_lockAccount", "address", address.String()) - api.logger.Info("personal_lockAccount not supported") - // TODO: Not supported. See underlying issue https://github.com/99designs/keyring/issues/85 - return false -} - -// NewAccount will create a new account and returns the address for the new -// account. -func (api *PersonalAPI) NewAccount(password string) (common.Address, error) { - api.logger.Debug("personal_newAccount") - - name := "key_" + time.Now().UTC().Format(time.RFC3339) - - // create the mnemonic and save the account - hdPath := api.hdPathIter() - - info, err := api.backend.NewMnemonic(name, keyring.English, hdPath.String(), password, hd.EthSecp256k1) - if err != nil { - return common.Address{}, err - } - - pubKey, err := info.GetPubKey() - if err != nil { - return common.Address{}, err - } - addr := common.BytesToAddress(pubKey.Address().Bytes()) - api.logger.Info("Your new key was generated", "address", addr.String()) - - binPath := fmt.Sprintf("%s/.%s/%s", - os.Getenv("HOME"), appconst.BinaryName, name) - api.logger.Info("Please backup your key file!", "path", binPath) - api.logger.Info("Please remember your password!") - return addr, nil -} - -// UnlockAccount will unlock the account associated with the given address with -// the given password for duration seconds. It returns an indication if the -// account was unlocked. -func (api *PersonalAPI) UnlockAccount( - _ context.Context, addr common.Address, _ string, _ *uint64, -) (isUnlocked bool, err error) { - api.logger.Debug("personal_unlockAccount", "address", addr.String()) - // TODO: feat(eth-rpc): Implement a way to lock and unlock the keyring - // securely on the Ethereum "peronsal" RPC namespace. - return false, nil // Not yet supported. -} - -// SendTransaction will create a transaction from the given arguments and -// tries to sign it with the key associated with args.To. If the given password isn't -// able to decrypt the key it fails. -func (api *PersonalAPI) SendTransaction( - _ context.Context, args evm.JsonTxArgs, _ string, -) (common.Hash, error) { - api.logger.Debug("personal_sendTransaction", "address", args.To.String()) - return api.backend.SendTransaction(args) -} - -// Sign calculates an Ethereum ECDSA signature for: -// keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)) -// -// Note, the produced signature conforms to the secp256k1 curve R, S and V values, -// where the V value will be 27 or 28 for legacy reasons. -// -// The key used to calculate the signature is decrypted with the given password. -// -// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign -func (api *PersonalAPI) Sign(_ context.Context, data hexutil.Bytes, addr common.Address, _ string) (hexutil.Bytes, error) { - api.logger.Debug("personal_sign", "data", data, "address", addr.String()) - return api.backend.Sign(addr, data) -} - -// EcRecover returns the address for the account that was used to create the signature. -// Note, this function is compatible with eth_sign and personal_sign. As such it recovers -// the address of: -// hash = keccak256("\x19Ethereum Signed Message:\n"${message length}${message}) -// addr = ecrecover(hash, signature) -// -// Note, the signature must conform to the secp256k1 curve R, S and V values, where -// the V value must be 27 or 28 for legacy reasons. -// -// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecove -func (api *PersonalAPI) EcRecover(_ context.Context, data, sig hexutil.Bytes) (common.Address, error) { - api.logger.Debug("personal_ecRecover", "data", data, "sig", sig) - - if len(sig) != crypto.SignatureLength { - return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength) - } - - if sig[crypto.RecoveryIDOffset] != 27 && sig[crypto.RecoveryIDOffset] != 28 { - return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)") - } - - sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1 - - pubkey, err := crypto.SigToPub(accounts.TextHash(data), sig) - if err != nil { - return common.Address{}, err - } - - return crypto.PubkeyToAddress(*pubkey), nil -} - -// Unpair deletes a pairing between wallet and ethermint. -func (api *PersonalAPI) Unpair(_ context.Context, url, pin string) error { - api.logger.Debug("personal_unpair", "url", url, "pin", pin) - api.logger.Info("personal_unpair for smartcard wallet not supported") - // TODO: Smartcard wallet not supported yet, refer to: https://github.com/ethereum/go-ethereum/blob/master/accounts/scwallet/README.md - return fmt.Errorf("smartcard wallet not supported yet") -} - -// InitializeWallet initializes a new wallet at the provided URL, by generating and returning a new private key. -func (api *PersonalAPI) InitializeWallet(_ context.Context, url string) (string, error) { - api.logger.Debug("personal_initializeWallet", "url", url) - api.logger.Info("personal_initializeWallet for smartcard wallet not supported") - // TODO: Smartcard wallet not supported yet, refer to: https://github.com/ethereum/go-ethereum/blob/master/accounts/scwallet/README.md - return "", fmt.Errorf("smartcard wallet not supported yet") -} - -// RawWallet is a JSON representation of an accounts.Wallet interface, with its -// data contents extracted into plain fields. -type RawWallet struct { - URL string `json:"url"` - Status string `json:"status"` - Failure string `json:"failure,omitempty"` - Accounts []accounts.Account `json:"accounts,omitempty"` -} - -// ListWallets will return a list of wallets this node manages. -func (api *PersonalAPI) ListWallets() []RawWallet { - api.logger.Debug("personal_ListWallets") - api.logger.Info("currently wallet level that manages accounts is not supported") - return ([]RawWallet)(nil) -} diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index 93259f963..d1d9d2a0c 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -234,11 +234,6 @@ func (k *Keeper) ApplyEvmMsgWithEmptyTxConfig( // - cfg: Encapsulates params required to construct an EVM. // - tracer: Collects execution traces for EVM transaction logging. // - stateDB: Holds the EVM state. -// -// [NewEVM] sets the validator operator address as the coinbase address to make -// it available for the COINBASE opcode. This is done for backwards -// compatibility. There is no benficiary of the COINBASE tx opcode because we use -// post-merge Ethereum (Proof of Stake rather than Proof of Work). func (k *Keeper) NewEVM( ctx sdk.Context, msg core.Message,