evm: balance and nonce invariants (#661)
* evm: balance and nonce invariants * nonce invariant * changelog * use iterator on export
This commit is contained in:
parent
6001baed80
commit
a1386eec09
@ -37,13 +37,19 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### API Breaking
|
||||||
|
|
||||||
|
* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) `Balance` field has been removed from the evm module's `GenesisState`.
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
|
|
||||||
|
* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) Add invariant check for account balance and account nonce.
|
||||||
* (deps) [\#654](https://github.com/cosmos/ethermint/pull/654) Bump go-ethereum version to [v1.9.25](https://github.com/ethereum/go-ethereum/releases/tag/v1.9.25)
|
* (deps) [\#654](https://github.com/cosmos/ethermint/pull/654) Bump go-ethereum version to [v1.9.25](https://github.com/ethereum/go-ethereum/releases/tag/v1.9.25)
|
||||||
* (evm) [\#627](https://github.com/cosmos/ethermint/issues/627) Add extra EIPs parameter to apply custom EVM jump tables.
|
* (evm) [\#627](https://github.com/cosmos/ethermint/issues/627) Add extra EIPs parameter to apply custom EVM jump tables.
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) Set nonce to the EVM account on genesis initialization.
|
||||||
* (evm) [\#621](https://github.com/cosmos/ethermint/issues/621) EVM `GenesisAccount` fields now share the same format as the auth module `Account`.
|
* (evm) [\#621](https://github.com/cosmos/ethermint/issues/621) EVM `GenesisAccount` fields now share the same format as the auth module `Account`.
|
||||||
* (evm) [\#618](https://github.com/cosmos/ethermint/issues/618) Add missing EVM `Context` `GetHash` field that retrieves a the header hash from a given block height.
|
* (evm) [\#618](https://github.com/cosmos/ethermint/issues/618) Add missing EVM `Context` `GetHash` field that retrieves a the header hash from a given block height.
|
||||||
* (app) [\#617](https://github.com/cosmos/ethermint/issues/617) Fix genesis export functionality.
|
* (app) [\#617](https://github.com/cosmos/ethermint/issues/617) Fix genesis export functionality.
|
||||||
|
@ -280,7 +280,7 @@ func NewEthermintApp(
|
|||||||
app.mm.SetOrderInitGenesis(
|
app.mm.SetOrderInitGenesis(
|
||||||
auth.ModuleName, distr.ModuleName, staking.ModuleName, bank.ModuleName,
|
auth.ModuleName, distr.ModuleName, staking.ModuleName, bank.ModuleName,
|
||||||
slashing.ModuleName, gov.ModuleName, mint.ModuleName, supply.ModuleName,
|
slashing.ModuleName, gov.ModuleName, mint.ModuleName, supply.ModuleName,
|
||||||
crisis.ModuleName, genutil.ModuleName, evidence.ModuleName, evm.ModuleName,
|
evm.ModuleName, crisis.ModuleName, genutil.ModuleName, evidence.ModuleName,
|
||||||
faucet.ModuleName,
|
faucet.ModuleName,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||||
|
|
||||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||||
|
|
||||||
@ -20,7 +21,6 @@ func InitGenesis(ctx sdk.Context, k Keeper, accountKeeper types.AccountKeeper, d
|
|||||||
for _, account := range data.Accounts {
|
for _, account := range data.Accounts {
|
||||||
address := ethcmn.HexToAddress(account.Address)
|
address := ethcmn.HexToAddress(account.Address)
|
||||||
accAddress := sdk.AccAddress(address.Bytes())
|
accAddress := sdk.AccAddress(address.Bytes())
|
||||||
|
|
||||||
// check that the EVM balance the matches the account balance
|
// check that the EVM balance the matches the account balance
|
||||||
acc := accountKeeper.GetAccount(ctx, accAddress)
|
acc := accountKeeper.GetAccount(ctx, accAddress)
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
@ -37,17 +37,11 @@ func InitGenesis(ctx sdk.Context, k Keeper, accountKeeper types.AccountKeeper, d
|
|||||||
}
|
}
|
||||||
|
|
||||||
evmBalance := acc.GetCoins().AmountOf(evmDenom)
|
evmBalance := acc.GetCoins().AmountOf(evmDenom)
|
||||||
if !evmBalance.Equal(account.Balance) {
|
|
||||||
panic(
|
|
||||||
fmt.Errorf(
|
|
||||||
"balance mismatch for account %s, expected %s%s, got %s%s",
|
|
||||||
account.Address, evmBalance, evmDenom, account.Balance, evmDenom,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
k.SetBalance(ctx, address, account.Balance.BigInt())
|
k.SetNonce(ctx, address, acc.GetSequence())
|
||||||
|
k.SetBalance(ctx, address, evmBalance.BigInt())
|
||||||
k.SetCode(ctx, address, account.Code)
|
k.SetCode(ctx, address, account.Code)
|
||||||
|
|
||||||
for _, storage := range account.Storage {
|
for _, storage := range account.Storage {
|
||||||
k.SetState(ctx, address, storage.Key, storage.Value)
|
k.SetState(ctx, address, storage.Key, storage.Value)
|
||||||
}
|
}
|
||||||
@ -83,12 +77,11 @@ func InitGenesis(ctx sdk.Context, k Keeper, accountKeeper types.AccountKeeper, d
|
|||||||
func ExportGenesis(ctx sdk.Context, k Keeper, ak types.AccountKeeper) GenesisState {
|
func ExportGenesis(ctx sdk.Context, k Keeper, ak types.AccountKeeper) GenesisState {
|
||||||
// nolint: prealloc
|
// nolint: prealloc
|
||||||
var ethGenAccounts []types.GenesisAccount
|
var ethGenAccounts []types.GenesisAccount
|
||||||
accounts := ak.GetAllAccounts(ctx)
|
ak.IterateAccounts(ctx, func(account authexported.Account) bool {
|
||||||
|
|
||||||
for _, account := range accounts {
|
|
||||||
ethAccount, ok := account.(*ethermint.EthAccount)
|
ethAccount, ok := account.(*ethermint.EthAccount)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
// ignore non EthAccounts
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := ethAccount.EthAddress()
|
addr := ethAccount.EthAddress()
|
||||||
@ -98,18 +91,15 @@ func ExportGenesis(ctx sdk.Context, k Keeper, ak types.AccountKeeper) GenesisSta
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
balanceInt := k.GetBalance(ctx, addr)
|
|
||||||
balance := sdk.NewIntFromBigInt(balanceInt)
|
|
||||||
|
|
||||||
genAccount := types.GenesisAccount{
|
genAccount := types.GenesisAccount{
|
||||||
Address: addr.String(),
|
Address: addr.String(),
|
||||||
Balance: balance,
|
|
||||||
Code: k.GetCode(ctx, addr),
|
Code: k.GetCode(ctx, addr),
|
||||||
Storage: storage,
|
Storage: storage,
|
||||||
}
|
}
|
||||||
|
|
||||||
ethGenAccounts = append(ethGenAccounts, genAccount)
|
ethGenAccounts = append(ethGenAccounts, genAccount)
|
||||||
}
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
config, _ := k.GetChainConfig(ctx)
|
config, _ := k.GetChainConfig(ctx)
|
||||||
|
|
||||||
|
@ -54,7 +54,6 @@ func (suite *EvmTestSuite) TestInitGenesis() {
|
|||||||
Accounts: []types.GenesisAccount{
|
Accounts: []types.GenesisAccount{
|
||||||
{
|
{
|
||||||
Address: address.String(),
|
Address: address.String(),
|
||||||
Balance: sdk.OneInt(),
|
|
||||||
Storage: types.Storage{
|
Storage: types.Storage{
|
||||||
{Key: common.BytesToHash([]byte("key")), Value: common.BytesToHash([]byte("value"))},
|
{Key: common.BytesToHash([]byte("key")), Value: common.BytesToHash([]byte("value"))},
|
||||||
},
|
},
|
||||||
@ -87,25 +86,6 @@ func (suite *EvmTestSuite) TestInitGenesis() {
|
|||||||
Accounts: []types.GenesisAccount{
|
Accounts: []types.GenesisAccount{
|
||||||
{
|
{
|
||||||
Address: address.String(),
|
Address: address.String(),
|
||||||
Balance: sdk.OneInt(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"balance mismatch",
|
|
||||||
func() {
|
|
||||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
|
||||||
suite.Require().NotNil(acc)
|
|
||||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
|
||||||
},
|
|
||||||
types.GenesisState{
|
|
||||||
Params: types.DefaultParams(),
|
|
||||||
Accounts: []types.GenesisAccount{
|
|
||||||
{
|
|
||||||
Address: address.String(),
|
|
||||||
Balance: sdk.OneInt(),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
100
x/evm/keeper/invariants.go
Normal file
100
x/evm/keeper/invariants.go
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package keeper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||||
|
|
||||||
|
ethermint "github.com/cosmos/ethermint/types"
|
||||||
|
"github.com/cosmos/ethermint/x/evm/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
balanceInvariant = "balance"
|
||||||
|
nonceInvariant = "nonce"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegisterInvariants registers the evm module invariants
|
||||||
|
func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) {
|
||||||
|
ir.RegisterRoute(types.ModuleName, balanceInvariant, k.BalanceInvariant())
|
||||||
|
ir.RegisterRoute(types.ModuleName, nonceInvariant, k.NonceInvariant())
|
||||||
|
}
|
||||||
|
|
||||||
|
// BalanceInvariant checks that all auth module's EthAccounts in the application have the same balance
|
||||||
|
// as the EVM one.
|
||||||
|
func (k Keeper) BalanceInvariant() sdk.Invariant {
|
||||||
|
return func(ctx sdk.Context) (string, bool) {
|
||||||
|
var (
|
||||||
|
msg string
|
||||||
|
count int
|
||||||
|
)
|
||||||
|
|
||||||
|
k.accountKeeper.IterateAccounts(ctx, func(account authexported.Account) bool {
|
||||||
|
ethAccount, ok := account.(*ethermint.EthAccount)
|
||||||
|
if !ok {
|
||||||
|
// ignore non EthAccounts
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
evmDenom := k.GetParams(ctx).EvmDenom
|
||||||
|
accountBalance := ethAccount.GetCoins().AmountOf(evmDenom)
|
||||||
|
evmBalance := k.GetBalance(ctx, ethAccount.EthAddress())
|
||||||
|
|
||||||
|
if evmBalance.Cmp(accountBalance.BigInt()) != 0 {
|
||||||
|
count++
|
||||||
|
msg += fmt.Sprintf(
|
||||||
|
"\tbalance mismatch for address %s: account balance %s, evm balance %s\n",
|
||||||
|
account.GetAddress(), accountBalance.String(), evmBalance.String(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
broken := count != 0
|
||||||
|
|
||||||
|
return sdk.FormatInvariant(
|
||||||
|
types.ModuleName, balanceInvariant,
|
||||||
|
fmt.Sprintf("account balances mismatches found %d\n%s", count, msg),
|
||||||
|
), broken
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NonceInvariant checks that all auth module's EthAccounts in the application have the same nonce
|
||||||
|
// sequence as the EVM.
|
||||||
|
func (k Keeper) NonceInvariant() sdk.Invariant {
|
||||||
|
return func(ctx sdk.Context) (string, bool) {
|
||||||
|
var (
|
||||||
|
msg string
|
||||||
|
count int
|
||||||
|
)
|
||||||
|
|
||||||
|
k.accountKeeper.IterateAccounts(ctx, func(account authexported.Account) bool {
|
||||||
|
ethAccount, ok := account.(*ethermint.EthAccount)
|
||||||
|
if !ok {
|
||||||
|
// ignore non EthAccounts
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
evmNonce := k.GetNonce(ctx, ethAccount.EthAddress())
|
||||||
|
|
||||||
|
if evmNonce != ethAccount.Sequence {
|
||||||
|
count++
|
||||||
|
msg += fmt.Sprintf(
|
||||||
|
"\nonce mismatch for address %s: account nonce %d, evm nonce %d\n",
|
||||||
|
account.GetAddress(), ethAccount.Sequence, evmNonce,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
broken := count != 0
|
||||||
|
|
||||||
|
return sdk.FormatInvariant(
|
||||||
|
types.ModuleName, nonceInvariant,
|
||||||
|
fmt.Sprintf("account nonces mismatches found %d\n%s", count, msg),
|
||||||
|
), broken
|
||||||
|
}
|
||||||
|
}
|
139
x/evm/keeper/invariants_test.go
Normal file
139
x/evm/keeper/invariants_test.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package keeper_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
|
||||||
|
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||||
|
ethermint "github.com/cosmos/ethermint/types"
|
||||||
|
|
||||||
|
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestBalanceInvariant() {
|
||||||
|
privkey, err := ethsecp256k1.GenerateKey()
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
address := ethcmn.HexToAddress(privkey.PubKey().Address().String())
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
malleate func()
|
||||||
|
expBroken bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"balance mismatch",
|
||||||
|
func() {
|
||||||
|
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||||
|
suite.Require().NotNil(acc)
|
||||||
|
err := acc.SetCoins(sdk.NewCoins(ethermint.NewPhotonCoinInt64(1)))
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
|
||||||
|
suite.app.EvmKeeper.SetBalance(suite.ctx, address, big.NewInt(1000))
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"balance ok",
|
||||||
|
func() {
|
||||||
|
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||||
|
suite.Require().NotNil(acc)
|
||||||
|
err := acc.SetCoins(sdk.NewCoins(ethermint.NewPhotonCoinInt64(1)))
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
|
||||||
|
suite.app.EvmKeeper.SetBalance(suite.ctx, address, big.NewInt(1))
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid account type",
|
||||||
|
func() {
|
||||||
|
acc := authtypes.NewBaseAccountWithAddress(address.Bytes())
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, &acc)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
suite.SetupTest() // reset values
|
||||||
|
|
||||||
|
tc.malleate()
|
||||||
|
|
||||||
|
_, broken := suite.app.EvmKeeper.BalanceInvariant()(suite.ctx)
|
||||||
|
if tc.expBroken {
|
||||||
|
suite.Require().True(broken)
|
||||||
|
} else {
|
||||||
|
suite.Require().False(broken)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestNonceInvariant() {
|
||||||
|
privkey, err := ethsecp256k1.GenerateKey()
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
address := ethcmn.HexToAddress(privkey.PubKey().Address().String())
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
malleate func()
|
||||||
|
expBroken bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"nonce mismatch",
|
||||||
|
func() {
|
||||||
|
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||||
|
suite.Require().NotNil(acc)
|
||||||
|
err := acc.SetSequence(1)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
|
||||||
|
suite.app.EvmKeeper.SetNonce(suite.ctx, address, 100)
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nonce ok",
|
||||||
|
func() {
|
||||||
|
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||||
|
suite.Require().NotNil(acc)
|
||||||
|
err := acc.SetSequence(1)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||||
|
|
||||||
|
suite.app.EvmKeeper.SetNonce(suite.ctx, address, 1)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid account type",
|
||||||
|
func() {
|
||||||
|
acc := authtypes.NewBaseAccountWithAddress(address.Bytes())
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, &acc)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
suite.SetupTest() // reset values
|
||||||
|
|
||||||
|
tc.malleate()
|
||||||
|
|
||||||
|
_, broken := suite.app.EvmKeeper.NonceInvariant()(suite.ctx)
|
||||||
|
if tc.expBroken {
|
||||||
|
suite.Require().True(broken)
|
||||||
|
} else {
|
||||||
|
suite.Require().False(broken)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,8 @@ type Keeper struct {
|
|||||||
// - storing block height -> bloom filter map. Needed for the Web3 API.
|
// - storing block height -> bloom filter map. Needed for the Web3 API.
|
||||||
// - storing block hash -> block height map. Needed for the Web3 API.
|
// - storing block hash -> block height map. Needed for the Web3 API.
|
||||||
storeKey sdk.StoreKey
|
storeKey sdk.StoreKey
|
||||||
|
// Account Keeper for fetching accounts
|
||||||
|
accountKeeper types.AccountKeeper
|
||||||
// Ethermint concrete implementation on the EVM StateDB interface
|
// Ethermint concrete implementation on the EVM StateDB interface
|
||||||
CommitStateDB *types.CommitStateDB
|
CommitStateDB *types.CommitStateDB
|
||||||
// Transaction counter in a block. Used on StateSB's Prepare function.
|
// Transaction counter in a block. Used on StateSB's Prepare function.
|
||||||
@ -52,6 +54,7 @@ func NewKeeper(
|
|||||||
return Keeper{
|
return Keeper{
|
||||||
cdc: cdc,
|
cdc: cdc,
|
||||||
storeKey: storeKey,
|
storeKey: storeKey,
|
||||||
|
accountKeeper: ak,
|
||||||
CommitStateDB: types.NewCommitStateDB(sdk.Context{}, storeKey, paramSpace, ak),
|
CommitStateDB: types.NewCommitStateDB(sdk.Context{}, storeKey, paramSpace, ak),
|
||||||
TxCount: 0,
|
TxCount: 0,
|
||||||
Bloom: big.NewInt(0),
|
Bloom: big.NewInt(0),
|
||||||
|
@ -197,12 +197,8 @@ func queryExportAccount(ctx sdk.Context, path []string, keeper Keeper) ([]byte,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
balanceInt := keeper.GetBalance(ctx, addr)
|
|
||||||
balance := sdk.NewIntFromBigInt(balanceInt)
|
|
||||||
|
|
||||||
res := types.GenesisAccount{
|
res := types.GenesisAccount{
|
||||||
Address: hexAddress,
|
Address: hexAddress,
|
||||||
Balance: balance,
|
|
||||||
Code: keeper.GetCode(ctx, addr),
|
Code: keeper.GetCode(ctx, addr),
|
||||||
Storage: storage,
|
Storage: storage,
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,9 @@ func (AppModule) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RegisterInvariants interface for registering invariants
|
// RegisterInvariants interface for registering invariants
|
||||||
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {}
|
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
|
||||||
|
keeper.RegisterInvariants(ir, am.keeper)
|
||||||
|
}
|
||||||
|
|
||||||
// Route specifies path for transactions
|
// Route specifies path for transactions
|
||||||
func (am AppModule) Route() string {
|
func (am AppModule) Route() string {
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
type AccountKeeper interface {
|
type AccountKeeper interface {
|
||||||
NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authexported.Account
|
NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authexported.Account
|
||||||
GetAllAccounts(ctx sdk.Context) (accounts []authexported.Account)
|
GetAllAccounts(ctx sdk.Context) (accounts []authexported.Account)
|
||||||
|
IterateAccounts(ctx sdk.Context, cb func(account authexported.Account) bool)
|
||||||
GetAccount(ctx sdk.Context, addr sdk.AccAddress) authexported.Account
|
GetAccount(ctx sdk.Context, addr sdk.AccAddress) authexported.Account
|
||||||
SetAccount(ctx sdk.Context, account authexported.Account)
|
SetAccount(ctx sdk.Context, account authexported.Account)
|
||||||
RemoveAccount(ctx sdk.Context, account authexported.Account)
|
RemoveAccount(ctx sdk.Context, account authexported.Account)
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
|
|
||||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
)
|
)
|
||||||
@ -22,9 +20,9 @@ type (
|
|||||||
// GenesisAccount defines an account to be initialized in the genesis state.
|
// GenesisAccount defines an account to be initialized in the genesis state.
|
||||||
// Its main difference between with Geth's GenesisAccount is that it uses a custom
|
// Its main difference between with Geth's GenesisAccount is that it uses a custom
|
||||||
// storage type and that it doesn't contain the private key field.
|
// storage type and that it doesn't contain the private key field.
|
||||||
|
// NOTE: balance is omitted as it is imported from the auth account balance.
|
||||||
GenesisAccount struct {
|
GenesisAccount struct {
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Balance sdk.Int `json:"balance"`
|
|
||||||
Code hexutil.Bytes `json:"code,omitempty"`
|
Code hexutil.Bytes `json:"code,omitempty"`
|
||||||
Storage Storage `json:"storage,omitempty"`
|
Storage Storage `json:"storage,omitempty"`
|
||||||
}
|
}
|
||||||
@ -35,12 +33,6 @@ func (ga GenesisAccount) Validate() error {
|
|||||||
if ga.Address == (ethcmn.Address{}.String()) {
|
if ga.Address == (ethcmn.Address{}.String()) {
|
||||||
return fmt.Errorf("address cannot be the zero address %s", ga.Address)
|
return fmt.Errorf("address cannot be the zero address %s", ga.Address)
|
||||||
}
|
}
|
||||||
if ga.Balance.IsNil() {
|
|
||||||
return errors.New("balance cannot be nil")
|
|
||||||
}
|
|
||||||
if ga.Balance.IsNegative() {
|
|
||||||
return errors.New("balance cannot be negative")
|
|
||||||
}
|
|
||||||
if ga.Code != nil && len(ga.Code) == 0 {
|
if ga.Code != nil && len(ga.Code) == 0 {
|
||||||
return errors.New("code bytes cannot be empty")
|
return errors.New("code bytes cannot be empty")
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,6 @@ import (
|
|||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
|
|
||||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,7 +24,6 @@ func TestValidateGenesisAccount(t *testing.T) {
|
|||||||
"valid genesis account",
|
"valid genesis account",
|
||||||
GenesisAccount{
|
GenesisAccount{
|
||||||
Address: address.String(),
|
Address: address.String(),
|
||||||
Balance: sdk.NewInt(1),
|
|
||||||
Code: []byte{1, 2, 3},
|
Code: []byte{1, 2, 3},
|
||||||
Storage: Storage{
|
Storage: Storage{
|
||||||
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
|
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
|
||||||
@ -38,23 +35,6 @@ func TestValidateGenesisAccount(t *testing.T) {
|
|||||||
"empty account address bytes",
|
"empty account address bytes",
|
||||||
GenesisAccount{
|
GenesisAccount{
|
||||||
Address: ethcmn.Address{}.String(),
|
Address: ethcmn.Address{}.String(),
|
||||||
Balance: sdk.NewInt(1),
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nil account balance",
|
|
||||||
GenesisAccount{
|
|
||||||
Address: address.String(),
|
|
||||||
Balance: sdk.Int{},
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nil account balance",
|
|
||||||
GenesisAccount{
|
|
||||||
Address: address.String(),
|
|
||||||
Balance: sdk.NewInt(-1),
|
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
@ -62,7 +42,6 @@ func TestValidateGenesisAccount(t *testing.T) {
|
|||||||
"empty code bytes",
|
"empty code bytes",
|
||||||
GenesisAccount{
|
GenesisAccount{
|
||||||
Address: address.String(),
|
Address: address.String(),
|
||||||
Balance: sdk.NewInt(1),
|
|
||||||
Code: []byte{},
|
Code: []byte{},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
@ -101,7 +80,6 @@ func TestValidateGenesis(t *testing.T) {
|
|||||||
Accounts: []GenesisAccount{
|
Accounts: []GenesisAccount{
|
||||||
{
|
{
|
||||||
Address: address.String(),
|
Address: address.String(),
|
||||||
Balance: sdk.NewInt(1),
|
|
||||||
Code: []byte{1, 2, 3},
|
Code: []byte{1, 2, 3},
|
||||||
Storage: Storage{
|
Storage: Storage{
|
||||||
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
|
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
|
||||||
@ -153,7 +131,6 @@ func TestValidateGenesis(t *testing.T) {
|
|||||||
Accounts: []GenesisAccount{
|
Accounts: []GenesisAccount{
|
||||||
{
|
{
|
||||||
Address: address.String(),
|
Address: address.String(),
|
||||||
Balance: sdk.NewInt(1),
|
|
||||||
Code: []byte{1, 2, 3},
|
Code: []byte{1, 2, 3},
|
||||||
Storage: Storage{
|
Storage: Storage{
|
||||||
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
|
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
|
||||||
@ -161,7 +138,6 @@ func TestValidateGenesis(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Address: address.String(),
|
Address: address.String(),
|
||||||
Balance: sdk.NewInt(1),
|
|
||||||
Code: []byte{1, 2, 3},
|
Code: []byte{1, 2, 3},
|
||||||
Storage: Storage{
|
Storage: Storage{
|
||||||
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
|
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
|
||||||
@ -177,7 +153,6 @@ func TestValidateGenesis(t *testing.T) {
|
|||||||
Accounts: []GenesisAccount{
|
Accounts: []GenesisAccount{
|
||||||
{
|
{
|
||||||
Address: address.String(),
|
Address: address.String(),
|
||||||
Balance: sdk.NewInt(1),
|
|
||||||
Code: []byte{1, 2, 3},
|
Code: []byte{1, 2, 3},
|
||||||
Storage: Storage{
|
Storage: Storage{
|
||||||
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
|
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
|
||||||
@ -227,7 +202,6 @@ func TestValidateGenesis(t *testing.T) {
|
|||||||
Accounts: []GenesisAccount{
|
Accounts: []GenesisAccount{
|
||||||
{
|
{
|
||||||
Address: address.String(),
|
Address: address.String(),
|
||||||
Balance: sdk.NewInt(1),
|
|
||||||
Code: []byte{1, 2, 3},
|
Code: []byte{1, 2, 3},
|
||||||
Storage: Storage{
|
Storage: Storage{
|
||||||
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
|
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
|
||||||
|
Loading…
Reference in New Issue
Block a user