Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: allow signerless account registration #16

Merged
merged 1 commit into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Allow accounts with a balance to be registered signerlessly. ([#17](https://github.com/noble-assets/forwarding/pull/17))
6 changes: 6 additions & 0 deletions proto/noble/forwarding/v1/account.proto
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,9 @@ message ForwardingAccount {
string recipient = 3;
int64 created_at = 4;
}

message ForwardingPubKey {
option (gogoproto.goproto_stringer) = false;

bytes key = 1;
}
53 changes: 53 additions & 0 deletions x/forwarding/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package forwarding
import (
cctptypes "github.com/circlefin/noble-cctp/x/cctp/types"
fiattokenfactorytypes "github.com/circlefin/noble-fiattokenfactory/x/fiattokenfactory/types"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/authz"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/noble-assets/forwarding/x/forwarding/keeper"
Expand Down Expand Up @@ -120,3 +124,52 @@ func (d Decorator) CheckMessages(ctx sdk.Context, msgs []sdk.Msg) error {

return nil
}

//

func SigVerificationGasConsumer(
meter storetypes.GasMeter, sig signing.SignatureV2, params authtypes.Params,
) error {
switch sig.PubKey.(type) {
case *types.ForwardingPubKey:
return nil
default:
return ante.DefaultSigVerificationGasConsumer(meter, sig, params)
}
}

//

type SigVerificationDecorator struct {
underlying ante.SigVerificationDecorator
bank types.BankKeeper
}

var _ sdk.AnteDecorator = SigVerificationDecorator{}

func NewSigVerificationDecorator(ak ante.AccountKeeper, bk types.BankKeeper, signModeHandler authsigning.SignModeHandler) SigVerificationDecorator {
return SigVerificationDecorator{
underlying: ante.NewSigVerificationDecorator(ak, signModeHandler),
bank: bk,
}
}

func (d SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if msgs := tx.GetMsgs(); len(msgs) == 1 {
msg, ok := msgs[0].(*types.MsgRegisterAccount)
if !ok {
return d.underlying.AnteHandle(ctx, tx, simulate, next)
}

address := types.GenerateAddress(msg.Channel, msg.Recipient)
balance := d.bank.GetAllBalances(ctx, address)

if balance.IsZero() || msg.Signer != address.String() {
return d.underlying.AnteHandle(ctx, tx, simulate, next)
}

return next(ctx, tx, simulate)
}

return d.underlying.AnteHandle(ctx, tx, simulate, next)
}
g-luca marked this conversation as resolved.
Show resolved Hide resolved
69 changes: 69 additions & 0 deletions x/forwarding/client/cli/tx.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package cli

import (
"fmt"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/noble-assets/forwarding/x/forwarding/types"
"github.com/spf13/cobra"
)
Expand All @@ -15,6 +18,7 @@ func GetTxCmd() *cobra.Command {
}

cmd.AddCommand(TxRegisterAccount())
cmd.AddCommand(TxRegisterAccountSignerlessly())
cmd.AddCommand(TxClearAccount())

return cmd
Expand Down Expand Up @@ -46,6 +50,71 @@ func TxRegisterAccount() *cobra.Command {
return cmd
}

func TxRegisterAccountSignerlessly() *cobra.Command {
cmd := &cobra.Command{
Use: "register-account-signerlessly [channel] [recipient]",
Short: "Signerlessly register a forwarding account for a channel and recipient",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

address := types.GenerateAddress(args[0], args[1])
msg := &types.MsgRegisterAccount{
Signer: address.String(),
Recipient: args[1],
Channel: args[0],
}
if err := msg.ValidateBasic(); err != nil {
return err
}

factory := tx.NewFactoryCLI(clientCtx, cmd.Flags())
builder, err := factory.BuildUnsignedTx(msg)
if err != nil {
return err
}

err = builder.SetSignatures(signingtypes.SignatureV2{
PubKey: &types.ForwardingPubKey{Key: address},
Data: &signingtypes.SingleSignatureData{
SignMode: signingtypes.SignMode_SIGN_MODE_DIRECT,
Signature: []byte(""),
},
})
if err != nil {
return err
}

if clientCtx.GenerateOnly {
bz, err := clientCtx.TxConfig.TxJSONEncoder()(builder.GetTx())
if err != nil {
return err
}

return clientCtx.PrintString(fmt.Sprintf("%s\n", bz))
}

bz, err := clientCtx.TxConfig.TxEncoder()(builder.GetTx())
if err != nil {
return err
}
res, err := clientCtx.BroadcastTx(bz)
if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}

func TxClearAccount() *cobra.Command {
cmd := &cobra.Command{
Use: "clear-account [address]",
Expand Down
4 changes: 3 additions & 1 deletion x/forwarding/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ func (k *Keeper) RegisterAccount(goCtx context.Context, msg *types.MsgRegisterAc
if k.authKeeper.HasAccount(ctx, address) {
rawAccount := k.authKeeper.GetAccount(ctx, address)
if rawAccount.GetPubKey() != nil || rawAccount.GetSequence() != 0 {
return nil, fmt.Errorf("attempting to register an existing user account with address: %s", address.String())
if !rawAccount.GetPubKey().Equals(&types.ForwardingPubKey{Key: address}) {
return nil, fmt.Errorf("attempting to register an existing user account with address: %s", address.String())
}
}

switch account := rawAccount.(type) {
Expand Down
28 changes: 28 additions & 0 deletions x/forwarding/types/account.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package types

import (
"bytes"
"fmt"

cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
Expand Down Expand Up @@ -30,3 +32,29 @@ func (fa *ForwardingAccount) Validate() error {

return fa.BaseAccount.Validate()
}

//

var _ cryptotypes.PubKey = &ForwardingPubKey{}

func (fpk *ForwardingPubKey) String() string {
return fmt.Sprintf("PubKeyForwarding{%X}", fpk.Key)
}

func (fpk *ForwardingPubKey) Address() cryptotypes.Address { return fpk.Key }

func (fpk *ForwardingPubKey) Bytes() []byte { return fpk.Key }

func (*ForwardingPubKey) VerifySignature(_ []byte, _ []byte) bool {
panic("PubKeyForwarding.VerifySignature should never be invoked")
}

func (fpk *ForwardingPubKey) Equals(other cryptotypes.PubKey) bool {
if _, ok := other.(*ForwardingPubKey); !ok {
return false
}

return bytes.Equal(fpk.Bytes(), other.Bytes())
}

func (*ForwardingPubKey) Type() string { return "forwarding" }
Loading