Skip to content
This repository has been archived by the owner on Nov 30, 2021. It is now read-only.

update chain-id format #542

Merged
merged 15 commits into from
Sep 24, 2020
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ Ref: https://keepachangelog.com/en/1.0.0/

## Unreleased

### State Machine Breaking

* (app) [\#540](https://github.com/ChainSafe/ethermint/issues/540) Chain identifier's format has been changed to match the Cosmos `chainID` [standard](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-5.md), which is required for IBC. The epoch number of the ID is used as the EVM `chainID`.

### API Breaking

* (types) [\#503](https://github.com/ChainSafe/ethermint/pull/503) The `types.DenomDefault` constant for `"aphoton"` has been renamed to `types.AttoPhoton`.
Expand All @@ -57,6 +61,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

* (ante) [\#525](https://github.com/ChainSafe/ethermint/pull/525) Add message validation decorator to `AnteHandler` for `MsgEthereumTx`.
* (types) [\#507](https://github.com/ChainSafe/ethermint/pull/507) Fix hardcoded `aphoton` on `EthAccount` balance getter and setter.
* (types) [\#501](https://github.com/ChainSafe/ethermint/pull/501) Fix bech32 encoding error by using the compressed ethereum secp256k1 public key.
Copy link
Contributor Author

@fedekunze fedekunze Sep 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgot to add this bug changelog entry

* (`x/evm`) [\#496](https://github.com/ChainSafe/ethermint/pull/496) Fix bugs on `journal.revert` and `CommitStateDB.Copy`.
* (types) [\#480](https://github.com/ChainSafe/ethermint/pull/480) Update [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) coin type to `60` to satisfy [EIP84](https://github.com/ethereum/EIPs/issues/84).
* (types) [\#513](https://github.com/ChainSafe/ethermint/pull/513) Fix simulated transaction bug that was causing a consensus error by unintentionally affecting the state.
Expand Down
4 changes: 2 additions & 2 deletions app/ante/ante_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func (suite *AnteTestSuite) TestEthInvalidSig() {
tx, err := newTestEthTx(suite.ctx, ethMsg, priv1)
suite.Require().NoError(err)

ctx := suite.ctx.WithChainID("4")
ctx := suite.ctx.WithChainID("ethermint-4")
requireInvalidTx(suite.T(), suite.anteHandler, ctx, tx, false)
}

Expand Down Expand Up @@ -253,7 +253,7 @@ func (suite *AnteTestSuite) TestEthInvalidIntrinsicGas() {
func (suite *AnteTestSuite) TestEthInvalidMempoolFees() {
// setup app with checkTx = true
suite.app = app.Setup(true)
suite.ctx = suite.app.BaseApp.NewContext(true, abci.Header{Height: 1, ChainID: "3", Time: time.Now().UTC()})
suite.ctx = suite.app.BaseApp.NewContext(true, abci.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()})
suite.app.EvmKeeper.SetParams(suite.ctx, evmtypes.DefaultParams())

suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.EvmKeeper, suite.app.SupplyKeeper)
Expand Down
10 changes: 5 additions & 5 deletions app/ante/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/types"

emint "github.com/cosmos/ethermint/types"
ethermint "github.com/cosmos/ethermint/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -141,13 +141,13 @@ func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
}

// parse the chainID from a string to a base-10 integer
chainID, ok := new(big.Int).SetString(ctx.ChainID(), 10)
if !ok {
return ctx, sdkerrors.Wrap(emint.ErrInvalidChainID, ctx.ChainID())
chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
if err != nil {
return ctx, err
}

// validate sender/signature and cache the address
_, err = msgEthTx.VerifySig(chainID)
_, err = msgEthTx.VerifySig(chainIDEpoch)
if err != nil {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "signature verification failed: %s", err.Error())
}
Expand Down
12 changes: 5 additions & 7 deletions app/ante/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package ante_test

import (
"fmt"
"math/big"
"testing"
"time"

Expand Down Expand Up @@ -37,7 +36,7 @@ func (suite *AnteTestSuite) SetupTest() {
suite.app = app.Setup(checkTx)
suite.app.Codec().RegisterConcrete(&sdk.TestMsg{}, "test/TestMsg", nil)

suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "3", Time: time.Now().UTC()})
suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()})
suite.app.EvmKeeper.SetParams(suite.ctx, evmtypes.DefaultParams())

suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.EvmKeeper, suite.app.SupplyKeeper)
Expand Down Expand Up @@ -91,18 +90,17 @@ func newTestSDKTx(
}

func newTestEthTx(ctx sdk.Context, msg evmtypes.MsgEthereumTx, priv tmcrypto.PrivKey) (sdk.Tx, error) {
chainID, ok := new(big.Int).SetString(ctx.ChainID(), 10)
if !ok {
return nil, fmt.Errorf("invalid chainID: %s", ctx.ChainID())
chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
if err != nil {
return nil, err
}

privkey, ok := priv.(crypto.PrivKeySecp256k1)
if !ok {
return nil, fmt.Errorf("invalid private key type: %T", priv)
}

err := msg.Sign(chainID, privkey.ToECDSA())
if err != nil {
if err := msg.Sign(chainIDEpoch, privkey.ToECDSA()); err != nil {
return nil, err
}

Expand Down
14 changes: 7 additions & 7 deletions client/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ package client

import (
"fmt"
"math/big"
"os"
"path"

"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/tendermint/tendermint/libs/cli"

"github.com/cosmos/cosmos-sdk/client/flags"

ethermint "github.com/cosmos/ethermint/types"
)

// InitConfig adds the chain-id, encoding and output flags to the persistent flag set.
Expand Down Expand Up @@ -47,12 +49,10 @@ func ValidateChainID(baseCmd *cobra.Command) *cobra.Command {

// Function to replace command's RunE function
validateFn := func(cmd *cobra.Command, args []string) error {
chainIDFlag := viper.GetString(flags.FlagChainID)
chainID := viper.GetString(flags.FlagChainID)

// Verify that the chain-id entered is a base 10 integer
_, ok := new(big.Int).SetString(chainIDFlag, 10)
if !ok {
return fmt.Errorf("invalid chainID: %s, must be base-10 integer format", chainIDFlag)
if !ethermint.IsValidChainID(chainID) {
return fmt.Errorf("invalid chain-id format: %s", chainID)
}

return baseRunE(cmd, args)
Expand Down
14 changes: 9 additions & 5 deletions client/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import (
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

"github.com/cosmos/ethermint/crypto"
"github.com/cosmos/ethermint/types"
ethermint "github.com/cosmos/ethermint/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
)

Expand Down Expand Up @@ -96,8 +96,8 @@ Note, strict routability for addresses is turned off in the config file.`,
cmd.Flags().String(flagNodeCLIHome, "ethermintcli", "Home directory of the node's cli configuration")
cmd.Flags().String(flagStartingIPAddress, "192.168.0.1", "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
cmd.Flags().String(flagCoinDenom, types.AttoPhoton, "Coin denomination used for staking, governance, mint, crisis and evm parameters")
cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", types.AttoPhoton), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01aphoton,0.001stake)")
cmd.Flags().String(flagCoinDenom, ethermint.AttoPhoton, "Coin denomination used for staking, governance, mint, crisis and evm parameters")
cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", ethermint.AttoPhoton), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01aphoton,0.001stake)")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
cmd.Flags().String(flagKeyAlgo, string(crypto.EthSecp256k1), "Key signing algorithm to generate keys for")
return cmd
Expand All @@ -124,7 +124,11 @@ func InitTestnet(
) error {

if chainID == "" {
chainID = fmt.Sprintf("%d", tmrand.Int63())
chainID = fmt.Sprintf("ethermint-%d", tmrand.Int63n(9999999999999)+1)
}

if !ethermint.IsValidChainID(chainID) {
return fmt.Errorf("invalid chain-id: %s", chainID)
}

if err := sdk.ValidateDenom(coinDenom); err != nil {
Expand Down Expand Up @@ -219,7 +223,7 @@ func InitTestnet(
sdk.NewCoin(coinDenom, accStakingTokens),
)

genAccounts = append(genAccounts, types.EthAccount{
genAccounts = append(genAccounts, ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(addr, coins, nil, 0, 0),
CodeHash: ethcrypto.Keccak256(nil),
})
Expand Down
4 changes: 3 additions & 1 deletion cmd/ethermintcli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ func main() {
sdkclient.ConfigCmd(app.DefaultCLIHome),
queryCmd(cdc),
txCmd(cdc),
rpc.EmintServeCmd(cdc),
client.ValidateChainID(
rpc.EmintServeCmd(cdc),
),
flags.LineBreak,
client.KeyCommands(),
flags.LineBreak,
Expand Down
2 changes: 1 addition & 1 deletion docs/quickstart/testnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ This guide helps you create a single validator node that runs a network locally
```bash
$MONIKER=testing
$KEY=mykey
$CHAINID=8
$CHAINID="ethermint-1"

ethermintd init $MONIKER --chain-id=$CHAINID
```
Expand Down
2 changes: 1 addition & 1 deletion init.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

KEY="mykey"
CHAINID=8
CHAINID="ethermint-1"
MONIKER="localtestnet"

# remove existing daemon and client
Expand Down
67 changes: 35 additions & 32 deletions rpc/eth_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import (
"fmt"
"math/big"
"os"
"strconv"
"sync"

"github.com/spf13/viper"

"github.com/cosmos/ethermint/crypto"
params "github.com/cosmos/ethermint/rpc/args"
emint "github.com/cosmos/ethermint/types"
ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/utils"
"github.com/cosmos/ethermint/version"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
Expand Down Expand Up @@ -43,27 +42,34 @@ import (

// PublicEthAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec.
type PublicEthAPI struct {
cliCtx context.CLIContext
logger log.Logger
backend Backend
keys []crypto.PrivKeySecp256k1
nonceLock *AddrLocker
keybaseLock sync.Mutex
cliCtx context.CLIContext
chainIDEpoch *big.Int
logger log.Logger
backend Backend
keys []crypto.PrivKeySecp256k1
nonceLock *AddrLocker
keybaseLock sync.Mutex
}

// NewPublicEthAPI creates an instance of the public ETH Web3 API.
func NewPublicEthAPI(cliCtx context.CLIContext, backend Backend, nonceLock *AddrLocker,
key []crypto.PrivKeySecp256k1) *PublicEthAPI {

epoch, err := ethermint.ParseChainID(cliCtx.ChainID)
if err != nil {
panic(err)
}

api := &PublicEthAPI{
cliCtx: cliCtx,
logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc"),
backend: backend,
keys: key,
nonceLock: nonceLock,
cliCtx: cliCtx,
chainIDEpoch: epoch,
logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc"),
backend: backend,
keys: key,
nonceLock: nonceLock,
}
err := api.getKeybaseInfo()
if err != nil {

if err := api.getKeybaseInfo(); err != nil {
api.logger.Error("failed to get keybase info", "error", err)
}

Expand Down Expand Up @@ -101,14 +107,7 @@ func (e *PublicEthAPI) ProtocolVersion() hexutil.Uint {
// ChainId returns the chain's identifier in hex format
func (e *PublicEthAPI) ChainId() (hexutil.Uint, error) { // nolint
e.logger.Debug("eth_chainId")

// parse the chainID from a integer string
intChainID, err := strconv.ParseUint(e.cliCtx.ChainID, 0, 64)
if err != nil {
return 0, fmt.Errorf("invalid chainID: %s, must be integer format", e.cliCtx.ChainID)
}

return hexutil.Uint(intChainID), nil
return hexutil.Uint(uint(e.chainIDEpoch.Uint64())), nil
}

// Syncing returns whether or not the current node is syncing with other peers. Returns false if not, or a struct
Expand Down Expand Up @@ -404,13 +403,13 @@ func (e *PublicEthAPI) SendTransaction(args params.SendTxArgs) (common.Hash, err
// ChainID must be set as flag to send transaction
chainID := viper.GetString(flags.FlagChainID)
// parse the chainID from a string to a base-10 integer
intChainID, ok := new(big.Int).SetString(chainID, 10)
if !ok {
return common.Hash{}, fmt.Errorf("invalid chainID: %s, must be integer format", chainID)
chainIDEpoch, err := ethermint.ParseChainID(chainID)
if err != nil {
return common.Hash{}, err
}

// Sign transaction
if err := tx.Sign(intChainID, key.ToECDSA()); err != nil {
if err := tx.Sign(chainIDEpoch, key.ToECDSA()); err != nil {
e.logger.Debug("failed to sign tx", "error", err)
return common.Hash{}, err
}
Expand Down Expand Up @@ -475,7 +474,7 @@ type CallArgs struct {
// Call performs a raw contract call.
func (e *PublicEthAPI) Call(args CallArgs, blockNr BlockNumber, _ *map[common.Address]account) (hexutil.Bytes, error) {
e.logger.Debug("eth_call", "args", args, "block number", blockNr)
simRes, err := e.doCall(args, blockNr, big.NewInt(emint.DefaultRPCGasLimit))
simRes, err := e.doCall(args, blockNr, big.NewInt(ethermint.DefaultRPCGasLimit))
if err != nil {
return []byte{}, err
}
Expand Down Expand Up @@ -528,7 +527,7 @@ func (e *PublicEthAPI) doCall(

// Set default gas & gas price if none were set
// Change this to uint64(math.MaxUint64 / 2) if gas cap can be configured
gas := uint64(emint.DefaultRPCGasLimit)
gas := uint64(ethermint.DefaultRPCGasLimit)
if args.Gas != nil {
gas = uint64(*args.Gas)
}
Expand All @@ -538,7 +537,7 @@ func (e *PublicEthAPI) doCall(
}

// Set gas price using default or parameter if passed in
gasPrice := new(big.Int).SetUint64(emint.DefaultGasPrice)
gasPrice := new(big.Int).SetUint64(ethermint.DefaultGasPrice)
if args.GasPrice != nil {
gasPrice = args.GasPrice.ToInt()
}
Expand All @@ -565,6 +564,10 @@ func (e *PublicEthAPI) doCall(
msg := evmtypes.NewMsgEthermint(0, &toAddr, sdk.NewIntFromBigInt(value), gas,
sdk.NewIntFromBigInt(gasPrice), data, sdk.AccAddress(addr.Bytes()))

if err := msg.ValidateBasic(); err != nil {
return nil, err
}

// Generate tx to be used to simulate (signature isn't needed)
var stdSig authtypes.StdSignature
tx := authtypes.NewStdTx([]sdk.Msg{msg}, authtypes.StdFee{}, []authtypes.StdSignature{stdSig}, "")
Expand Down Expand Up @@ -594,7 +597,7 @@ func (e *PublicEthAPI) doCall(
// param from the SDK.
func (e *PublicEthAPI) EstimateGas(args CallArgs) (hexutil.Uint64, error) {
e.logger.Debug("eth_estimateGas", "args", args)
simResponse, err := e.doCall(args, 0, big.NewInt(emint.DefaultRPCGasLimit))
simResponse, err := e.doCall(args, 0, big.NewInt(ethermint.DefaultRPCGasLimit))
if err != nil {
return 0, err
}
Expand Down Expand Up @@ -1000,7 +1003,7 @@ func (e *PublicEthAPI) generateFromArgs(args params.SendTxArgs) (*evmtypes.MsgEt

// Set default gas price
// TODO: Change to min gas price from context once available through server/daemon
gasPrice = big.NewInt(emint.DefaultGasPrice)
gasPrice = big.NewInt(ethermint.DefaultGasPrice)
}

if args.Nonce == nil {
Expand Down
8 changes: 4 additions & 4 deletions rpc/net_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package rpc

import (
"fmt"
"strconv"

"github.com/spf13/viper"

"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/flags"
ethermint "github.com/cosmos/ethermint/types"
)

// PublicNetAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec.
Expand All @@ -19,13 +19,13 @@ type PublicNetAPI struct {
func NewPublicNetAPI(_ context.CLIContext) *PublicNetAPI {
chainID := viper.GetString(flags.FlagChainID)
// parse the chainID from a integer string
intChainID, err := strconv.ParseUint(chainID, 0, 64)
chainIDEpoch, err := ethermint.ParseChainID(chainID)
if err != nil {
panic(fmt.Sprintf("invalid chainID: %s, must be integer format", chainID))
panic(err)
}

return &PublicNetAPI{
networkVersion: intChainID,
networkVersion: chainIDEpoch.Uint64(),
}
}

Expand Down
Loading