-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
fix: Prevent signing from wrong key in multisig #12446
Changes from all commits
5427e73
4d82385
f219b5e
fe4fca0
15eb5ce
b19f524
dcb2ff0
032d822
cbdf185
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -224,15 +224,14 @@ func makeSignCmd() func(cmd *cobra.Command, args []string) error { | |
return err | ||
} | ||
|
||
txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags()) | ||
txCfg := clientCtx.TxConfig | ||
txBuilder, err := txCfg.WrapTxBuilder(newTx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
printSignatureOnly, _ := cmd.Flags().GetBool(flagSigOnly) | ||
multisig, _ := cmd.Flags().GetString(flagMultisig) | ||
multisigkey, _ := cmd.Flags().GetString(flagMultisig) | ||
if err != nil { | ||
return err | ||
} | ||
|
@@ -243,15 +242,44 @@ func makeSignCmd() func(cmd *cobra.Command, args []string) error { | |
} | ||
|
||
overwrite, _ := f.GetBool(flagOverwrite) | ||
if multisig != "" { | ||
multisigAddr, err := sdk.AccAddressFromBech32(multisig) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems to me that this line got deleted. @likhita-809 is this intended? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, because at the line L251, we are getting both name and address of the multisig irrespective of multisig flag value(be it name or address). |
||
if multisigkey != "" { | ||
var ( | ||
multisigName string | ||
multisigAddr sdk.AccAddress | ||
) | ||
// Bech32 decode error, maybe it's a name, we try to fetch from keyring | ||
multisigAddr, multisigName, _, err = client.GetFromFields(clientCtx, txF.Keybase(), multisigkey) | ||
if err != nil { | ||
// Bech32 decode error, maybe it's a name, we try to fetch from keyring | ||
multisigAddr, _, _, err = client.GetFromFields(clientCtx, txFactory.Keybase(), multisig) | ||
if err != nil { | ||
return fmt.Errorf("error getting account from keybase: %w", err) | ||
return fmt.Errorf("error getting account from keybase: %w", err) | ||
} | ||
multisigRecord, err := clientCtx.Keyring.Key(multisigName) | ||
if err != nil { | ||
return err | ||
} | ||
multisigPub, err := multisigRecord.GetMultisigPubKey() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fromRecord, err := clientCtx.Keyring.Key(fromName) | ||
if err != nil { | ||
return err | ||
} | ||
fromPubKey, err := fromRecord.GetPubKey() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var found bool | ||
for _, pubkey := range multisigPub.GetPubKeys() { | ||
if pubkey.Equals(fromPubKey) { | ||
found = true | ||
} | ||
} | ||
if !found { | ||
return fmt.Errorf("from key is not a part of multisig key") | ||
} | ||
|
||
err = authclient.SignTxWithSignerAddress( | ||
txF, clientCtx, multisigAddr, fromName, txBuilder, clientCtx.Offline, overwrite) | ||
if err != nil { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,6 +74,10 @@ func (s *IntegrationTestSuite) SetupSuite() { | |
pub2, err := account2.GetPubKey() | ||
s.Require().NoError(err) | ||
|
||
// Create a dummy account for testing purpose | ||
_, _, err = kb.NewMnemonic("dummyAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) | ||
s.Require().NoError(err) | ||
|
||
multi := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{pub1, pub2}) | ||
_, err = kb.SaveMultisig("multi", multi) | ||
s.Require().NoError(err) | ||
|
@@ -938,6 +942,10 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() { | |
multisigRecord, err := val1.ClientCtx.Keyring.Key("multi") | ||
s.Require().NoError(err) | ||
|
||
// Generate dummy account which is not a part of multisig. | ||
dummyAcc, err := val1.ClientCtx.Keyring.Key("dummyAccount") | ||
s.Require().NoError(err) | ||
|
||
addr, err := multisigRecord.GetAddress() | ||
s.Require().NoError(err) | ||
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, addr) | ||
|
@@ -995,14 +1003,21 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() { | |
|
||
sign1File := testutil.WriteToNewTempFile(s.T(), account1Signature.String()) | ||
|
||
// Sign with account1 | ||
// Sign with account2 | ||
addr2, err := account2.GetAddress() | ||
s.Require().NoError(err) | ||
account2Signature, err := TxSignExec(val1.ClientCtx, addr2, multiGeneratedTxFile.Name(), "--multisig", addr.String()) | ||
s.Require().NoError(err) | ||
|
||
sign2File := testutil.WriteToNewTempFile(s.T(), account2Signature.String()) | ||
|
||
// Sign with dummy account | ||
dummyAddr, err := dummyAcc.GetAddress() | ||
s.Require().NoError(err) | ||
_, err = TxSignExec(val1.ClientCtx, dummyAddr, multiGeneratedTxFile.Name(), "--multisig", addr.String()) | ||
s.Require().Error(err) | ||
s.Require().Contains(err.Error(), "from key is not a part of multisig key") | ||
|
||
multiSigWith2Signatures, err := TxMultiSignExec(val1.ClientCtx, multisigRecord.Name, multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name()) | ||
s.Require().NoError(err) | ||
|
||
|
@@ -1057,7 +1072,7 @@ func (s *IntegrationTestSuite) TestSignWithMultisig() { | |
// as the main point of this test is to test the `--multisig` flag with an address | ||
// that is not in the keyring. | ||
_, err = TxSignExec(val1.ClientCtx, addr1, multiGeneratedTx2File.Name(), "--multisig", multisigAddr.String()) | ||
s.Require().Contains(err.Error(), "tx intended signer does not match the given signer") | ||
s.Require().Contains(err.Error(), "error getting account from keybase") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fact that we changed this test seems a bit suspicious to me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this test, we are passing multisig flag value as its address. |
||
} | ||
|
||
func (s *IntegrationTestSuite) TestCLIMultisign() { | ||
|
@@ -1124,7 +1139,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() { | |
|
||
addr2, err := account2.GetAddress() | ||
s.Require().NoError(err) | ||
// Sign with account1 | ||
// Sign with account2 | ||
account2Signature, err := TxSignExec(val1.ClientCtx, addr2, multiGeneratedTxFile.Name(), "--multisig", addr.String()) | ||
s.Require().NoError(err) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is a good API on Record: there should only be a method to get the PubKey.
Then, in tx_sign.go, we can cast
.GetPubKey().(*multisig.LegacyAminoPubKey)