Skip to content

Commit b97d36b

Browse files
committed
feat: receive pubkey for signature verification
1 parent 258836b commit b97d36b

File tree

13 files changed

+778
-459
lines changed

13 files changed

+778
-459
lines changed

api/v1/tx.pulsar.go

Lines changed: 467 additions & 281 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

keeper/keeper.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ import (
1818
"context"
1919
"fmt"
2020

21+
"cosmossdk.io/core/address"
2122
"cosmossdk.io/core/store"
23+
"github.com/cosmos/cosmos-sdk/codec"
2224
sdk "github.com/cosmos/cosmos-sdk/types"
2325
"github.com/monerium/module-noble/v2/types"
2426
"github.com/monerium/module-noble/v2/types/blacklist"
@@ -28,22 +30,25 @@ type Keeper struct {
2830
authority string
2931
storeService store.KVStoreService
3032

31-
accountKeeper types.AccountKeeper
32-
bankKeeper types.BankKeeper
33+
cdc codec.Codec
34+
addressCodec address.Codec
35+
bankKeeper types.BankKeeper
3336
}
3437

3538
func NewKeeper(
3639
authority string,
3740
storeService store.KVStoreService,
38-
accountKeeper types.AccountKeeper,
41+
cdc codec.Codec,
42+
addressCodec address.Codec,
3943
bankKeeper types.BankKeeper,
4044
) *Keeper {
4145
return &Keeper{
4246
authority: authority,
4347
storeService: storeService,
4448

45-
accountKeeper: accountKeeper,
46-
bankKeeper: bankKeeper,
49+
cdc: cdc,
50+
addressCodec: addressCodec,
51+
bankKeeper: bankKeeper,
4752
}
4853
}
4954

keeper/msg_server.go

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
package keeper
1616

1717
import (
18+
"bytes"
1819
"context"
1920
"fmt"
2021

2122
"adr36.dev"
2223
"cosmossdk.io/errors"
24+
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
2325
sdk "github.com/cosmos/cosmos-sdk/types"
2426
"github.com/monerium/module-noble/v2/types"
2527
)
@@ -128,23 +130,28 @@ func (k msgServer) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBu
128130
return nil, types.ErrInvalidSystem
129131
}
130132

131-
address := sdk.MustAccAddressFromBech32(msg.From)
132-
account := k.accountKeeper.GetAccount(ctx, address)
133-
if account == nil || account.GetPubKey() == nil {
134-
return nil, types.ErrNoPubKey
133+
var pubKey cryptotypes.PubKey
134+
if err := k.cdc.UnpackAny(msg.PubKey, &pubKey); err != nil {
135+
return nil, errors.Wrap(err, "unable to unpack pubkey")
136+
}
137+
from, err := k.addressCodec.StringToBytes(msg.From)
138+
if err != nil {
139+
return nil, errors.Wrapf(err, "unable to decode user address %s", msg.From)
140+
}
141+
if !bytes.Equal(from, pubKey.Address()) {
142+
return nil, types.ErrInvalidPubKey
135143
}
136144

137145
if !adr36.VerifySignature(
138-
account.GetPubKey(),
146+
pubKey,
139147
[]byte("I hereby declare that I am the address owner."),
140148
msg.Signature,
141149
) {
142150
return nil, types.ErrInvalidSignature
143151
}
144152

145153
coins := sdk.NewCoins(sdk.NewCoin(msg.Denom, msg.Amount))
146-
from := sdk.MustAccAddressFromBech32(msg.From)
147-
err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, from, types.ModuleName, coins)
154+
err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, from, types.ModuleName, coins)
148155
if err != nil {
149156
return nil, errors.Wrap(err, "unable to transfer from user to module")
150157
}
@@ -175,8 +182,11 @@ func (k msgServer) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMi
175182
k.Keeper.SetMintAllowance(ctx, msg.Denom, msg.Signer, allowance)
176183

177184
coins := sdk.NewCoins(sdk.NewCoin(msg.Denom, msg.Amount))
178-
to := sdk.MustAccAddressFromBech32(msg.To)
179-
err := k.bankKeeper.MintCoins(ctx, types.ModuleName, coins)
185+
to, err := k.addressCodec.StringToBytes(msg.To)
186+
if err != nil {
187+
return nil, errors.Wrapf(err, "unable to decode user address %s", msg.To)
188+
}
189+
err = k.bankKeeper.MintCoins(ctx, types.ModuleName, coins)
180190
if err != nil {
181191
return nil, errors.Wrap(err, "unable to mint to module")
182192
}
@@ -202,14 +212,20 @@ func (k msgServer) Recover(goCtx context.Context, msg *types.MsgRecover) (*types
202212
return nil, types.ErrInvalidSystem
203213
}
204214

205-
from := sdk.MustAccAddressFromBech32(msg.From)
206-
account := k.accountKeeper.GetAccount(ctx, from)
207-
if account == nil || account.GetPubKey() == nil {
208-
return nil, types.ErrNoPubKey
215+
var pubKey cryptotypes.PubKey
216+
if err := k.cdc.UnpackAny(msg.PubKey, &pubKey); err != nil {
217+
return nil, errors.Wrap(err, "unable to unpack pubkey")
218+
}
219+
from, err := k.addressCodec.StringToBytes(msg.From)
220+
if err != nil {
221+
return nil, errors.Wrapf(err, "unable to decode user address %s", msg.From)
222+
}
223+
if !bytes.Equal(from, pubKey.Address()) {
224+
return nil, types.ErrInvalidPubKey
209225
}
210226

211227
if !adr36.VerifySignature(
212-
account.GetPubKey(),
228+
pubKey,
213229
[]byte("I hereby declare that I am the address owner."),
214230
msg.Signature,
215231
) {
@@ -221,8 +237,11 @@ func (k msgServer) Recover(goCtx context.Context, msg *types.MsgRecover) (*types
221237
return &types.MsgRecoverResponse{}, nil
222238
}
223239

224-
to := sdk.MustAccAddressFromBech32(msg.To)
225-
err := k.bankKeeper.SendCoins(ctx, from, to, sdk.NewCoins(balance))
240+
to, err := k.addressCodec.StringToBytes(msg.To)
241+
if err != nil {
242+
return nil, errors.Wrapf(err, "unable to decode user address %s", msg.To)
243+
}
244+
err = k.bankKeeper.SendCoins(ctx, from, to, sdk.NewCoins(balance))
226245
if err != nil {
227246
return nil, errors.Wrap(err, "unable to transfer from user to user")
228247
}

keeper/msg_server_test.go

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
2323
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
2424
sdk "github.com/cosmos/cosmos-sdk/types"
25-
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
2625
"github.com/monerium/module-noble/v2/keeper"
2726
"github.com/monerium/module-noble/v2/types"
2827
"github.com/monerium/module-noble/v2/utils"
@@ -229,14 +228,11 @@ func TestBurn(t *testing.T) {
229228
bz, _ := base64.StdEncoding.DecodeString("AlE8CxHR19ID5lxrVtTxSgJFlK3T+eYtyDM/vBA3Fowr")
230229
pubkey, _ := codectypes.NewAnyWithValue(&secp256k1.PubKey{Key: bz})
231230

232-
account := mocks.AccountKeeper{
233-
Accounts: make(map[string]sdk.AccountI),
234-
}
235231
bank := mocks.BankKeeper{
236232
Balances: make(map[string]sdk.Coins),
237233
Restriction: mocks.NoOpSendRestrictionFn,
238234
}
239-
k, ctx := mocks.FlorinWithKeepers(account, bank)
235+
k, ctx := mocks.FlorinWithKeepers(bank)
240236
goCtx := sdk.WrapSDKContext(ctx)
241237
server := keeper.NewMsgServer(k)
242238

@@ -257,34 +253,36 @@ func TestBurn(t *testing.T) {
257253
// ASSERT: The action should've failed due to invalid signer.
258254
require.ErrorIs(t, err, types.ErrInvalidSystem)
259255

260-
// ACT: Attempt to burn with no account in state.
256+
// ACT: Attempt to burn with invalid any.
257+
invalidPubKey, _ := codectypes.NewAnyWithValue(&types.MsgBurn{})
261258
_, err = server.Burn(goCtx, &types.MsgBurn{
262259
Denom: "ueure",
263260
Signer: system.Address,
264-
From: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
261+
PubKey: invalidPubKey,
265262
})
266-
// ASSERT: The action should've failed due to no account.
267-
require.ErrorIs(t, err, types.ErrNoPubKey)
263+
// ASSERT: The action should've failed due to invalid any.
264+
require.ErrorContains(t, err, "unable to unpack pubkey")
268265

269-
// ARRANGE: Set account in state, without pubkey.
270-
account.Accounts["noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2"] = &authtypes.BaseAccount{}
266+
// ACT: Attempt to burn with invalid user address.
267+
_, err = server.Burn(goCtx, &types.MsgBurn{
268+
Denom: "ueure",
269+
Signer: system.Address,
270+
From: utils.TestAccount().Invalid,
271+
PubKey: pubkey,
272+
})
273+
// ASSERT: The action should've failed due to invalid user address.
274+
require.ErrorContains(t, err, "unable to decode user address")
271275

272-
// ACT: Attempt to burn with no pubkey in state.
276+
// ACT: Attempt to burn with invalid public key.
277+
invalidPubKey, _ = codectypes.NewAnyWithValue(secp256k1.GenPrivKey().PubKey())
273278
_, err = server.Burn(goCtx, &types.MsgBurn{
274279
Denom: "ueure",
275280
Signer: system.Address,
276281
From: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
282+
PubKey: invalidPubKey,
277283
})
278-
// ASSERT: The action should've failed due to no pubkey.
279-
require.ErrorIs(t, err, types.ErrNoPubKey)
280-
281-
// ARRANGE: Set pubkey in state.
282-
account.Accounts["noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2"] = &authtypes.BaseAccount{
283-
Address: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
284-
PubKey: pubkey,
285-
AccountNumber: 0,
286-
Sequence: 0,
287-
}
284+
// ASSERT: The action should've failed due to invalid public key.
285+
require.ErrorIs(t, err, types.ErrInvalidPubKey)
288286

289287
// ACT: Attempt to burn with invalid signature.
290288
signature, _ := base64.StdEncoding.DecodeString("QBrRfIqjdBvXx9zaBcuiE9P5SVesxFO/He3deyx2OE0NoSNqwmSb7b5iP2UhZRI1duiOeho3+NETUkCBv14zjQ==")
@@ -293,6 +291,7 @@ func TestBurn(t *testing.T) {
293291
Signer: system.Address,
294292
From: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
295293
Signature: signature,
294+
PubKey: pubkey,
296295
})
297296
// ASSERT: The action should've failed due to invalid signature.
298297
require.ErrorIs(t, err, types.ErrInvalidSignature)
@@ -305,6 +304,7 @@ func TestBurn(t *testing.T) {
305304
From: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
306305
Amount: One,
307306
Signature: signature,
307+
PubKey: pubkey,
308308
})
309309
// ASSERT: The action should've failed due to insufficient balance.
310310
require.ErrorContains(t, err, "unable to transfer from user to module")
@@ -319,6 +319,7 @@ func TestBurn(t *testing.T) {
319319
From: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
320320
Amount: One,
321321
Signature: signature,
322+
PubKey: pubkey,
322323
})
323324
// ASSERT: The action should've succeeded.
324325
require.NoError(t, err)
@@ -330,7 +331,7 @@ func TestMint(t *testing.T) {
330331
Balances: make(map[string]sdk.Coins),
331332
Restriction: mocks.NoOpSendRestrictionFn,
332333
}
333-
k, ctx := mocks.FlorinWithKeepers(mocks.AccountKeeper{}, bank)
334+
k, ctx := mocks.FlorinWithKeepers(bank)
334335
goCtx := sdk.WrapSDKContext(ctx)
335336
server := keeper.NewMsgServer(k)
336337

@@ -375,6 +376,16 @@ func TestMint(t *testing.T) {
375376
// ARRANGE: Generate a user account.
376377
user := utils.TestAccount()
377378

379+
// ACT: Attempt to mint with invalid user address.
380+
_, err = server.Mint(goCtx, &types.MsgMint{
381+
Denom: "ueure",
382+
Signer: system.Address,
383+
To: user.Invalid,
384+
Amount: math.ZeroInt(),
385+
})
386+
// ASSERT: The action should've failed due to invalid user address.
387+
require.ErrorContains(t, err, "unable to decode user address")
388+
378389
// ACT: Attempt to mint.
379390
_, err = server.Mint(goCtx, &types.MsgMint{
380391
Denom: "ueure",
@@ -406,14 +417,11 @@ func TestRecover(t *testing.T) {
406417
bz, _ := base64.StdEncoding.DecodeString("AlE8CxHR19ID5lxrVtTxSgJFlK3T+eYtyDM/vBA3Fowr")
407418
pubkey, _ := codectypes.NewAnyWithValue(&secp256k1.PubKey{Key: bz})
408419

409-
account := mocks.AccountKeeper{
410-
Accounts: make(map[string]sdk.AccountI),
411-
}
412420
bank := mocks.BankKeeper{
413421
Balances: make(map[string]sdk.Coins),
414422
Restriction: mocks.NoOpSendRestrictionFn,
415423
}
416-
k, ctx := mocks.FlorinWithKeepers(account, bank)
424+
k, ctx := mocks.FlorinWithKeepers(bank)
417425
goCtx := sdk.WrapSDKContext(ctx)
418426
server := keeper.NewMsgServer(k)
419427

@@ -434,34 +442,36 @@ func TestRecover(t *testing.T) {
434442
// ASSERT: The action should've failed due to invalid signer.
435443
require.ErrorIs(t, err, types.ErrInvalidSystem)
436444

437-
// ACT: Attempt to recover with no account in state.
445+
// ACT: Attempt to recover with invalid any.
446+
invalidPubKey, _ := codectypes.NewAnyWithValue(&types.MsgRecover{})
438447
_, err = server.Recover(goCtx, &types.MsgRecover{
439448
Denom: "ueure",
440449
Signer: system.Address,
441-
From: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
450+
PubKey: invalidPubKey,
442451
})
443-
// ASSERT: The action should've failed due to no account.
444-
require.ErrorIs(t, err, types.ErrNoPubKey)
452+
// ASSERT: The action should've failed due to invalid any.
453+
require.ErrorContains(t, err, "unable to unpack pubkey")
445454

446-
// ARRANGE: Set account in state, without pubkey.
447-
account.Accounts["noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2"] = &authtypes.BaseAccount{}
455+
// ACT: Attempt to recover with invalid user address.
456+
_, err = server.Recover(goCtx, &types.MsgRecover{
457+
Denom: "ueure",
458+
Signer: system.Address,
459+
From: utils.TestAccount().Invalid,
460+
PubKey: pubkey,
461+
})
462+
// ASSERT: The action should've failed due to invalid user address.
463+
require.ErrorContains(t, err, "unable to decode user address")
448464

449-
// ACT: Attempt to recover with no pubkey in state.
465+
// ACT: Attempt to recover with invalid public key.
466+
invalidPubKey, _ = codectypes.NewAnyWithValue(secp256k1.GenPrivKey().PubKey())
450467
_, err = server.Recover(goCtx, &types.MsgRecover{
451468
Denom: "ueure",
452469
Signer: system.Address,
453470
From: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
471+
PubKey: invalidPubKey,
454472
})
455-
// ASSERT: The action should've failed due to no pubkey.
456-
require.ErrorIs(t, err, types.ErrNoPubKey)
457-
458-
// ARRANGE: Set pubkey in state.
459-
account.Accounts["noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2"] = &authtypes.BaseAccount{
460-
Address: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
461-
PubKey: pubkey,
462-
AccountNumber: 0,
463-
Sequence: 0,
464-
}
473+
// ASSERT: The action should've failed due to invalid public key.
474+
require.ErrorIs(t, err, types.ErrInvalidPubKey)
465475

466476
// ACT: Attempt to recover with invalid signature.
467477
signature, _ := base64.StdEncoding.DecodeString("QBrRfIqjdBvXx9zaBcuiE9P5SVesxFO/He3deyx2OE0NoSNqwmSb7b5iP2UhZRI1duiOeho3+NETUkCBv14zjQ==")
@@ -470,6 +480,7 @@ func TestRecover(t *testing.T) {
470480
Signer: system.Address,
471481
From: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
472482
Signature: signature,
483+
PubKey: pubkey,
473484
})
474485
// ASSERT: The action should've failed due to invalid signature.
475486
require.ErrorIs(t, err, types.ErrInvalidSignature)
@@ -485,20 +496,34 @@ func TestRecover(t *testing.T) {
485496
From: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
486497
To: recipient.Address,
487498
Signature: signature,
499+
PubKey: pubkey,
488500
})
489501
// ASSERT: The action should've succeeded.
490502
require.NoError(t, err)
491503

492504
// ARRANGE: Give user 1 $EURe.
493505
bank.Balances["noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2"] = sdk.NewCoins(sdk.NewCoin("ueure", One))
494506

507+
// ACT: Attempt to recover with invalid user address.
508+
_, err = server.Recover(goCtx, &types.MsgRecover{
509+
Denom: "ueure",
510+
Signer: system.Address,
511+
From: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
512+
To: recipient.Invalid,
513+
Signature: signature,
514+
PubKey: pubkey,
515+
})
516+
// ASSERT: The action should've failed due to invalid user address.
517+
require.ErrorContains(t, err, "unable to decode user address")
518+
495519
// ACT: Attempt to recover.
496520
_, err = server.Recover(goCtx, &types.MsgRecover{
497521
Denom: "ueure",
498522
Signer: system.Address,
499523
From: "noble1rwvjzk28l38js7xx6mq23nrpghd8qqvxmj6ep2",
500524
To: recipient.Address,
501525
Signature: signature,
526+
PubKey: pubkey,
502527
})
503528
// ASSERT: The action should've succeeded.
504529
require.NoError(t, err)

0 commit comments

Comments
 (0)