update chain-id format (#542)

* chain_id.go

* rpc changes

* update scripts

* additional test

* changelog

* fix tests

* update script

* rpc updates

* validate testnet command chain-id

* validate rest server chain-id

* fix lint

* rpc updates

* changelog

* comment simulations
This commit is contained in:
Federico Kunze 2020-09-24 19:50:47 +02:00 committed by GitHub
parent b9a10b3f3e
commit a924b20091
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 427 additions and 301 deletions

View File

@ -16,111 +16,106 @@ jobs:
- uses: rokroskar/workflow-run-cleanup-action@master - uses: rokroskar/workflow-run-cleanup-action@master
env: env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
# install-runsim:
install-runsim: # runs-on: ubuntu-latest
runs-on: ubuntu-latest # if: "!contains(github.event.head_commit.message, 'skip-sims')"
if: "!contains(github.event.head_commit.message, 'skip-sims')" # steps:
steps: # - uses: actions/setup-go@v2.1.2
- uses: actions/setup-go@v2.1.2 # - name: install runsim
- name: install runsim # run: |
run: | # export GO111MODULE="on" && go get github.com/cosmos/tools/cmd/runsim@v1.0.0
export GO111MODULE="on" && go get github.com/cosmos/tools/cmd/runsim@v1.0.0 # - uses: actions/cache@v2.1.1
- uses: actions/cache@v2.1.1 # with:
with: # path: ~/go/bin
path: ~/go/bin # key: ${{ runner.os }}-go-runsim-binary
key: ${{ runner.os }}-go-runsim-binary # test-sim-nondeterminism:
# runs-on: ubuntu-latest
test-sim-nondeterminism: # if: "!contains(github.event.head_commit.message, 'skip-sims')"
runs-on: ubuntu-latest # needs: install-runsim
if: "!contains(github.event.head_commit.message, 'skip-sims')" # steps:
needs: install-runsim # - uses: actions/checkout@v2
steps: # - uses: technote-space/get-diff-action@v3.2
- uses: actions/checkout@v2 # with:
- uses: technote-space/get-diff-action@v3.2 # SUFFIX_FILTER: |
with: # .go
SUFFIX_FILTER: | # .mod
.go # .sum
.mod # SET_ENV_NAME_INSERTIONS: 1
.sum # SET_ENV_NAME_LINES: 1
SET_ENV_NAME_INSERTIONS: 1 # - uses: actions/cache@v2.1.1
SET_ENV_NAME_LINES: 1 # with:
- uses: actions/cache@v2.1.1 # path: ~/go/bin
with: # key: ${{ runner.os }}-go-runsim-binary
path: ~/go/bin # if: "env.GIT_DIFF != ''"
key: ${{ runner.os }}-go-runsim-binary # - name: test-sim-nondeterminism
if: "env.GIT_DIFF != ''" # run: |
- name: test-sim-nondeterminism # make test-sim-nondeterminism
run: | # if: "env.GIT_DIFF != ''"
make test-sim-nondeterminism # test-sim-import-export:
if: "env.GIT_DIFF != ''" # runs-on: ubuntu-latest
# needs: install-runsim
test-sim-import-export: # steps:
runs-on: ubuntu-latest # - uses: actions/checkout@v2
needs: install-runsim # - uses: technote-space/get-diff-action@v3.2
steps: # with:
- uses: actions/checkout@v2 # SUFFIX_FILTER: |
- uses: technote-space/get-diff-action@v3.2 # .go
with: # .mod
SUFFIX_FILTER: | # .sum
.go # SET_ENV_NAME_INSERTIONS: 1
.mod # SET_ENV_NAME_LINES: 1
.sum # - uses: actions/cache@v2.1.1
SET_ENV_NAME_INSERTIONS: 1 # with:
SET_ENV_NAME_LINES: 1 # path: ~/go/bin
- uses: actions/cache@v2.1.1 # key: ${{ runner.os }}-go-runsim-binary
with: # if: "env.GIT_DIFF != ''"
path: ~/go/bin # - name: test-sim-import-export
key: ${{ runner.os }}-go-runsim-binary # run: |
if: "env.GIT_DIFF != ''" # make test-sim-import-export
- name: test-sim-import-export # if: "env.GIT_DIFF != ''"
run: | # test-sim-after-import:
make test-sim-import-export # runs-on: ubuntu-latest
if: "env.GIT_DIFF != ''" # if: "!contains(github.event.head_commit.message, 'skip-sims')"
# needs: install-runsim
test-sim-after-import: # steps:
runs-on: ubuntu-latest # - uses: actions/checkout@v2
if: "!contains(github.event.head_commit.message, 'skip-sims')" # - uses: technote-space/get-diff-action@v3.2
needs: install-runsim # with:
steps: # SUFFIX_FILTER: |
- uses: actions/checkout@v2 # .go
- uses: technote-space/get-diff-action@v3.2 # .mod
with: # .sum
SUFFIX_FILTER: | # SET_ENV_NAME_INSERTIONS: 1
.go # SET_ENV_NAME_LINES: 1
.mod # - uses: actions/cache@v2.1.1
.sum # with:
SET_ENV_NAME_INSERTIONS: 1 # path: ~/go/bin
SET_ENV_NAME_LINES: 1 # key: ${{ runner.os }}-go-runsim-binary
- uses: actions/cache@v2.1.1 # if: "env.GIT_DIFF != ''"
with: # - name: test-sim-after-import
path: ~/go/bin # run: |
key: ${{ runner.os }}-go-runsim-binary # make test-sim-after-import
if: "env.GIT_DIFF != ''" # if: "env.GIT_DIFF != ''"
- name: test-sim-after-import # test-sim-multi-seed-short:
run: | # runs-on: ubuntu-latest
make test-sim-after-import # if: "!contains(github.event.head_commit.message, 'skip-sims')"
if: "env.GIT_DIFF != ''" # needs: install-runsim
# steps:
test-sim-multi-seed-short: # - uses: actions/checkout@v2
runs-on: ubuntu-latest # - uses: technote-space/get-diff-action@v3.2
if: "!contains(github.event.head_commit.message, 'skip-sims')" # with:
needs: install-runsim # SUFFIX_FILTER: |
steps: # .go
- uses: actions/checkout@v2 # .mod
- uses: technote-space/get-diff-action@v3.2 # .sum
with: # SET_ENV_NAME_INSERTIONS: 1
SUFFIX_FILTER: | # SET_ENV_NAME_LINES: 1
.go # - uses: actions/cache@v2.1.1
.mod # with:
.sum # path: ~/go/bin
SET_ENV_NAME_INSERTIONS: 1 # key: ${{ runner.os }}-go-runsim-binary
SET_ENV_NAME_LINES: 1 # if: "env.GIT_DIFF != ''"
- uses: actions/cache@v2.1.1 # - name: test-sim-multi-seed-short
with: # run: |
path: ~/go/bin # make test-sim-multi-seed-short
key: ${{ runner.os }}-go-runsim-binary # if: "env.GIT_DIFF != ''"
if: "env.GIT_DIFF != ''"
- name: test-sim-multi-seed-short
run: |
make test-sim-multi-seed-short
if: "env.GIT_DIFF != ''"

View File

@ -37,6 +37,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
## Unreleased ## 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 ### API Breaking
* (types) [\#503](https://github.com/ChainSafe/ethermint/pull/503) The `types.DenomDefault` constant for `"aphoton"` has been renamed to `types.AttoPhoton`. * (types) [\#503](https://github.com/ChainSafe/ethermint/pull/503) The `types.DenomDefault` constant for `"aphoton"` has been renamed to `types.AttoPhoton`.
@ -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`. * (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) [\#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.
* (`x/evm`) [\#496](https://github.com/ChainSafe/ethermint/pull/496) Fix bugs on `journal.revert` and `CommitStateDB.Copy`. * (`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) [\#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. * (types) [\#513](https://github.com/ChainSafe/ethermint/pull/513) Fix simulated transaction bug that was causing a consensus error by unintentionally affecting the state.

View File

@ -180,7 +180,7 @@ func (suite *AnteTestSuite) TestEthInvalidSig() {
tx, err := newTestEthTx(suite.ctx, ethMsg, priv1) tx, err := newTestEthTx(suite.ctx, ethMsg, priv1)
suite.Require().NoError(err) suite.Require().NoError(err)
ctx := suite.ctx.WithChainID("4") ctx := suite.ctx.WithChainID("ethermint-4")
requireInvalidTx(suite.T(), suite.anteHandler, ctx, tx, false) requireInvalidTx(suite.T(), suite.anteHandler, ctx, tx, false)
} }
@ -253,7 +253,7 @@ func (suite *AnteTestSuite) TestEthInvalidIntrinsicGas() {
func (suite *AnteTestSuite) TestEthInvalidMempoolFees() { func (suite *AnteTestSuite) TestEthInvalidMempoolFees() {
// setup app with checkTx = true // setup app with checkTx = true
suite.app = app.Setup(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.app.EvmKeeper.SetParams(suite.ctx, evmtypes.DefaultParams())
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.EvmKeeper, suite.app.SupplyKeeper) suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.EvmKeeper, suite.app.SupplyKeeper)

View File

@ -10,7 +10,7 @@ import (
authante "github.com/cosmos/cosmos-sdk/x/auth/ante" authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/types" "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" evmtypes "github.com/cosmos/ethermint/x/evm/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -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 // parse the chainID from a string to a base-10 integer
chainID, ok := new(big.Int).SetString(ctx.ChainID(), 10) chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
if !ok { if err != nil {
return ctx, sdkerrors.Wrap(emint.ErrInvalidChainID, ctx.ChainID()) return ctx, err
} }
// validate sender/signature and cache the address // validate sender/signature and cache the address
_, err = msgEthTx.VerifySig(chainID) _, err = msgEthTx.VerifySig(chainIDEpoch)
if err != nil { if err != nil {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "signature verification failed: %s", err.Error()) return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "signature verification failed: %s", err.Error())
} }

View File

@ -2,7 +2,6 @@ package ante_test
import ( import (
"fmt" "fmt"
"math/big"
"testing" "testing"
"time" "time"
@ -37,7 +36,7 @@ func (suite *AnteTestSuite) SetupTest() {
suite.app = app.Setup(checkTx) suite.app = app.Setup(checkTx)
suite.app.Codec().RegisterConcrete(&sdk.TestMsg{}, "test/TestMsg", nil) 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.app.EvmKeeper.SetParams(suite.ctx, evmtypes.DefaultParams())
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.EvmKeeper, suite.app.SupplyKeeper) suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.EvmKeeper, suite.app.SupplyKeeper)
@ -91,9 +90,9 @@ func newTestSDKTx(
} }
func newTestEthTx(ctx sdk.Context, msg evmtypes.MsgEthereumTx, priv tmcrypto.PrivKey) (sdk.Tx, error) { func newTestEthTx(ctx sdk.Context, msg evmtypes.MsgEthereumTx, priv tmcrypto.PrivKey) (sdk.Tx, error) {
chainID, ok := new(big.Int).SetString(ctx.ChainID(), 10) chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
if !ok { if err != nil {
return nil, fmt.Errorf("invalid chainID: %s", ctx.ChainID()) return nil, err
} }
privkey, ok := priv.(crypto.PrivKeySecp256k1) privkey, ok := priv.(crypto.PrivKeySecp256k1)
@ -101,8 +100,7 @@ func newTestEthTx(ctx sdk.Context, msg evmtypes.MsgEthereumTx, priv tmcrypto.Pri
return nil, fmt.Errorf("invalid private key type: %T", priv) return nil, fmt.Errorf("invalid private key type: %T", priv)
} }
err := msg.Sign(chainID, privkey.ToECDSA()) if err := msg.Sign(chainIDEpoch, privkey.ToECDSA()); err != nil {
if err != nil {
return nil, err return nil, err
} }

View File

@ -2,15 +2,17 @@ package client
import ( import (
"fmt" "fmt"
"math/big"
"os" "os"
"path" "path"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/tendermint/tendermint/libs/cli" "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. // InitConfig adds the chain-id, encoding and output flags to the persistent flag set.
@ -47,12 +49,10 @@ func ValidateChainID(baseCmd *cobra.Command) *cobra.Command {
// Function to replace command's RunE function // Function to replace command's RunE function
validateFn := func(cmd *cobra.Command, args []string) error { 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 if !ethermint.IsValidChainID(chainID) {
_, ok := new(big.Int).SetString(chainIDFlag, 10) return fmt.Errorf("invalid chain-id format: %s", chainID)
if !ok {
return fmt.Errorf("invalid chainID: %s, must be base-10 integer format", chainIDFlag)
} }
return baseRunE(cmd, args) return baseRunE(cmd, args)

View File

@ -37,7 +37,7 @@ import (
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cosmos/ethermint/crypto" "github.com/cosmos/ethermint/crypto"
"github.com/cosmos/ethermint/types" ethermint "github.com/cosmos/ethermint/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
) )
@ -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(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(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(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(flagCoinDenom, ethermint.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(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(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") cmd.Flags().String(flagKeyAlgo, string(crypto.EthSecp256k1), "Key signing algorithm to generate keys for")
return cmd return cmd
@ -124,7 +124,11 @@ func InitTestnet(
) error { ) error {
if chainID == "" { 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 { if err := sdk.ValidateDenom(coinDenom); err != nil {
@ -219,7 +223,7 @@ func InitTestnet(
sdk.NewCoin(coinDenom, accStakingTokens), sdk.NewCoin(coinDenom, accStakingTokens),
) )
genAccounts = append(genAccounts, types.EthAccount{ genAccounts = append(genAccounts, ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(addr, coins, nil, 0, 0), BaseAccount: authtypes.NewBaseAccount(addr, coins, nil, 0, 0),
CodeHash: ethcrypto.Keccak256(nil), CodeHash: ethcrypto.Keccak256(nil),
}) })

View File

@ -66,7 +66,9 @@ func main() {
sdkclient.ConfigCmd(app.DefaultCLIHome), sdkclient.ConfigCmd(app.DefaultCLIHome),
queryCmd(cdc), queryCmd(cdc),
txCmd(cdc), txCmd(cdc),
rpc.EmintServeCmd(cdc), client.ValidateChainID(
rpc.EmintServeCmd(cdc),
),
flags.LineBreak, flags.LineBreak,
client.KeyCommands(), client.KeyCommands(),
flags.LineBreak, flags.LineBreak,

View File

@ -22,7 +22,7 @@ This guide helps you create a single validator node that runs a network locally
```bash ```bash
$MONIKER=testing $MONIKER=testing
$KEY=mykey $KEY=mykey
$CHAINID=8 $CHAINID="ethermint-1"
ethermintd init $MONIKER --chain-id=$CHAINID ethermintd init $MONIKER --chain-id=$CHAINID
``` ```

View File

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
KEY="mykey" KEY="mykey"
CHAINID=8 CHAINID="ethermint-1"
MONIKER="localtestnet" MONIKER="localtestnet"
# remove existing daemon and client # remove existing daemon and client

View File

@ -6,14 +6,13 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"os" "os"
"strconv"
"sync" "sync"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/cosmos/ethermint/crypto" "github.com/cosmos/ethermint/crypto"
params "github.com/cosmos/ethermint/rpc/args" 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/utils"
"github.com/cosmos/ethermint/version" "github.com/cosmos/ethermint/version"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
@ -43,27 +42,34 @@ import (
// PublicEthAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec. // PublicEthAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec.
type PublicEthAPI struct { type PublicEthAPI struct {
cliCtx context.CLIContext cliCtx context.CLIContext
logger log.Logger chainIDEpoch *big.Int
backend Backend logger log.Logger
keys []crypto.PrivKeySecp256k1 backend Backend
nonceLock *AddrLocker keys []crypto.PrivKeySecp256k1
keybaseLock sync.Mutex nonceLock *AddrLocker
keybaseLock sync.Mutex
} }
// NewPublicEthAPI creates an instance of the public ETH Web3 API. // NewPublicEthAPI creates an instance of the public ETH Web3 API.
func NewPublicEthAPI(cliCtx context.CLIContext, backend Backend, nonceLock *AddrLocker, func NewPublicEthAPI(cliCtx context.CLIContext, backend Backend, nonceLock *AddrLocker,
key []crypto.PrivKeySecp256k1) *PublicEthAPI { key []crypto.PrivKeySecp256k1) *PublicEthAPI {
api := &PublicEthAPI{ epoch, err := ethermint.ParseChainID(cliCtx.ChainID)
cliCtx: cliCtx,
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 != nil {
panic(err)
}
api := &PublicEthAPI{
cliCtx: cliCtx,
chainIDEpoch: epoch,
logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc"),
backend: backend,
keys: key,
nonceLock: nonceLock,
}
if err := api.getKeybaseInfo(); err != nil {
api.logger.Error("failed to get keybase info", "error", err) api.logger.Error("failed to get keybase info", "error", err)
} }
@ -101,14 +107,7 @@ func (e *PublicEthAPI) ProtocolVersion() hexutil.Uint {
// ChainId returns the chain's identifier in hex format // ChainId returns the chain's identifier in hex format
func (e *PublicEthAPI) ChainId() (hexutil.Uint, error) { // nolint func (e *PublicEthAPI) ChainId() (hexutil.Uint, error) { // nolint
e.logger.Debug("eth_chainId") e.logger.Debug("eth_chainId")
return hexutil.Uint(uint(e.chainIDEpoch.Uint64())), nil
// 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
} }
// Syncing returns whether or not the current node is syncing with other peers. Returns false if not, or a struct // Syncing returns whether or not the current node is syncing with other peers. Returns false if not, or a struct
@ -404,13 +403,13 @@ func (e *PublicEthAPI) SendTransaction(args params.SendTxArgs) (common.Hash, err
// ChainID must be set as flag to send transaction // ChainID must be set as flag to send transaction
chainID := viper.GetString(flags.FlagChainID) chainID := viper.GetString(flags.FlagChainID)
// parse the chainID from a string to a base-10 integer // parse the chainID from a string to a base-10 integer
intChainID, ok := new(big.Int).SetString(chainID, 10) chainIDEpoch, err := ethermint.ParseChainID(chainID)
if !ok { if err != nil {
return common.Hash{}, fmt.Errorf("invalid chainID: %s, must be integer format", chainID) return common.Hash{}, err
} }
// Sign transaction // 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) e.logger.Debug("failed to sign tx", "error", err)
return common.Hash{}, err return common.Hash{}, err
} }
@ -475,7 +474,7 @@ type CallArgs struct {
// Call performs a raw contract call. // Call performs a raw contract call.
func (e *PublicEthAPI) Call(args CallArgs, blockNr BlockNumber, _ *map[common.Address]account) (hexutil.Bytes, error) { 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) 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 { if err != nil {
return []byte{}, err return []byte{}, err
} }
@ -528,7 +527,7 @@ func (e *PublicEthAPI) doCall(
// Set default gas & gas price if none were set // Set default gas & gas price if none were set
// Change this to uint64(math.MaxUint64 / 2) if gas cap can be configured // 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 { if args.Gas != nil {
gas = uint64(*args.Gas) gas = uint64(*args.Gas)
} }
@ -538,7 +537,7 @@ func (e *PublicEthAPI) doCall(
} }
// Set gas price using default or parameter if passed in // 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 { if args.GasPrice != nil {
gasPrice = args.GasPrice.ToInt() gasPrice = args.GasPrice.ToInt()
} }
@ -565,6 +564,10 @@ func (e *PublicEthAPI) doCall(
msg := evmtypes.NewMsgEthermint(0, &toAddr, sdk.NewIntFromBigInt(value), gas, msg := evmtypes.NewMsgEthermint(0, &toAddr, sdk.NewIntFromBigInt(value), gas,
sdk.NewIntFromBigInt(gasPrice), data, sdk.AccAddress(addr.Bytes())) 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) // Generate tx to be used to simulate (signature isn't needed)
var stdSig authtypes.StdSignature var stdSig authtypes.StdSignature
tx := authtypes.NewStdTx([]sdk.Msg{msg}, authtypes.StdFee{}, []authtypes.StdSignature{stdSig}, "") tx := authtypes.NewStdTx([]sdk.Msg{msg}, authtypes.StdFee{}, []authtypes.StdSignature{stdSig}, "")
@ -594,7 +597,7 @@ func (e *PublicEthAPI) doCall(
// param from the SDK. // param from the SDK.
func (e *PublicEthAPI) EstimateGas(args CallArgs) (hexutil.Uint64, error) { func (e *PublicEthAPI) EstimateGas(args CallArgs) (hexutil.Uint64, error) {
e.logger.Debug("eth_estimateGas", "args", args) 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 { if err != nil {
return 0, err return 0, err
} }
@ -1000,7 +1003,7 @@ func (e *PublicEthAPI) generateFromArgs(args params.SendTxArgs) (*evmtypes.MsgEt
// Set default gas price // Set default gas price
// TODO: Change to min gas price from context once available through server/daemon // 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 { if args.Nonce == nil {

View File

@ -2,12 +2,12 @@ package rpc
import ( import (
"fmt" "fmt"
"strconv"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/flags" "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. // PublicNetAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec.
@ -19,13 +19,13 @@ type PublicNetAPI struct {
func NewPublicNetAPI(_ context.CLIContext) *PublicNetAPI { func NewPublicNetAPI(_ context.CLIContext) *PublicNetAPI {
chainID := viper.GetString(flags.FlagChainID) chainID := viper.GetString(flags.FlagChainID)
// parse the chainID from a integer string // parse the chainID from a integer string
intChainID, err := strconv.ParseUint(chainID, 0, 64) chainIDEpoch, err := ethermint.ParseChainID(chainID)
if err != nil { if err != nil {
panic(fmt.Sprintf("invalid chainID: %s, must be integer format", chainID)) panic(err)
} }
return &PublicNetAPI{ return &PublicNetAPI{
networkVersion: intChainID, networkVersion: chainIDEpoch.Uint64(),
} }
} }

View File

@ -2,7 +2,7 @@
KEY="mykey" KEY="mykey"
TESTKEY="test" TESTKEY="test"
CHAINID=123321 CHAINID="ethermint-100"
MONIKER="localtestnet" MONIKER="localtestnet"
# stop and remove existing daemon and client data and process(es) # stop and remove existing daemon and client data and process(es)

View File

@ -15,7 +15,7 @@ IP_ADDR="0.0.0.0"
MODE="rpc" MODE="rpc"
KEY="mykey" KEY="mykey"
CHAINID=8 CHAINID="ethermint-2"
MONIKER="mymoniker" MONIKER="mymoniker"
## default port prefixes for ethermintd ## default port prefixes for ethermintd
@ -24,25 +24,25 @@ NODE_PORT="2663"
NODE_RPC_PORT="2666" NODE_RPC_PORT="2666"
usage() { usage() {
echo "Usage: $SCRIPT" echo "Usage: $SCRIPT"
echo "Optional command line arguments" echo "Optional command line arguments"
echo "-t <string> -- Test to run. eg: rpc" echo "-t <string> -- Test to run. eg: rpc"
echo "-q <number> -- Quantity of nodes to run. eg: 3" echo "-q <number> -- Quantity of nodes to run. eg: 3"
echo "-z <number> -- Quantity of nodes to run tests against eg: 3" echo "-z <number> -- Quantity of nodes to run tests against eg: 3"
echo "-s <number> -- Sleep between operations in secs. eg: 5" echo "-s <number> -- Sleep between operations in secs. eg: 5"
exit 1 exit 1
} }
while getopts "h?t:q:z:s:" args; do while getopts "h?t:q:z:s:" args; do
case $args in case $args in
h|\?) h|\?)
usage; usage;
exit;; exit;;
t ) TEST=${OPTARG};; t ) TEST=${OPTARG};;
q ) QTD=${OPTARG};; q ) QTD=${OPTARG};;
z ) TEST_QTD=${OPTARG};; z ) TEST_QTD=${OPTARG};;
s ) SLEEP_TIMEOUT=${OPTARG};; s ) SLEEP_TIMEOUT=${OPTARG};;
esac esac
done done
set -euxo pipefail set -euxo pipefail
@ -50,15 +50,15 @@ set -euxo pipefail
DATA_DIR=$(mktemp -d -t ethermint-datadir.XXXXX) DATA_DIR=$(mktemp -d -t ethermint-datadir.XXXXX)
if [[ ! "$DATA_DIR" ]]; then if [[ ! "$DATA_DIR" ]]; then
echo "Could not create $DATA_DIR" echo "Could not create $DATA_DIR"
exit 1 exit 1
fi fi
DATA_CLI_DIR=$(mktemp -d -t ethermint-cli-datadir.XXXXX) DATA_CLI_DIR=$(mktemp -d -t ethermint-cli-datadir.XXXXX)
if [[ ! "$DATA_CLI_DIR" ]]; then if [[ ! "$DATA_CLI_DIR" ]]; then
echo "Could not create $DATA_CLI_DIR" echo "Could not create $DATA_CLI_DIR"
exit 1 exit 1
fi fi
# Compile ethermint # Compile ethermint
@ -72,64 +72,64 @@ arr=()
arrcli=() arrcli=()
init_func() { init_func() {
echo "create and add new keys" echo "create and add new keys"
"$PWD"/build/ethermintcli config keyring-backend test --home "$DATA_CLI_DIR$i" "$PWD"/build/ethermintcli config keyring-backend test --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintcli keys add $KEY"$i" --home "$DATA_CLI_DIR$i" --no-backup --chain-id $CHAINID "$PWD"/build/ethermintcli keys add $KEY"$i" --home "$DATA_CLI_DIR$i" --no-backup --chain-id $CHAINID
echo "init Ethermint with moniker=$MONIKER and chain-id=$CHAINID" echo "init Ethermint with moniker=$MONIKER and chain-id=$CHAINID"
"$PWD"/build/ethermintd init $MONIKER --chain-id $CHAINID --home "$DATA_DIR$i" "$PWD"/build/ethermintd init $MONIKER --chain-id $CHAINID --home "$DATA_DIR$i"
echo "init ethermintcli with chain-id=$CHAINID and config it trust-node true" echo "init ethermintcli with chain-id=$CHAINID and config it trust-node true"
"$PWD"/build/ethermintcli config chain-id $CHAINID --home "$DATA_CLI_DIR$i" "$PWD"/build/ethermintcli config chain-id $CHAINID --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintcli config output json --home "$DATA_CLI_DIR$i" "$PWD"/build/ethermintcli config output json --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintcli config indent true --home "$DATA_CLI_DIR$i" "$PWD"/build/ethermintcli config indent true --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintcli config trust-node true --home "$DATA_CLI_DIR$i" "$PWD"/build/ethermintcli config trust-node true --home "$DATA_CLI_DIR$i"
echo "prepare genesis: Allocate genesis accounts" echo "prepare genesis: Allocate genesis accounts"
"$PWD"/build/ethermintd add-genesis-account \ "$PWD"/build/ethermintd add-genesis-account \
"$("$PWD"/build/ethermintcli keys show "$KEY$i" -a --home "$DATA_CLI_DIR$i" )" 1000000000000000000aphoton,1000000000000000000stake \ "$("$PWD"/build/ethermintcli keys show "$KEY$i" -a --home "$DATA_CLI_DIR$i" )" 1000000000000000000aphoton,1000000000000000000stake \
--home "$DATA_DIR$i" --home-client "$DATA_CLI_DIR$i" --home "$DATA_DIR$i" --home-client "$DATA_CLI_DIR$i"
echo "prepare genesis: Sign genesis transaction" echo "prepare genesis: Sign genesis transaction"
"$PWD"/build/ethermintd gentx --name $KEY"$i" --keyring-backend test --home "$DATA_DIR$i" --home-client "$DATA_CLI_DIR$i" "$PWD"/build/ethermintd gentx --name $KEY"$i" --keyring-backend test --home "$DATA_DIR$i" --home-client "$DATA_CLI_DIR$i"
echo "prepare genesis: Collect genesis tx" echo "prepare genesis: Collect genesis tx"
"$PWD"/build/ethermintd collect-gentxs --home "$DATA_DIR$i" "$PWD"/build/ethermintd collect-gentxs --home "$DATA_DIR$i"
echo "prepare genesis: Run validate-genesis to ensure everything worked and that the genesis file is setup correctly" echo "prepare genesis: Run validate-genesis to ensure everything worked and that the genesis file is setup correctly"
"$PWD"/build/ethermintd validate-genesis --home "$DATA_DIR$i" "$PWD"/build/ethermintd validate-genesis --home "$DATA_DIR$i"
} }
start_func() { start_func() {
echo "starting ethermint node $i in background ..." echo "starting ethermint node $i in background ..."
"$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe --log_level "main:info,state:info,mempool:info" \ "$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe --log_level "main:info,state:info,mempool:info" \
--p2p.laddr tcp://$IP_ADDR:$NODE_P2P_PORT"$i" --address tcp://$IP_ADDR:$NODE_PORT"$i" --rpc.laddr tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \ --p2p.laddr tcp://$IP_ADDR:$NODE_P2P_PORT"$i" --address tcp://$IP_ADDR:$NODE_PORT"$i" --rpc.laddr tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \
--home "$DATA_DIR$i" \ --home "$DATA_DIR$i" \
>"$DATA_DIR"/node"$i".log 2>&1 & disown >"$DATA_DIR"/node"$i".log 2>&1 & disown
ETHERMINT_PID=$! ETHERMINT_PID=$!
echo "started ethermint node, pid=$ETHERMINT_PID" echo "started ethermint node, pid=$ETHERMINT_PID"
# add PID to array # add PID to array
arr+=("$ETHERMINT_PID") arr+=("$ETHERMINT_PID")
} }
start_cli_func() { start_cli_func() {
echo "starting ethermint node $i in background ..." echo "starting ethermint node $i in background ..."
"$PWD"/build/ethermintcli rest-server --unlock-key $KEY"$i" --chain-id $CHAINID --trace \ "$PWD"/build/ethermintcli rest-server --unlock-key $KEY"$i" --chain-id $CHAINID --trace \
--laddr "tcp://localhost:$RPC_PORT$i" --node tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \ --laddr "tcp://localhost:$RPC_PORT$i" --node tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \
--home "$DATA_CLI_DIR$i" --read-timeout 30 --write-timeout 30 \ --home "$DATA_CLI_DIR$i" --read-timeout 30 --write-timeout 30 \
>"$DATA_CLI_DIR"/cli"$i".log 2>&1 & disown >"$DATA_CLI_DIR"/cli"$i".log 2>&1 & disown
ETHERMINT_CLI_PID=$! ETHERMINT_CLI_PID=$!
echo "started ethermintcli node, pid=$ETHERMINT_CLI_PID" echo "started ethermintcli node, pid=$ETHERMINT_CLI_PID"
# add PID to array # add PID to array
arrcli+=("$ETHERMINT_CLI_PID") arrcli+=("$ETHERMINT_CLI_PID")
} }
# Run node with static blockchain database # Run node with static blockchain database
# For loop N times # For loop N times
for i in $(seq 1 "$QTD"); do for i in $(seq 1 "$QTD"); do
init_func "$i" init_func "$i"
start_func "$i" start_func "$i"
sleep 1 sleep 1
start_cli_func "$i" start_cli_func "$i"
echo "sleeping $SLEEP_TIMEOUT seconds for startup" echo "sleeping $SLEEP_TIMEOUT seconds for startup"
sleep "$SLEEP_TIMEOUT" sleep "$SLEEP_TIMEOUT"
echo "done sleeping" echo "done sleeping"
done done
echo "sleeping $SLEEP_TIMEOUT seconds before running tests ... " echo "sleeping $SLEEP_TIMEOUT seconds before running tests ... "
@ -139,37 +139,37 @@ echo "done sleeping"
set +e set +e
if [[ -z $TEST || $TEST == "rpc" ]]; then if [[ -z $TEST || $TEST == "rpc" ]]; then
for i in $(seq 1 "$TEST_QTD"); do for i in $(seq 1 "$TEST_QTD"); do
HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i" HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i"
echo "going to test ethermint node $HOST_RPC ..." echo "going to test ethermint node $HOST_RPC ..."
MODE=$MODE HOST=$HOST_RPC go test ./tests/... -timeout=300s -v -short MODE=$MODE HOST=$HOST_RPC go test ./tests/... -timeout=300s -v -short
RPC_FAIL=$? RPC_FAIL=$?
done done
fi fi
stop_func() { stop_func() {
ETHERMINT_PID=$i ETHERMINT_PID=$i
echo "shutting down node, pid=$ETHERMINT_PID ..." echo "shutting down node, pid=$ETHERMINT_PID ..."
# Shutdown ethermint node # Shutdown ethermint node
kill -9 "$ETHERMINT_PID" kill -9 "$ETHERMINT_PID"
wait "$ETHERMINT_PID" wait "$ETHERMINT_PID"
} }
for i in "${arrcli[@]}"; do for i in "${arrcli[@]}"; do
stop_func "$i" stop_func "$i"
done done
for i in "${arr[@]}"; do for i in "${arr[@]}"; do
stop_func "$i" stop_func "$i"
done done
if [[ (-z $TEST || $TEST == "rpc") && $RPC_FAIL -ne 0 ]]; then if [[ (-z $TEST || $TEST == "rpc") && $RPC_FAIL -ne 0 ]]; then
exit $RPC_FAIL exit $RPC_FAIL
else else
exit 0 exit 0
fi fi

View File

@ -2,27 +2,29 @@
export GOPATH=~/go export GOPATH=~/go
export PATH=$PATH:$GOPATH/bin export PATH=$PATH:$GOPATH/bin
go build -o ./build/ethermintd ./cmd/ethermintd go build -o ./build/ethermintd ./cmd/ethermintd
go build -o ./build/ethermintcli ./cmd/ethermintcli go build -o ./build/ethermintcli ./cmd/ethermintcli
mkdir $GOPATH/bin mkdir $GOPATH/bin
cp ./build/ethermintd $GOPATH/bin cp ./build/ethermintd $GOPATH/bin
cp ./build/ethermintcli $GOPATH/bin cp ./build/ethermintcli $GOPATH/bin
CHAINID="ethermint-1337"
cd tests-solidity cd tests-solidity
if command -v yarn &> /dev/null; then if command -v yarn &> /dev/null; then
yarn install yarn install
else else
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt update && sudo apt install yarn sudo apt update && sudo apt install yarn
yarn install yarn install
fi fi
chmod +x ./init-test-node.sh chmod +x ./init-test-node.sh
./init-test-node.sh > ethermintd.log & ./init-test-node.sh > ethermintd.log &
sleep 5 sleep 5
ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key localkey,user1,user2 --chain-id 1337 --trace --wsport 8546 > ethermintcli.log & ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key localkey,user1,user2 --chain-id $CHAINID --trace --wsport 8546 > ethermintcli.log &
cd suites/initializable cd suites/initializable
yarn test-ethermint yarn test-ethermint
@ -30,7 +32,7 @@ yarn test-ethermint
ok=$? ok=$?
if (( $? != 0 )); then if (( $? != 0 )); then
echo "initializable test failed: exit code $?" echo "initializable test failed: exit code $?"
fi fi
killall ethermintcli killall ethermintcli
@ -43,7 +45,7 @@ exit $ok
./../../init-test-node.sh > ethermintd.log & ./../../init-test-node.sh > ethermintd.log &
sleep 5 sleep 5
ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key localkey,user1,user2 --chain-id 1337 --trace --wsport 8546 > ethermintcli.log & ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key localkey,user1,user2 --chain-id $CHAINID --trace --wsport 8546 > ethermintcli.log &
cd ../initializable-buidler cd ../initializable-buidler
yarn test-ethermint yarn test-ethermint
@ -51,7 +53,7 @@ yarn test-ethermint
ok=$(($? + $ok)) ok=$(($? + $ok))
if (( $? != 0 )); then if (( $? != 0 )); then
echo "initializable-buidler test failed: exit code $?" echo "initializable-buidler test failed: exit code $?"
fi fi
killall ethermintcli killall ethermintcli

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
ethermintd --home /ethermint/node$ID/ethermintd/ start > ethermintd.log & ethermintd --home /ethermint/node$ID/ethermintd/ start > ethermintd.log &
sleep 5 sleep 5
ethermintcli rest-server --laddr "tcp://localhost:8545" --chain-id 7305661614933169792 --trace > ethermintcli.log & ethermintcli rest-server --laddr "tcp://localhost:8545" --chain-id "ethermint-7305661614933169792" --trace > ethermintcli.log &
tail -f /dev/null tail -f /dev/null

View File

@ -25,7 +25,7 @@ In the first, run `ethermintd`:
In the second, run `ethermintcli` as mentioned in the script's output: In the second, run `ethermintcli` as mentioned in the script's output:
```sh ```sh
ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key localkey,user1,user2 --chain-id 1337 --trace --wsport 8546 ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key localkey,user1,user2 --chain-id "ethermint-1337" --trace --wsport 8546
``` ```
You will now have three ethereum accounts unlocked in the test node: You will now have three ethereum accounts unlocked in the test node:
@ -83,7 +83,7 @@ Running `ethermintcli list keys` should output:
And running: And running:
``` ```sh
curl localhost:8545 -H "Content-Type:application/json" -X POST --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1}' curl localhost:8545 -H "Content-Type:application/json" -X POST --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1}'
``` ```

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
CHAINID=1337 CHAINID="ethermint-1337"
MONIKER="localtestnet" MONIKER="localtestnet"
VAL_KEY="localkey" VAL_KEY="localkey"

48
types/chain_id.go Normal file
View File

@ -0,0 +1,48 @@
package types
import (
"fmt"
"math/big"
"regexp"
"strings"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
var (
regexChainID = `[a-z]*`
regexSeparator = `-{1}`
regexEpoch = `[1-9][0-9]*`
ethermintChainID = regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)$`, regexChainID, regexSeparator, regexEpoch))
)
// IsValidChainID returns false if the given chain identifier is incorrectly formatted.
func IsValidChainID(chainID string) bool {
if len(chainID) > 48 {
return false
}
return ethermintChainID.MatchString(chainID)
}
// ParseChainID parses a string chain identifier's epoch to an Ethereum-compatible
// chain-id in *big.Int format. The function returns an error if the chain-id has an invalid format
func ParseChainID(chainID string) (*big.Int, error) {
chainID = strings.TrimSpace(chainID)
if len(chainID) > 48 {
return nil, sdkerrors.Wrapf(ErrInvalidChainID, "chain-id '%s' cannot exceed 48 chars", chainID)
}
matches := ethermintChainID.FindStringSubmatch(chainID)
if matches == nil || len(matches) != 3 || matches[1] == "" {
return nil, sdkerrors.Wrap(ErrInvalidChainID, chainID)
}
// verify that the chain-id entered is a base 10 integer
chainIDInt, ok := new(big.Int).SetString(matches[2], 10)
if !ok {
return nil, sdkerrors.Wrapf(ErrInvalidChainID, "epoch %s must be base-10 integer format", matches[2])
}
return chainIDInt, nil
}

75
types/chain_id_test.go Normal file
View File

@ -0,0 +1,75 @@
package types
import (
"math/big"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func TestParseChainID(t *testing.T) {
testCases := []struct {
name string
chainID string
expError bool
expInt *big.Int
}{
{
"valid chain-id, single digit", "ethermint-1", false, big.NewInt(1),
},
{
"valid chain-id, multiple digits", "aragonchain-256", false, big.NewInt(256),
},
{
"invalid chain-id, double dash", "aragon-chain-1", true, nil,
},
{
"invalid chain-id, dash only", "-", true, nil,
},
{
"invalid chain-id, undefined", "-1", true, nil,
},
{
"invalid chain-id, uppercases", "ETHERMINT-1", true, nil,
},
{
"invalid chain-id, mixed cases", "Ethermint-1", true, nil,
},
{
"invalid chain-id, special chars", "$&*#!-1", true, nil,
},
{
"invalid epoch, cannot start with 0", "ethermint-001", true, nil,
},
{
"invalid epoch, cannot invalid base", "ethermint-0x212", true, nil,
},
{
"invalid epoch, non-integer", "ethermint-ethermint", true, nil,
},
{
"invalid epoch, undefined", "ethermint-", true, nil,
},
{
"blank chain ID", " ", true, nil,
},
{
"empty chain ID", "", true, nil,
},
{
"long chain-id", "ethermint-" + strings.Repeat("1", 40), true, nil,
},
}
for _, tc := range testCases {
chainIDEpoch, err := ParseChainID(tc.chainID)
if tc.expError {
require.Error(t, err, tc.name)
require.Nil(t, chainIDEpoch)
} else {
require.NoError(t, err, tc.name)
require.Equal(t, tc.expInt, chainIDEpoch, tc.name)
}
}
}

View File

@ -1,11 +1,9 @@
package evm package evm
import ( import (
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
emint "github.com/cosmos/ethermint/types" ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/x/evm/types" "github.com/cosmos/ethermint/x/evm/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -32,13 +30,13 @@ func NewHandler(k Keeper) sdk.Handler {
// handleMsgEthereumTx handles an Ethereum specific tx // handleMsgEthereumTx handles an Ethereum specific tx
func handleMsgEthereumTx(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) (*sdk.Result, error) { func handleMsgEthereumTx(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) (*sdk.Result, error) {
// parse the chainID from a string to a base-10 integer // parse the chainID from a string to a base-10 integer
intChainID, ok := new(big.Int).SetString(ctx.ChainID(), 10) chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
if !ok { if err != nil {
return nil, sdkerrors.Wrap(emint.ErrInvalidChainID, ctx.ChainID()) return nil, err
} }
// Verify signature and retrieve sender address // Verify signature and retrieve sender address
sender, err := msg.VerifySig(intChainID) sender, err := msg.VerifySig(chainIDEpoch)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -54,7 +52,7 @@ func handleMsgEthereumTx(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) (*s
Amount: msg.Data.Amount, Amount: msg.Data.Amount,
Payload: msg.Data.Payload, Payload: msg.Data.Payload,
Csdb: k.CommitStateDB.WithContext(ctx), Csdb: k.CommitStateDB.WithContext(ctx),
ChainID: intChainID, ChainID: chainIDEpoch,
TxHash: &ethHash, TxHash: &ethHash,
Sender: sender, Sender: sender,
Simulate: ctx.IsCheckTx(), Simulate: ctx.IsCheckTx(),
@ -123,9 +121,9 @@ func handleMsgEthereumTx(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) (*s
// handleMsgEthermint handles an sdk.StdTx for an Ethereum state transition // handleMsgEthermint handles an sdk.StdTx for an Ethereum state transition
func handleMsgEthermint(ctx sdk.Context, k Keeper, msg types.MsgEthermint) (*sdk.Result, error) { func handleMsgEthermint(ctx sdk.Context, k Keeper, msg types.MsgEthermint) (*sdk.Result, error) {
// parse the chainID from a string to a base-10 integer // parse the chainID from a string to a base-10 integer
intChainID, ok := new(big.Int).SetString(ctx.ChainID(), 10) chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
if !ok { if err != nil {
return nil, sdkerrors.Wrap(emint.ErrInvalidChainID, ctx.ChainID()) return nil, err
} }
txHash := tmtypes.Tx(ctx.TxBytes()).Hash() txHash := tmtypes.Tx(ctx.TxBytes()).Hash()
@ -138,7 +136,7 @@ func handleMsgEthermint(ctx sdk.Context, k Keeper, msg types.MsgEthermint) (*sdk
Amount: msg.Amount.BigInt(), Amount: msg.Amount.BigInt(),
Payload: msg.Payload, Payload: msg.Payload,
Csdb: k.CommitStateDB.WithContext(ctx), Csdb: k.CommitStateDB.WithContext(ctx),
ChainID: intChainID, ChainID: chainIDEpoch,
TxHash: &ethHash, TxHash: &ethHash,
Sender: common.BytesToAddress(msg.From.Bytes()), Sender: common.BytesToAddress(msg.From.Bytes()),
Simulate: ctx.IsCheckTx(), Simulate: ctx.IsCheckTx(),

View File

@ -21,6 +21,7 @@ import (
"github.com/cosmos/ethermint/app" "github.com/cosmos/ethermint/app"
"github.com/cosmos/ethermint/crypto" "github.com/cosmos/ethermint/crypto"
ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/x/evm" "github.com/cosmos/ethermint/x/evm"
"github.com/cosmos/ethermint/x/evm/keeper" "github.com/cosmos/ethermint/x/evm/keeper"
"github.com/cosmos/ethermint/x/evm/types" "github.com/cosmos/ethermint/x/evm/types"
@ -43,7 +44,7 @@ func (suite *EvmTestSuite) SetupTest() {
checkTx := false checkTx := false
suite.app = app.Setup(checkTx) suite.app = app.Setup(checkTx)
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.handler = evm.NewHandler(suite.app.EvmKeeper) suite.handler = evm.NewHandler(suite.app.EvmKeeper)
suite.querier = keeper.NewQuerier(suite.app.EvmKeeper) suite.querier = keeper.NewQuerier(suite.app.EvmKeeper)
suite.codec = codec.New() suite.codec = codec.New()
@ -58,10 +59,7 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
suite.Require().NoError(err) suite.Require().NoError(err)
sender := ethcmn.HexToAddress(privkey.PubKey().Address().String()) sender := ethcmn.HexToAddress(privkey.PubKey().Address().String())
var ( var tx types.MsgEthereumTx
tx types.MsgEthereumTx
chainID *big.Int
)
testCases := []struct { testCases := []struct {
msg string msg string
@ -75,9 +73,8 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
tx = types.NewMsgEthereumTx(0, &sender, big.NewInt(100), 0, big.NewInt(10000), nil) tx = types.NewMsgEthereumTx(0, &sender, big.NewInt(100), 0, big.NewInt(10000), nil)
// parse context chain ID to big.Int // parse context chain ID to big.Int
var ok bool chainID, err := ethermint.ParseChainID(suite.ctx.ChainID())
chainID, ok = new(big.Int).SetString(suite.ctx.ChainID(), 10) suite.Require().NoError(err)
suite.Require().True(ok)
// sign transaction // sign transaction
err = tx.Sign(chainID, privkey.ToECDSA()) err = tx.Sign(chainID, privkey.ToECDSA())
@ -91,9 +88,8 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
tx = types.NewMsgEthereumTxContract(0, big.NewInt(100), 0, big.NewInt(10000), nil) tx = types.NewMsgEthereumTxContract(0, big.NewInt(100), 0, big.NewInt(10000), nil)
// parse context chain ID to big.Int // parse context chain ID to big.Int
var ok bool chainID, err := ethermint.ParseChainID(suite.ctx.ChainID())
chainID, ok = new(big.Int).SetString(suite.ctx.ChainID(), 10) suite.Require().NoError(err)
suite.Require().True(ok)
// sign transaction // sign transaction
err = tx.Sign(chainID, privkey.ToECDSA()) err = tx.Sign(chainID, privkey.ToECDSA())
@ -125,7 +121,7 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
} }
for _, tc := range testCases { for _, tc := range testCases {
suite.Run("", func() { suite.Run(tc.msg, func() {
suite.SetupTest() // reset suite.SetupTest() // reset
//nolint //nolint
tc.malleate() tc.malleate()