Repository: cosmos/cosmos-sdk (Go)

Issue:
x/auth/types: CountSubKeys inexplicably returns 1 when the public key isn't of type multisig.PubKeyMultisigThreshold yet naturally counts otherwise
The code in question is
https://github.com/cosmos/cosmos-sdk/blob/72ebafeecadba67a39d3ebe1df8a24d85409ea18/x/auth/types/stdtx.go#L128-L140

Why does it return the magic number 1 if pub is not of the required yet, yet in the positive case is actually recursively counts subkeys. I don't see a test to affirm this behavior and could perhaps return random behavior. If this logic is intended, at least let's document it. 

____

## For Admin Use

- [ ] Not duplicate issue
- [ ] Appropriate labels applied
- [ ] Appropriate contributors tagged
- [ ] Contributor assigned/self-assigned

ante CountSubKeys should return 0
<!-- < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < ☺ 
v                            ✰  Thanks for opening an issue! ✰    
v    Before smashing the submit button please review the template.
v    Please also ensure that this is not a duplicate issue :)  
☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >  -->

<!--
IMPORTANT: Prior to opening a bug report, check if it affects one of the core modules
and if its elegible for a bug bounty on `SECURITY.md`. Bugs that are not submitted
through the appropriate channels won't receive any bounty.
 -->

## Summary of Bug

When calling `ante.CountSubKeys` with a nil Pubkey a total of 0 subkeys should be expected, instead it returns 1.
[https://github.com/cosmos/cosmos-sdk/blob/94b0bdcc5cef18aa153396eec3e78ccffaba06db/x/auth/ante/sigverify.go#L462-L475](https://github.com/cosmos/cosmos-sdk/blob/94b0bdcc5cef18aa153396eec3e78ccffaba06db/x/auth/ante/sigverify.go#L462-L475)

## Proposal
Check if Pubkey is nil
```go
func CountSubKeys(pub cryptotypes.PubKey) int {
	if pub == nil {
		return 0
	}
	v, ok := pub.(*kmultisig.LegacyAminoPubKey)
```



Discussion:
A non-multisig, i.e. a regular signature, it naturally a count of 1. If it is a multisig, then it recursively calls it on its pubkeys. The number one isn't magic here.
Is this just missing a test @odeke-em ? The logic looks correct to me.
It could use a comment as to why that 1, and a test of sorts indeed would
be nice but just the comment that Aleksander explaining that logic would
suffice for me.

On Thu, Jul 30, 2020 at 7:34 AM Aaron Craelius <notifications@github.com>
wrote:

> Is this just missing a test @odeke-em <https://github.com/odeke-em> ? The
> logic looks correct to me.
>
> —
> You are receiving this because you were mentioned.
>
>
> Reply to this email directly, view it on GitHub
> <https://github.com/cosmos/cosmos-sdk/issues/6889#issuecomment-666404516>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ABFL3V3T6L6JDLKDNZRKBZDR6GAJBANCNFSM4PMYTG7Q>
> .
>

Is recursive function lingo, returning `1` is the base-case -- i.e. when a key has no sub-keys. If tests are lacking, we should certainly add more tests/cases!
@odeke-em can we close this one? there are some test cases for this in here
https://github.com/cosmos/cosmos-sdk/blob/main/x/auth/ante/ante_test.go#L1281-L1313





Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0f8aeb8d502c..59fccaa8f99d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -271,6 +271,7 @@ extension interfaces. `module.Manager.Modules` is now of type `map[string]interf
 
 ### Bug Fixes
 
+* (x/auth) [#15059](https://github.com/cosmos/cosmos-sdk/pull/15059) `ante.CountSubKeys` returns 0 when passing a nil `Pubkey`.
 * (x/capability) [#15030](https://github.com/cosmos/cosmos-sdk/pull/15030) Fixed bug where `x/capability` consumed `GasMeter` gas during `InitMemStore`.
 * [#14995](https://github.com/cosmos/cosmos-sdk/pull/14995) Allow unknown fields in `ParseTypedEvent`.
 * [#14952](https://github.com/cosmos/cosmos-sdk/pull/14952) Pin version of github.com/syndtr/goleveldb `v1.0.1-0.20210819022825-2ae1ddf74ef7` to avoid issues in the store.
diff --git a/x/auth/ante/sigverify.go b/x/auth/ante/sigverify.go
index 977a9284d89e..6eb29b2fc4e9 100644
--- a/x/auth/ante/sigverify.go
+++ b/x/auth/ante/sigverify.go
@@ -461,7 +461,12 @@ func GetSignerAcc(ctx sdk.Context, ak AccountKeeper, addr sdk.AccAddress) (sdk.A
 }
 
 // CountSubKeys counts the total number of keys for a multi-sig public key.
+// A non-multisig, i.e. a regular signature, it naturally a count of 1. If it is a multisig,
+// then it recursively calls it on its pubkeys.
 func CountSubKeys(pub cryptotypes.PubKey) int {
+	if pub == nil {
+		return 0
+	}
 	v, ok := pub.(*kmultisig.LegacyAminoPubKey)
 	if !ok {
 		return 1


Test patch:
diff --git a/x/auth/ante/ante_test.go b/x/auth/ante/ante_test.go
index 1fa833c66dbb..79d485f25eed 100644
--- a/x/auth/ante/ante_test.go
+++ b/x/auth/ante/ante_test.go
@@ -1307,6 +1307,7 @@ func TestCountSubkeys(t *testing.T) {
 		{"single key", args{singleKey}, 1},
 		{"single level multikey", args{singleLevelMultiKey}, 5},
 		{"multi level multikey", args{multiLevelMultiKey}, 11},
+		{"nil key", args{nil}, 0},
 	}
 	for _, tc := range testCases {
 		t.Run(tc.name, func(T *testing.T) {