Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: handle multi signatures #277

Merged
merged 6 commits into from
Mar 12, 2024
Merged
Changes from 1 commit
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
104 changes: 60 additions & 44 deletions x/smartaccount/ante/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,16 @@ func (sad SmartAccountAuthDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
return ctx, err
}

// Current smartaccount only supports one signer (TODO review in the future)
// Current smartaccount only supports one signer
// Multiple signers here means that the transaction perform state changes on multiple wallets
emidev98 marked this conversation as resolved.
Show resolved Hide resolved
// (Not the same as a multi-sig transaction)
if len(signers) != 1 {
return ctx, sdkerrors.ErrorInvalidSigner.Wrap("only one account is supported (sigTx.GetSigners()!= 1)")
}

// Sender here is the account that signed the transaction
// Could be different from the account above (confusingly named signer)
senderAddr, signaturesBs, signedBytes, err := sad.GetParamsForCustomAuthVerification(ctx, sigTx, account)
senderAddrs, signaturesBs, signedBytes, err := sad.GetParamsForCustomAuthVerification(ctx, sigTx, account)
if err != nil {
return ctx, err
}
Expand All @@ -101,7 +103,7 @@ func (sad SmartAccountAuthDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
success, err := sad.CustomAuthVerify(
ctx,
setting.Authorization,
[]string{senderAddr.String()},
senderAddrs,
accountStr,
signaturesBs,
signedBytes,
Expand Down Expand Up @@ -132,8 +134,8 @@ func (sad SmartAccountAuthDecorator) GetParamsForCustomAuthVerification(
sigTx authsigning.SigVerifiableTx,
account sdk.AccAddress,
) (
senderAddr sdk.AccAddress,
signatureBz [][]byte,
senderAddrs []string,
signatureBzs [][]byte,
signedBytes [][]byte,
err error,
) {
Expand All @@ -143,46 +145,52 @@ func (sad SmartAccountAuthDecorator) GetParamsForCustomAuthVerification(
}
if len(signatures) == 0 {
return nil, nil, nil, sdkerrors.ErrNoSignatures.Wrap("no signatures found")
} else if len(signatures) > 1 {
// TODO: remove when support multi sig auth
return nil, nil, nil, sdkerrors.ErrUnauthorized.Wrap("multiple signatures not supported")
}

signature := signatures[0]
signaturesBs := [][]byte{}
for _, signature := range signatures {
// This is to get the list of signers that contributed to the signatures
sas, err := GetSignerAddrStrings(signature.PubKey)
if err != nil {
return nil, nil, nil, err
}
senderAddrs = append(senderAddrs, sas...)

senderAddr, err = sdk.AccAddressFromHexUnsafe(signature.PubKey.Address().String())
if err != nil {
return nil, nil, nil, err
}
// This is to get the address of the signer (either a multisig or a single sig)
// For multisig, the address to generated from the json encoded list of signers
// See: cosmos-sdk: crypto/keys/multisig/multisig.go
javiersuweijie marked this conversation as resolved.
Show resolved Hide resolved
senderAddr, err := sdk.AccAddressFromHexUnsafe(signature.PubKey.Address().String())
if err != nil {
return nil, nil, nil, err
}

senderAcc, err := authante.GetSignerAcc(ctx, sad.accountKeeper, senderAddr)
if err != nil {
return nil, nil, nil, err
}
var senderAccNum uint64
if ctx.BlockHeight() != 0 {
senderAccNum = senderAcc.GetAccountNumber()
}
senderAcc, err := authante.GetSignerAcc(ctx, sad.accountKeeper, senderAddr)
if err != nil {
return nil, nil, nil, err
}
var senderAccNum uint64
if ctx.BlockHeight() != 0 {
senderAccNum = senderAcc.GetAccountNumber()
}

signerData := authsigning.SignerData{
Address: senderAddr.String(),
ChainID: ctx.ChainID(),
AccountNumber: senderAccNum,
Sequence: senderAcc.GetSequence(),
PubKey: signature.PubKey,
}
signerData := authsigning.SignerData{
Address: senderAddr.String(),
ChainID: ctx.ChainID(),
AccountNumber: senderAccNum,
Sequence: senderAcc.GetSequence(),
PubKey: signature.PubKey,
}

signatureBz, err = signatureDataToBz(signature.Data)
if err != nil {
return nil, nil, nil, err
}
signedBytes, err = GetSignBytesArr(signature.PubKey, signerData, signature.Data, sad.signModeHandler, sigTx)
if err != nil {
return nil, nil, nil, err
signatureBz, err := signatureDataToBz(signature.Data)
if err != nil {
return nil, nil, nil, err
}
signedBytes, err = GetSignBytesArr(signature.PubKey, signerData, signature.Data, sad.signModeHandler, sigTx)
if err != nil {
return nil, nil, nil, err
}
signatureBzs = append(signatureBzs, signatureBz...)
}
signaturesBs = append(signaturesBs, signatureBz...)
return senderAddr, signaturesBs, signedBytes, nil
return senderAddrs, signatureBzs, signedBytes, nil
}

func (sad SmartAccountAuthDecorator) CustomAuthVerify(
Expand Down Expand Up @@ -269,12 +277,6 @@ func GetSignBytesArr(pubKey cryptotypes.PubKey, signerData authsigning.SignerDat
if err != nil {
return nil, err
}
// TODO: should this be removed?
// this works right now because its secp256k1
// if verification is done only in wasm, then this probably would not work
// if !pubKey.VerifySignature(signBytes, data.Signature) {
// return nil, fmt.Errorf("unable to verify single signer signature")
// }
return [][]byte{signBytes}, nil

case *signing.MultiSignatureData:
Expand All @@ -288,6 +290,20 @@ func GetSignBytesArr(pubKey cryptotypes.PubKey, signerData authsigning.SignerDat
}
}

func GetSignerAddrStrings(pubKey cryptotypes.PubKey) ([]string, error) {
switch pubKey := pubKey.(type) {
case multisig.PubKey:
pubKeys := pubKey.GetPubKeys()
addrStrings := make([]string, len(pubKeys))
for i, pk := range pubKeys {
addrStrings[i] = pk.Address().String()
}
return addrStrings, nil
default:
return []string{pubKey.Address().String()}, nil
}
}

func GetMultiSigSignBytes(multiPK multisig.PubKey, sig *signing.MultiSignatureData, signerData authsigning.SignerData, handler authsigning.SignModeHandler, tx sdk.Tx) (signersBytes [][]byte, err error) {
bitarray := sig.BitArray
sigs := sig.Signatures
Expand Down
Loading