diff --git a/testutil/keeper/mocks/fungible/authority.go b/testutil/keeper/mocks/fungible/authority.go index cea0c0d145..b3ed6cae5a 100644 --- a/testutil/keeper/mocks/fungible/authority.go +++ b/testutil/keeper/mocks/fungible/authority.go @@ -4,7 +4,6 @@ package mocks import ( mock "github.com/stretchr/testify/mock" - authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" types "github.com/cosmos/cosmos-sdk/types" ) @@ -32,24 +31,6 @@ func (_m *FungibleAuthorityKeeper) CheckAuthorization(ctx types.Context, msg typ return r0 } -// IsAuthorized provides a mock function with given fields: ctx, address, policyType -func (_m *FungibleAuthorityKeeper) IsAuthorized(ctx types.Context, address string, policyType authoritytypes.PolicyType) bool { - ret := _m.Called(ctx, address, policyType) - - if len(ret) == 0 { - panic("no return value specified for IsAuthorized") - } - - var r0 bool - if rf, ok := ret.Get(0).(func(types.Context, string, authoritytypes.PolicyType) bool); ok { - r0 = rf(ctx, address, policyType) - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - // NewFungibleAuthorityKeeper creates a new instance of FungibleAuthorityKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewFungibleAuthorityKeeper(t interface { diff --git a/testutil/keeper/mocks/lightclient/authority.go b/testutil/keeper/mocks/lightclient/authority.go index 03dd6972de..3db36d6ce0 100644 --- a/testutil/keeper/mocks/lightclient/authority.go +++ b/testutil/keeper/mocks/lightclient/authority.go @@ -14,6 +14,24 @@ type LightclientAuthorityKeeper struct { mock.Mock } +// CheckAuthorization provides a mock function with given fields: ctx, msg +func (_m *LightclientAuthorityKeeper) CheckAuthorization(ctx types.Context, msg types.Msg) error { + ret := _m.Called(ctx, msg) + + if len(ret) == 0 { + panic("no return value specified for CheckAuthorization") + } + + var r0 error + if rf, ok := ret.Get(0).(func(types.Context, types.Msg) error); ok { + r0 = rf(ctx, msg) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // IsAuthorized provides a mock function with given fields: ctx, address, policyType func (_m *LightclientAuthorityKeeper) IsAuthorized(ctx types.Context, address string, policyType authoritytypes.PolicyType) bool { ret := _m.Called(ctx, address, policyType) diff --git a/testutil/keeper/mocks/observer/authority.go b/testutil/keeper/mocks/observer/authority.go index 5eaca6dbda..30a0d21b6d 100644 --- a/testutil/keeper/mocks/observer/authority.go +++ b/testutil/keeper/mocks/observer/authority.go @@ -32,24 +32,6 @@ func (_m *ObserverAuthorityKeeper) CheckAuthorization(ctx types.Context, msg typ return r0 } -// IsAuthorized provides a mock function with given fields: ctx, address, policyType -func (_m *ObserverAuthorityKeeper) IsAuthorized(ctx types.Context, address string, policyType authoritytypes.PolicyType) bool { - ret := _m.Called(ctx, address, policyType) - - if len(ret) == 0 { - panic("no return value specified for IsAuthorized") - } - - var r0 bool - if rf, ok := ret.Get(0).(func(types.Context, string, authoritytypes.PolicyType) bool); ok { - r0 = rf(ctx, address, policyType) - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - // SetPolicies provides a mock function with given fields: ctx, policies func (_m *ObserverAuthorityKeeper) SetPolicies(ctx types.Context, policies authoritytypes.Policies) { _m.Called(ctx, policies) diff --git a/x/authority/keeper/authorization_list.go b/x/authority/keeper/authorization_list.go index 6c3692138c..452848a386 100644 --- a/x/authority/keeper/authorization_list.go +++ b/x/authority/keeper/authorization_list.go @@ -30,20 +30,6 @@ func (k Keeper) GetAuthorizationList(ctx sdk.Context) (val types.AuthorizationLi return val, true } -// IsAuthorized checks if the address is authorized for the given policy type -func (k Keeper) IsAuthorized(ctx sdk.Context, address string, policyType types.PolicyType) bool { - policies, found := k.GetPolicies(ctx) - if !found { - return false - } - for _, policy := range policies.Items { - if policy.Address == address && policy.PolicyType == policyType { - return true - } - } - return false -} - // CheckAuthorization checks if the signer is authorized to sign the message func (k Keeper) CheckAuthorization(ctx sdk.Context, msg sdk.Msg) error { // Policy transactions must have only one signer diff --git a/x/authority/keeper/msg_server_update_chain_info.go b/x/authority/keeper/msg_server_update_chain_info.go index 11cd064c2a..5200e073e3 100644 --- a/x/authority/keeper/msg_server_update_chain_info.go +++ b/x/authority/keeper/msg_server_update_chain_info.go @@ -2,9 +2,8 @@ package keeper import ( "context" - "fmt" - cosmoserror "cosmossdk.io/errors" + "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/zeta-chain/zetacore/x/authority/types" @@ -21,10 +20,10 @@ func (k msgServer) UpdateChainInfo( // This message is only allowed to be called by group admin // Group admin because this functionality would rarely be called // and overwriting false chain info can have undesired effects - if !k.IsAuthorized(ctx, msg.Creator, types.PolicyType_groupAdmin) { - return nil, cosmoserror.Wrap(types.ErrUnauthorized, fmt.Sprintf("creator %s", msg.Creator)) + err := k.CheckAuthorization(ctx, msg) + if err != nil { + return nil, errors.Wrap(types.ErrUnauthorized, err.Error()) } - // set chain info k.SetChainInfo(ctx, msg.ChainInfo) diff --git a/x/authority/keeper/msg_server_update_chain_info_test.go b/x/authority/keeper/msg_server_update_chain_info_test.go index e9c5762940..d61be631a4 100644 --- a/x/authority/keeper/msg_server_update_chain_info_test.go +++ b/x/authority/keeper/msg_server_update_chain_info_test.go @@ -16,6 +16,7 @@ func TestMsgServer_UpdateChainInfo(t *testing.T) { t.Run("can't update chain info if not authorized", func(t *testing.T) { k, ctx := keepertest.AuthorityKeeper(t) msgServer := keeper.NewMsgServerImpl(*k) + k.SetAuthorizationList(ctx, types.DefaultAuthorizationsList()) _, err := msgServer.UpdateChainInfo(sdk.WrapSDKContext(ctx), &types.MsgUpdateChainInfo{ Creator: sample.AccAddress(), @@ -42,6 +43,8 @@ func TestMsgServer_UpdateChainInfo(t *testing.T) { }) chainInfo := sample.ChainInfo(42) + k.SetAuthorizationList(ctx, types.DefaultAuthorizationsList()) + _, err := msgServer.UpdateChainInfo(sdk.WrapSDKContext(ctx), &types.MsgUpdateChainInfo{ Creator: admin, ChainInfo: chainInfo, @@ -71,6 +74,7 @@ func TestMsgServer_UpdateChainInfo(t *testing.T) { }, }) chainInfo := sample.ChainInfo(84) + k.SetAuthorizationList(ctx, types.DefaultAuthorizationsList()) _, err := msgServer.UpdateChainInfo(sdk.WrapSDKContext(ctx), &types.MsgUpdateChainInfo{ Creator: admin, @@ -101,6 +105,7 @@ func TestMsgServer_UpdateChainInfo(t *testing.T) { }, }) chainInfo := types.ChainInfo{} + k.SetAuthorizationList(ctx, types.DefaultAuthorizationsList()) _, err := msgServer.UpdateChainInfo(sdk.WrapSDKContext(ctx), &types.MsgUpdateChainInfo{ Creator: admin, diff --git a/x/authority/keeper/policies_test.go b/x/authority/keeper/policies_test.go index 5e2347bd05..3cb7f486a6 100644 --- a/x/authority/keeper/policies_test.go +++ b/x/authority/keeper/policies_test.go @@ -7,7 +7,6 @@ import ( keepertest "github.com/zeta-chain/zetacore/testutil/keeper" "github.com/zeta-chain/zetacore/testutil/sample" - "github.com/zeta-chain/zetacore/x/authority/types" ) func TestKeeper_SetPolicies(t *testing.T) { @@ -32,28 +31,3 @@ func TestKeeper_SetPolicies(t *testing.T) { require.True(t, found) require.Equal(t, newPolicies, got) } - -func TestKeeper_IsAuthorized(t *testing.T) { - k, ctx := keepertest.AuthorityKeeper(t) - - // Not authorized if no policies - require.False(t, k.IsAuthorized(ctx, sample.AccAddress(), types.PolicyType_groupAdmin)) - require.False(t, k.IsAuthorized(ctx, sample.AccAddress(), types.PolicyType_groupEmergency)) - - policies := sample.Policies() - k.SetPolicies(ctx, policies) - - // Check policy is set - got, found := k.GetPolicies(ctx) - require.True(t, found) - require.Equal(t, policies, got) - - // Check policy is authorized - for _, policy := range policies.Items { - require.True(t, k.IsAuthorized(ctx, policy.Address, policy.PolicyType)) - } - - // Check policy is not authorized - require.False(t, k.IsAuthorized(ctx, sample.AccAddress(), types.PolicyType_groupAdmin)) - require.False(t, k.IsAuthorized(ctx, sample.AccAddress(), types.PolicyType_groupEmergency)) -} diff --git a/x/authority/types/authorizations.go b/x/authority/types/authorizations.go index 0de98a768e..79e292da3c 100644 --- a/x/authority/types/authorizations.go +++ b/x/authority/types/authorizations.go @@ -34,6 +34,7 @@ var ( "/zetachain.zetacore.fungible.MsgUpdateContractBytecode", "/zetachain.zetacore.fungible.MsgUpdateSystemContract", "/zetachain.zetacore.observer.MsgUpdateObserver", + "/zetachain.zetacore.authority.MsgUpdateChainInfo", } // EmergencyPolicyMessages keeps track of the message URLs that can, by default, only be executed by emergency policy address EmergencyPolicyMessages = []string{ diff --git a/x/authority/types/authorizations_test.go b/x/authority/types/authorizations_test.go index 8bb7ed805a..8413b09712 100644 --- a/x/authority/types/authorizations_test.go +++ b/x/authority/types/authorizations_test.go @@ -407,6 +407,7 @@ func TestDefaultAuthorizationsList(t *testing.T) { sdk.MsgTypeURL(&fungibletypes.MsgUpdateContractBytecode{}), sdk.MsgTypeURL(&fungibletypes.MsgUpdateSystemContract{}), sdk.MsgTypeURL(&observertypes.MsgUpdateObserver{}), + sdk.MsgTypeURL(&types.MsgUpdateChainInfo{}), } defaultList := types.DefaultAuthorizationsList() for _, msgUrl := range OperationalPolicyMessageList { diff --git a/x/fungible/types/expected_keepers.go b/x/fungible/types/expected_keepers.go index d81f26d537..b2997566ff 100644 --- a/x/fungible/types/expected_keepers.go +++ b/x/fungible/types/expected_keepers.go @@ -13,7 +13,6 @@ import ( evmtypes "github.com/evmos/ethermint/x/evm/types" "github.com/zeta-chain/zetacore/pkg/chains" - authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" ) // AccountKeeper defines the expected account keeper used for simulations (noalias) @@ -60,6 +59,5 @@ type EVMKeeper interface { } type AuthorityKeeper interface { - IsAuthorized(ctx sdk.Context, address string, policyType authoritytypes.PolicyType) bool CheckAuthorization(ctx sdk.Context, msg sdk.Msg) error } diff --git a/x/lightclient/keeper/msg_server_disable_block_header_verification._test.go b/x/lightclient/keeper/msg_server_disable_block_header_verification._test.go index bfb300a344..c3f9f9d52a 100644 --- a/x/lightclient/keeper/msg_server_disable_block_header_verification._test.go +++ b/x/lightclient/keeper/msg_server_disable_block_header_verification._test.go @@ -39,12 +39,14 @@ func TestMsgServer_DisableVerificationFlags(t *testing.T) { }) // enable eth type chain - keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupEmergency, true) - _, err := srv.DisableHeaderVerification(sdk.WrapSDKContext(ctx), &types.MsgDisableHeaderVerification{ + msg := types.MsgDisableHeaderVerification{ Creator: admin, ChainIdList: []int64{chains.Ethereum.ChainId, chains.BitcoinMainnet.ChainId}, - }) + } + keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + _, err := srv.DisableHeaderVerification(sdk.WrapSDKContext(ctx), &msg) require.NoError(t, err) + bhv, found := k.GetBlockHeaderVerification(ctx) require.True(t, found) require.False(t, bhv.IsChainEnabled(chains.Ethereum.ChainId)) @@ -75,11 +77,12 @@ func TestMsgServer_DisableVerificationFlags(t *testing.T) { }, }) - keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupEmergency, false) - _, err := srv.DisableHeaderVerification(sdk.WrapSDKContext(ctx), &types.MsgDisableHeaderVerification{ + msg := types.MsgDisableHeaderVerification{ Creator: admin, ChainIdList: []int64{chains.Ethereum.ChainId}, - }) + } + keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, authoritytypes.ErrUnauthorized) + _, err := srv.DisableHeaderVerification(sdk.WrapSDKContext(ctx), &msg) require.ErrorIs(t, err, authoritytypes.ErrUnauthorized) }) @@ -94,11 +97,12 @@ func TestMsgServer_DisableVerificationFlags(t *testing.T) { authorityMock := keepertest.GetLightclientAuthorityMock(t, k) // enable eth type chain - keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupEmergency, true) - _, err := srv.DisableHeaderVerification(sdk.WrapSDKContext(ctx), &types.MsgDisableHeaderVerification{ + msg := types.MsgDisableHeaderVerification{ Creator: admin, ChainIdList: []int64{chains.Ethereum.ChainId, chains.BitcoinMainnet.ChainId}, - }) + } + keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + _, err := srv.DisableHeaderVerification(sdk.WrapSDKContext(ctx), &msg) require.NoError(t, err) bhv, found := k.GetBlockHeaderVerification(ctx) require.True(t, found) diff --git a/x/lightclient/keeper/msg_server_disable_block_header_verification.go b/x/lightclient/keeper/msg_server_disable_block_header_verification.go index 023bc17515..c38bac327b 100644 --- a/x/lightclient/keeper/msg_server_disable_block_header_verification.go +++ b/x/lightclient/keeper/msg_server_disable_block_header_verification.go @@ -3,6 +3,7 @@ package keeper import ( "context" + cosmoserrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" @@ -18,8 +19,10 @@ func (k msgServer) DisableHeaderVerification( ctx := sdk.UnwrapSDKContext(goCtx) // check permission - if !k.GetAuthorityKeeper().IsAuthorized(ctx, msg.Creator, authoritytypes.PolicyType_groupEmergency) { - return nil, authoritytypes.ErrUnauthorized + + err := k.GetAuthorityKeeper().CheckAuthorization(ctx, msg) + if err != nil { + return nil, cosmoserrors.Wrap(authoritytypes.ErrUnauthorized, err.Error()) } bhv, found := k.GetBlockHeaderVerification(ctx) diff --git a/x/lightclient/keeper/msg_server_enable_block_header_verification.go b/x/lightclient/keeper/msg_server_enable_block_header_verification.go index 84b3ff3a69..0b0613c8e2 100644 --- a/x/lightclient/keeper/msg_server_enable_block_header_verification.go +++ b/x/lightclient/keeper/msg_server_enable_block_header_verification.go @@ -3,6 +3,7 @@ package keeper import ( "context" + cosmoserrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" @@ -18,8 +19,10 @@ func (k msgServer) EnableHeaderVerification(goCtx context.Context, msg *types.Ms ctx := sdk.UnwrapSDKContext(goCtx) // check permission - if !k.GetAuthorityKeeper().IsAuthorized(ctx, msg.Creator, authoritytypes.PolicyType_groupOperational) { - return nil, authoritytypes.ErrUnauthorized + + err := k.GetAuthorityKeeper().CheckAuthorization(ctx, msg) + if err != nil { + return nil, cosmoserrors.Wrap(authoritytypes.ErrUnauthorized, err.Error()) } bhv, found := k.GetBlockHeaderVerification(ctx) diff --git a/x/lightclient/keeper/msg_server_enable_block_header_verification_test.go b/x/lightclient/keeper/msg_server_enable_block_header_verification_test.go index 2025904b9a..96c5444123 100644 --- a/x/lightclient/keeper/msg_server_enable_block_header_verification_test.go +++ b/x/lightclient/keeper/msg_server_enable_block_header_verification_test.go @@ -39,11 +39,12 @@ func TestMsgServer_EnableVerificationFlags(t *testing.T) { }) // enable both eth and btc type chain together - keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) - _, err := srv.EnableHeaderVerification(sdk.WrapSDKContext(ctx), &types.MsgEnableHeaderVerification{ + msg := types.MsgEnableHeaderVerification{ Creator: admin, ChainIdList: []int64{chains.Ethereum.ChainId, chains.BitcoinMainnet.ChainId}, - }) + } + keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + _, err := srv.EnableHeaderVerification(sdk.WrapSDKContext(ctx), &msg) require.NoError(t, err) bhv, found := k.GetBlockHeaderVerification(ctx) require.True(t, found) @@ -62,11 +63,12 @@ func TestMsgServer_EnableVerificationFlags(t *testing.T) { authorityMock := keepertest.GetLightclientAuthorityMock(t, k) // enable both eth and btc type chain together - keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) - _, err := srv.EnableHeaderVerification(sdk.WrapSDKContext(ctx), &types.MsgEnableHeaderVerification{ + msg := types.MsgEnableHeaderVerification{ Creator: admin, ChainIdList: []int64{chains.Ethereum.ChainId, chains.BitcoinMainnet.ChainId}, - }) + } + keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, nil) + _, err := srv.EnableHeaderVerification(sdk.WrapSDKContext(ctx), &msg) require.NoError(t, err) bhv, found := k.GetBlockHeaderVerification(ctx) require.True(t, found) @@ -97,11 +99,12 @@ func TestMsgServer_EnableVerificationFlags(t *testing.T) { }, }) - keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, false) - _, err := srv.EnableHeaderVerification(sdk.WrapSDKContext(ctx), &types.MsgEnableHeaderVerification{ + msg := types.MsgEnableHeaderVerification{ Creator: admin, ChainIdList: []int64{chains.Ethereum.ChainId}, - }) + } + keepertest.MockCheckAuthorization(&authorityMock.Mock, &msg, authoritytypes.ErrUnauthorized) + _, err := srv.EnableHeaderVerification(sdk.WrapSDKContext(ctx), &msg) require.ErrorIs(t, err, authoritytypes.ErrUnauthorized) }) } diff --git a/x/lightclient/types/expected_keepers.go b/x/lightclient/types/expected_keepers.go index 57dec2bd11..bee335d628 100644 --- a/x/lightclient/types/expected_keepers.go +++ b/x/lightclient/types/expected_keepers.go @@ -2,10 +2,8 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" - - authoritytypes "github.com/zeta-chain/zetacore/x/authority/types" ) type AuthorityKeeper interface { - IsAuthorized(ctx sdk.Context, address string, policyType authoritytypes.PolicyType) bool + CheckAuthorization(ctx sdk.Context, msg sdk.Msg) error } diff --git a/x/observer/types/expected_keepers.go b/x/observer/types/expected_keepers.go index 28831537f0..5eb8b03468 100644 --- a/x/observer/types/expected_keepers.go +++ b/x/observer/types/expected_keepers.go @@ -32,7 +32,6 @@ type StakingHooks interface { } type AuthorityKeeper interface { - IsAuthorized(ctx sdk.Context, address string, policyType authoritytypes.PolicyType) bool CheckAuthorization(ctx sdk.Context, msg sdk.Msg) error // SetPolicies is solely used for the migration of policies from observer to authority