Skip to content

Commit

Permalink
[2137]: Update the ValidateUpdateValueOwners method and re-implement …
Browse files Browse the repository at this point in the history
…the UpdateValueOwners and MigrateValueOwner endpoints.
  • Loading branch information
SpicyLemon committed Sep 4, 2024
1 parent f690914 commit 28eda88
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 25 deletions.
38 changes: 34 additions & 4 deletions x/metadata/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"
"time"

"cosmossdk.io/collections"
sdkmath "cosmossdk.io/math"

"github.com/cosmos/cosmos-sdk/telemetry"
Expand Down Expand Up @@ -218,9 +219,12 @@ func (k msgServer) UpdateValueOwners(
defer telemetry.MeasureSince(time.Now(), types.ModuleName, "tx", "UpdateValueOwners")
ctx := UnwrapMetadataContext(goCtx)

// TODO[2137]: Identify the owners from the bank keeper.
links, err := k.GetScopeValueOwners(ctx, msg.ScopeIds)
if err != nil {
return nil, sdkerrors.ErrInvalidRequest.Wrap(err.Error())
}

err := k.ValidateUpdateValueOwners(ctx, nil, msg.ValueOwnerAddress, msg)
err = k.ValidateUpdateValueOwners(ctx, links, msg)
if err != nil {
return nil, sdkerrors.ErrInvalidRequest.Wrap(err.Error())
}
Expand All @@ -243,13 +247,39 @@ func (k msgServer) MigrateValueOwner(
ctx := UnwrapMetadataContext(goCtx)

// TODO[2137]: Identify the scopes from the bank keeper.
addr, err := sdk.AccAddressFromBech32(msg.Existing)
if err != nil {
return nil, sdkerrors.ErrInvalidRequest.Wrapf("invalid existing address %q: %w", msg.Existing, err)

Check failure on line 252 in x/metadata/keeper/msg_server.go

View workflow job for this annotation

GitHub Actions / golangci-lint

printf: (*cosmossdk.io/errors.Error).Wrapf does not support error-wrapping directive %w (govet)

Check failure on line 252 in x/metadata/keeper/msg_server.go

View workflow job for this annotation

GitHub Actions / tests (01)

(*cosmossdk.io/errors.Error).Wrapf does not support error-wrapping directive %w

Check failure on line 252 in x/metadata/keeper/msg_server.go

View workflow job for this annotation

GitHub Actions / test-race (01)

(*cosmossdk.io/errors.Error).Wrapf does not support error-wrapping directive %w
}
ranger := &collections.Range[collections.Pair[sdk.AccAddress, string]]{}
ranger.Prefix(collections.Join(addr, scopeDenomPrefix))
var links types.AccMDLinks
err = k.bankKeeper.GetBalancesCollection().Walk(ctx, ranger, func(key collections.Pair[sdk.AccAddress, string], _ sdkmath.Int) (bool, error) {
accAddr := key.K1()
// If this entry's addr does not equal the one we care about, something's horribly wrong.
if !addr.Equals(accAddr) {
return true, fmt.Errorf("address in iterator key %q does not equal the provided existing address %q", accAddr, msg.Existing)
}
denom := key.K2()
mdAddr, mdErr := types.MetadataAddressFromDenom(denom)
// This should be iterating only over scope denoms. If there's a bad one, log it, then keep going.
if mdErr != nil {
k.Logger(ctx).Error(fmt.Sprintf("invalid metadata denom %q (owned by %q): %v", denom, accAddr, mdErr))
return false, nil
}
links = append(links, types.NewAccMDLink(accAddr, mdAddr))
return false, nil
})
if err != nil {
return nil, sdkerrors.ErrLogic.Wrapf("error iterating scopes owned by %q: %w", addr, err)

Check failure on line 274 in x/metadata/keeper/msg_server.go

View workflow job for this annotation

GitHub Actions / golangci-lint

printf: (*cosmossdk.io/errors.Error).Wrapf does not support error-wrapping directive %w (govet)

Check failure on line 274 in x/metadata/keeper/msg_server.go

View workflow job for this annotation

GitHub Actions / tests (01)

(*cosmossdk.io/errors.Error).Wrapf does not support error-wrapping directive %w

Check failure on line 274 in x/metadata/keeper/msg_server.go

View workflow job for this annotation

GitHub Actions / test-race (01)

(*cosmossdk.io/errors.Error).Wrapf does not support error-wrapping directive %w
}

err := k.ValidateUpdateValueOwners(ctx, nil, msg.Proposed, msg)
err = k.ValidateUpdateValueOwners(ctx, links, msg)
if err != nil {
return nil, sdkerrors.ErrInvalidRequest.Wrap(err.Error())
}

err = k.SetScopeValueOwners(ctx, nil, msg.Proposed)
err = k.SetScopeValueOwners(ctx, links, msg.Proposed)
if err != nil {
return nil, fmt.Errorf("failure setting scope value owners: %w", err)
}
Expand Down
70 changes: 50 additions & 20 deletions x/metadata/keeper/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -749,38 +749,68 @@ func (k Keeper) ValidateUpdateScopeOwners(

func (k Keeper) ValidateUpdateValueOwners(
ctx sdk.Context,
scopes []*types.Scope,
newValueOwner string,
links types.AccMDLinks,
msg types.MetadataMsg,
) error {
var existingValueOwners []string
knownValueOwners := make(map[string]bool)
if len(links) == 0 {
return errors.New("no scopes found")
}
if err := links.ValidateForScopes(); err != nil {
return err
}

for _, scope := range scopes {
if len(scope.ValueOwnerAddress) == 0 {
return fmt.Errorf("scope %s does not yet have a value owner", scope.ScopeId)
}
if !knownValueOwners[scope.ValueOwnerAddress] {
existingValueOwners = append(existingValueOwners, scope.ValueOwnerAddress)
knownValueOwners[scope.ValueOwnerAddress] = true
}
signerStrs := msg.GetSignerStrs()
if len(signerStrs) == 0 {
return errors.New("no signers provided")
}

signers := NewSignersWrapper(msg.GetSignerStrs())
usedSigners, err := k.validateScopeValueOwnerChangeToProposed(ctx, newValueOwner, signers)
// If the first signer is a smart contract, ignore all other signers provided.
// This is different from the other metadata signers stuff because we don't have any permissions to check.
// We just need to make sure all existing value owners have signed (or given authority with authz).
// If it's a smart contract doing this, then all needed signers must have an authz grant for the given smart contract.
// It's probably not a good idea to authz grant a smart contract, but it's allowed.
var signerAccs []sdk.AccAddress
signer0, err := sdk.AccAddressFromBech32(signerStrs[0])
if err != nil {
return err
return fmt.Errorf("invalid signer address %q: %w", signerStrs[0], err)
}
if k.isWasmAccount(ctx, signer0) {
signerAccs = make([]sdk.AccAddress, 1)
if len(signerStrs) > 1 {
signerStrs = signerStrs[:1]
}
} else {
signerAccs = make([]sdk.AccAddress, len(signerStrs))
}
signerAccs[0] = signer0

for _, existing := range existingValueOwners {
alsoUsedSigners, err := k.validateScopeValueOwnerChangeFromExisting(ctx, existing, signers, msg)
signerAccMap := make(map[string]bool)
for i, signerStr := range signerStrs {
if len(signerAccs[i]) == 0 {
signerAccs[i], err = sdk.AccAddressFromBech32(signerStr)
if err != nil {
return fmt.Errorf("invalid signer[%d] address %q: %w", i, signerStr, err)
}
}
signerAccMap[string(signerAccs[i])] = true
}

reqSigners := links.GetAccAddrs()
for _, req := range reqSigners {
if signerAccMap[string(req)] {
continue
}

grantee, err := k.findAuthzGrantee(ctx, req, signerAccs, msg)
if err != nil {
return err
return fmt.Errorf("authz error with existing value owner %q: %w", req.String(), err)
}
if len(grantee) == 0 {
return fmt.Errorf("missing signature from existing value owner %q", req.String())
}
usedSigners.AlsoUse(alsoUsedSigners)
}

return k.validateSmartContractSigners(ctx, usedSigners, msg)
return nil
}

// AddSetNetAssetValues adds a set of net asset values to a scope
Expand Down
4 changes: 3 additions & 1 deletion x/metadata/keeper/scope_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2874,6 +2874,7 @@ func (s *ScopeKeeperTestSuite) TestScopeIndexing() {
}

func (s *ScopeKeeperTestSuite) TestValidateUpdateValueOwners() {
s.FailNow("This test needs to be revised.")
scopeID1 := types.ScopeMetadataAddress(uuid.New())
scopeID2 := types.ScopeMetadataAddress(uuid.New())
scopeID3 := types.ScopeMetadataAddress(uuid.New())
Expand Down Expand Up @@ -3077,7 +3078,8 @@ func (s *ScopeKeeperTestSuite) TestValidateUpdateValueOwners() {
mdKeeper.SetAuthzKeeper(origAuthzK)
}()

err := mdKeeper.ValidateUpdateValueOwners(s.FreshCtx(), tc.scopes, tc.newValueOwner, tc.msg)
// TODO[2137]: Call this correctly.
err := mdKeeper.ValidateUpdateValueOwners(s.FreshCtx(), nil, tc.msg)
s.AssertErrorValue(err, tc.expErr, "ValidateUpdateValueOwners")

getAccs := tc.authK.GetAccountCalls
Expand Down

0 comments on commit 28eda88

Please sign in to comment.