diff --git a/CHANGELOG.md b/CHANGELOG.md index 09d221600..65e1acd16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## v1.3.0 +This release introduces the Hulunbeier upgrade to the testnet. + +Features: +* [#542](https://github.com/bnb-chain/greenfield/pull/542) feat: add crosschain permission app +* [#534](https://github.com/bnb-chain/greenfield/pull/534) feat: implement Msgs for SP exit + +Bugfixes: +* [#552](https://github.com/bnb-chain/greenfield/pull/552) fix: resource account policy key collision + +Chore: +* [#551](https://github.com/bnb-chain/greenfield/pull/551) chore: fix typo and update doc + ## v1.2.2 This release introduces the Manchurian upgrade to the mainnet. diff --git a/app/upgrade.go b/app/upgrade.go index 92cbbcbb9..3b818308d 100644 --- a/app/upgrade.go +++ b/app/upgrade.go @@ -27,6 +27,7 @@ func (app *App) RegisterUpgradeHandlers(chainID string, serverCfg *serverconfig. app.registerPampasUpgradeHandler() app.registerManchurianUpgradeHandler() app.registerHulunbeierUpgradeHandler() + app.registerHulunbeierPatchUpgradeHandler() // app.register...() // ... @@ -161,3 +162,21 @@ func (app *App) registerHulunbeierUpgradeHandler() { return nil }) } + +func (app *App) registerHulunbeierPatchUpgradeHandler() { + // Register the upgrade handler + app.UpgradeKeeper.SetUpgradeHandler(upgradetypes.HulunbeierPatch, + func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + app.Logger().Info("upgrade to ", plan.Name) + + app.PermissionmoduleKeeper.MigrateAccountPolicyForResources(ctx) + return app.mm.RunMigrations(ctx, app.configurator, fromVM) + }) + + // Register the upgrade initializer + app.UpgradeKeeper.SetUpgradeInitializer(upgradetypes.HulunbeierPatch, + func() error { + app.Logger().Info("Init Hulunbeier patch upgrade") + return nil + }) +} diff --git a/deployment/localup/localup.sh b/deployment/localup/localup.sh index 7cfad3ed1..6ee1a6f91 100644 --- a/deployment/localup/localup.sh +++ b/deployment/localup/localup.sh @@ -175,6 +175,7 @@ function generate_genesis() { echo -e '[[upgrade]]\nname = "Pampas"\nheight = 20\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml echo -e '[[upgrade]]\nname = "Manchurian"\nheight = 20\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml echo -e '[[upgrade]]\nname = "Hulunbeier"\nheight = 21\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml + echo -e '[[upgrade]]\nname = "HulunbeierPatch"\nheight = 21\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml done # enable swagger API for validator0 diff --git a/go.mod b/go.mod index bed9cbb5b..6cffc703e 100644 --- a/go.mod +++ b/go.mod @@ -180,7 +180,7 @@ replace ( github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-cometbft v1.1.0 github.com/cometbft/cometbft-db => github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/bnb-chain/greenfield-cosmos-sdk v1.0.2-0.20231214052136-c20e9a5452b6 + github.com/cosmos/cosmos-sdk => github.com/bnb-chain/greenfield-cosmos-sdk v1.2.2-0.20240102032738-3661d43faf8f github.com/cosmos/iavl => github.com/bnb-chain/greenfield-iavl v0.20.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/wercker/journalhook => github.com/wercker/journalhook v0.0.0-20230927020745-64542ffa4117 diff --git a/go.sum b/go.sum index 4c0fde9f9..f5541dc50 100644 --- a/go.sum +++ b/go.sum @@ -163,8 +163,8 @@ github.com/bnb-chain/greenfield-cometbft v1.1.0 h1:jqnkDWIZW6f/rUn5/pE26YZMT9xzp github.com/bnb-chain/greenfield-cometbft v1.1.0/go.mod h1:NZ2/ZJK2HYe3++0CsPiw4LTG6UrC6pH7fQ3VOz6pqJw= github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1 h1:XcWulGacHVRiSCx90Q8Y//ajOrLNBQWR/KDB89dy3cU= github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1/go.mod h1:ey1CiK4bYo1RBNJLRiVbYr5CMdSxci9S/AZRINLtppI= -github.com/bnb-chain/greenfield-cosmos-sdk v1.0.2-0.20231214052136-c20e9a5452b6 h1:XO3cnv1E2vCSPfKw9467y3/8FL4r2XOI/h0C9NrFKTA= -github.com/bnb-chain/greenfield-cosmos-sdk v1.0.2-0.20231214052136-c20e9a5452b6/go.mod h1:Yrvq+J1Lsm7OHFX+M/AZWBTGt1TRHUTC4VYOMlvW3fs= +github.com/bnb-chain/greenfield-cosmos-sdk v1.2.2-0.20240102032738-3661d43faf8f h1:cU9Zsbmiy5NKDmaYU8kS8uZR0J1AyQrq5RR1EJgVO+k= +github.com/bnb-chain/greenfield-cosmos-sdk v1.2.2-0.20240102032738-3661d43faf8f/go.mod h1:Yrvq+J1Lsm7OHFX+M/AZWBTGt1TRHUTC4VYOMlvW3fs= github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20230816082903-b48770f5e210 h1:GHPbV2bC+gmuO6/sG0Tm8oGal3KKSRlyE+zPscDjlA8= github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20230816082903-b48770f5e210/go.mod h1:vhsZxXE9tYJeYB5JR4hPhd6Pc/uPf7j1T8IJ7p9FdeM= github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20230816082903-b48770f5e210 h1:FLVOn4+OVbsKi2+YJX5kmD27/4dRu4FW7xCXFhzDO5s= diff --git a/x/permission/keeper/keeper.go b/x/permission/keeper/keeper.go index 7dc41bbcc..ae44f970e 100644 --- a/x/permission/keeper/keeper.go +++ b/x/permission/keeper/keeper.go @@ -143,11 +143,10 @@ func (k Keeper) updatePolicy(ctx sdk.Context, policy, newPolicy *types.Policy) * func (k Keeper) PutPolicy(ctx sdk.Context, policy *types.Policy) (math.Uint, error) { store := ctx.KVStore(k.storeKey) - var newPolicy *types.Policy if policy.Principal.Type == types.PRINCIPAL_TYPE_GNFD_ACCOUNT { policyKey := types.GetPolicyForAccountKey(policy.ResourceId, policy.ResourceType, - policy.Principal.MustGetAccountAddress()) + policy.Principal.MustGetAccountAddress(), ctx.IsUpgraded(upgradetypes.HulunbeierPatch)) bz := store.Get(policyKey) if bz != nil { id := k.policySeq.DecodeSequence(bz) @@ -257,13 +256,11 @@ func (k Keeper) GetPolicyForAccount(ctx sdk.Context, resourceID math.Uint, isFound bool, ) { store := ctx.KVStore(k.storeKey) - policyKey := types.GetPolicyForAccountKey(resourceID, resourceType, addr) - + policyKey := types.GetPolicyForAccountKey(resourceID, resourceType, addr, ctx.IsUpgraded(upgradetypes.HulunbeierPatch)) bz := store.Get(policyKey) if bz == nil { return policy, false } - return k.GetPolicyByID(ctx, k.policySeq.DecodeSequence(bz)) } @@ -315,7 +312,7 @@ func (k Keeper) DeletePolicy(ctx sdk.Context, principal *types.Principal, resour accAddr := sdk.MustAccAddressFromHex(principal.Value) policy, found := k.GetPolicyForAccount(ctx, resourceID, resourceType, accAddr) if found { - store.Delete(types.GetPolicyForAccountKey(resourceID, resourceType, accAddr)) + store.Delete(types.GetPolicyForAccountKey(resourceID, resourceType, accAddr, ctx.IsUpgraded(upgradetypes.HulunbeierPatch))) store.Delete(types.GetPolicyByIDKey(policy.Id)) if policy.ExpirationTime != nil { store.Delete(types.PolicyPrefixQueue(policy.ExpirationTime, policy.Id.Bytes())) @@ -380,7 +377,7 @@ func (k Keeper) ForceDeleteAccountPolicyForResource(ctx sdk.Context, maxDelete, return deletedTotal, true } store := ctx.KVStore(k.storeKey) - resourceAccountsPolicyStore := prefix.NewStore(store, types.PolicyForAccountPrefix(resourceID, resourceType)) + resourceAccountsPolicyStore := prefix.NewStore(store, types.PolicyForAccountPrefix(resourceID, resourceType, ctx.IsUpgraded(upgradetypes.HulunbeierPatch))) iterator := resourceAccountsPolicyStore.Iterator(nil, nil) defer iterator.Close() isNagquUpgraded := ctx.IsUpgraded(upgradetypes.Nagqu) @@ -494,7 +491,7 @@ func (k Keeper) ExistAccountPolicyForResource(ctx sdk.Context, resourceType reso return false } store := ctx.KVStore(k.storeKey) - resourceAccountsPolicyStore := prefix.NewStore(store, types.PolicyForAccountPrefix(resourceID, resourceType)) + resourceAccountsPolicyStore := prefix.NewStore(store, types.PolicyForAccountPrefix(resourceID, resourceType, ctx.IsUpgraded(upgradetypes.HulunbeierPatch))) iterator := resourceAccountsPolicyStore.Iterator(nil, nil) defer iterator.Close() return iterator.Valid() @@ -545,7 +542,8 @@ func (k Keeper) RemoveExpiredPolicies(ctx sdk.Context) { if ctx.IsUpgraded(upgradetypes.Pampas) { if policy.Principal.Type == types.PRINCIPAL_TYPE_GNFD_ACCOUNT { policyKey := types.GetPolicyForAccountKey(policy.ResourceId, policy.ResourceType, - policy.Principal.MustGetAccountAddress()) + policy.Principal.MustGetAccountAddress(), + ctx.IsUpgraded(upgradetypes.HulunbeierPatch)) store.Delete(policyKey) } else if policy.Principal.Type == types.PRINCIPAL_TYPE_GNFD_GROUP { policyGroupKey := types.GetPolicyForGroupKey(policy.ResourceId, policy.ResourceType) @@ -570,3 +568,28 @@ func (k Keeper) RemoveExpiredPolicies(ctx sdk.Context) { } } } + +func (k Keeper) MigrateAccountPolicyForResources(ctx sdk.Context) { + store := ctx.KVStore(k.storeKey) + // PolicyForAccountKey: + // ResourcePolicyForAccountPrefix| ResourceID | AccountAddr + // iterator key: + // ResourceID | AccountAddr + migration := func(resourcePolicyForAccountPrefix []byte, resourceType resource.ResourceType) { + resourceAccountPolicyStore := prefix.NewStore(store, resourcePolicyForAccountPrefix) + iterator := resourceAccountPolicyStore.Iterator(nil, nil) + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + resourceAccountPolicyStore.Delete(iterator.Key()) + + // newKey might be the same as the previous one + resourceIDBz := iterator.Key()[:len(iterator.Key())-sdk.EthAddressLength] + addrBz := iterator.Key()[len(iterator.Key())-sdk.EthAddressLength:] + newKey := types.GetPolicyForAccountKey(math.ZeroUint().SetBytes(resourceIDBz), resourceType, addrBz, true) + store.Set(newKey, iterator.Value()) + } + } + migration(types.BucketPolicyForAccountPrefix, resource.RESOURCE_TYPE_BUCKET) + migration(types.ObjectPolicyForAccountPrefix, resource.RESOURCE_TYPE_OBJECT) + migration(types.GroupPolicyForAccountPrefix, resource.RESOURCE_TYPE_GROUP) +} diff --git a/x/permission/types/keys.go b/x/permission/types/keys.go index bb7e93b9f..ebd4058d3 100644 --- a/x/permission/types/keys.go +++ b/x/permission/types/keys.go @@ -47,7 +47,7 @@ var ( PolicyQueueKeyPrefix = []byte{0x51} ) -func PolicyForAccountPrefix(resourceID math.Uint, resourceType resource.ResourceType) []byte { +func PolicyForAccountPrefix(resourceID math.Uint, resourceType resource.ResourceType, useV2 bool) []byte { var key []byte switch resourceType { case resource.RESOURCE_TYPE_BUCKET: @@ -59,12 +59,17 @@ func PolicyForAccountPrefix(resourceID math.Uint, resourceType resource.Resource default: panic(fmt.Sprintf("GetPolicyForAccountKey Invalid Resource Type, %s", resourceType.String())) } - key = append(key, resourceID.Bytes()...) + if useV2 { + key = append(key, LengthPrefix(resourceID)...) + } else { + key = append(key, resourceID.Bytes()...) + } return key } -func GetPolicyForAccountKey(resourceID math.Uint, resourceType resource.ResourceType, addr sdk.AccAddress) []byte { - key := PolicyForAccountPrefix(resourceID, resourceType) +func GetPolicyForAccountKey(resourceID math.Uint, resourceType resource.ResourceType, addr sdk.AccAddress, useV2 bool) []byte { + var key []byte + key = PolicyForAccountPrefix(resourceID, resourceType, useV2) key = append(key, addr.Bytes()...) return key } diff --git a/x/permission/types/keys_test.go b/x/permission/types/keys_test.go index 8b12fcdf7..9530f2599 100644 --- a/x/permission/types/keys_test.go +++ b/x/permission/types/keys_test.go @@ -1,11 +1,16 @@ package types import ( + "encoding/hex" "math/rand" + "strings" "testing" "time" "cosmossdk.io/math" + "github.com/stretchr/testify/assert" + + "github.com/bnb-chain/greenfield/types/resource" ) func TestParsePolicyIdFromQueueKey(t *testing.T) { @@ -19,3 +24,18 @@ func TestParsePolicyIdFromQueueKey(t *testing.T) { } } } +func TestPrefixKeyCollision(t *testing.T) { + resourceID1 := math.NewUint(17) + resourceID2 := math.NewUint(4522) + + // collision, the prefix bytes of resourceID2 has included all prefix bytes generated by resourceID1 + assert.True(t, strings.Contains( + hex.EncodeToString(PolicyForAccountPrefix(resourceID2, resource.RESOURCE_TYPE_BUCKET, false)), + hex.EncodeToString(PolicyForAccountPrefix(resourceID1, resource.RESOURCE_TYPE_BUCKET, false)), + )) + + assert.False(t, strings.Contains( + hex.EncodeToString(PolicyForAccountPrefix(resourceID2, resource.RESOURCE_TYPE_BUCKET, true)), + hex.EncodeToString(PolicyForAccountPrefix(resourceID1, resource.RESOURCE_TYPE_BUCKET, true)), + )) +}