diff --git a/app/app.go b/app/app.go index 7552389175..66c4c4222d 100644 --- a/app/app.go +++ b/app/app.go @@ -1,6 +1,8 @@ package app import ( + "crypto/sha256" + "encoding/hex" stderrors "errors" "fmt" "io" @@ -9,6 +11,7 @@ import ( "net/http" "os" "path/filepath" + "sort" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" @@ -175,6 +178,8 @@ const ( // // NOTE: In the SDK, the default value is 255. AddrLen = 20 + + FlagBlockedAddresses = "blocked-addresses" ) var Forks = []Fork{} @@ -918,6 +923,7 @@ func New( app.SetEndBlocker(app.EndBlocker) if err := app.setAnteHandler(encodingConfig.TxConfig, cast.ToUint64(appOpts.Get(srvflags.EVMMaxTxGasWanted)), + cast.ToStringSlice(appOpts.Get(FlagBlockedAddresses)), ); err != nil { panic(err) } @@ -965,7 +971,35 @@ func New( } // use Ethermint's custom AnteHandler -func (app *App) setAnteHandler(txConfig client.TxConfig, maxGasWanted uint64) error { +func (app *App) setAnteHandler(txConfig client.TxConfig, maxGasWanted uint64, blacklist []string) error { + if len(blacklist) > 0 { + sort.Strings(blacklist) + // hash blacklist concatenated + h := sha256.New() + for _, addr := range blacklist { + _, err := h.Write([]byte(addr)) + if err != nil { + panic(err) + } + } + app.Logger().Error("Setting ante handler with blacklist", "size", len(blacklist), "hash", hex.EncodeToString(h.Sum(nil))) + for _, addr := range blacklist { + app.Logger().Error("Blacklisted address", "address", addr) + } + } else { + app.Logger().Error("Setting ante handler without blacklist") + } + blockedMap := make(map[string]struct{}, len(blacklist)) + for _, str := range blacklist { + addr, err := sdk.AccAddressFromBech32(str) + if err != nil { + return fmt.Errorf("invalid bech32 address: %s, err: %w", str, err) + } + + blockedMap[string(addr)] = struct{}{} + } + blockAddressDecorator := NewBlockAddressesDecorator(blockedMap) + options := evmante.HandlerOptions{ AccountKeeper: app.AccountKeeper, BankKeeper: app.BankKeeper, @@ -982,6 +1016,7 @@ func (app *App) setAnteHandler(txConfig client.TxConfig, maxGasWanted uint64) er sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}), sdk.MsgTypeURL(&vestingtypes.MsgCreateVestingAccount{}), }, + ExtraDecorators: []sdk.AnteDecorator{blockAddressDecorator}, } anteHandler, err := evmante.NewAnteHandler(options) diff --git a/app/block_address.go b/app/block_address.go new file mode 100644 index 0000000000..11cb1cfa68 --- /dev/null +++ b/app/block_address.go @@ -0,0 +1,31 @@ +package app + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// BlockAddressesDecorator block addresses from sending transactions +type BlockAddressesDecorator struct { + blockedMap map[string]struct{} +} + +func NewBlockAddressesDecorator(blacklist map[string]struct{}) BlockAddressesDecorator { + return BlockAddressesDecorator{ + blockedMap: blacklist, + } +} + +func (bad BlockAddressesDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { + if ctx.IsCheckTx() { + for _, msg := range tx.GetMsgs() { + for _, signer := range msg.GetSigners() { + if _, ok := bad.blockedMap[string(signer)]; ok { + return ctx, fmt.Errorf("signer is blocked: %s", signer.String()) + } + } + } + } + return next(ctx, tx, simulate) +} diff --git a/integration_tests/configs/long_timeout_commit.jsonnet b/integration_tests/configs/long_timeout_commit.jsonnet index 2036a74ee6..2dfe559653 100644 --- a/integration_tests/configs/long_timeout_commit.jsonnet +++ b/integration_tests/configs/long_timeout_commit.jsonnet @@ -7,5 +7,8 @@ default { timeout_commit: '15s', }, }, + 'app-config'+: { + 'blocked-addresses': ['crc16z0herz998946wr659lr84c8c556da55dc34hh'], + }, }, } diff --git a/integration_tests/test_mempool.py b/integration_tests/test_mempool.py index 80d54ba8f5..b565edf1a0 100644 --- a/integration_tests/test_mempool.py +++ b/integration_tests/test_mempool.py @@ -76,3 +76,10 @@ def test_mempool(cronos_mempool): break wait_for_new_blocks(cli, 1, sleep=0.1) assert len(sended_hash_set) == 0 + + +def test_blocked_address(cronos_mempool): + cli = cronos_mempool.cosmos_cli(0) + rsp = cli.transfer("signer1", cli.address("validator"), "1basecro") + assert rsp["code"] != 0 + assert "signer is blocked" in rsp["raw_log"]