Skip to content

Approve multisig proposals with any local signer, Add keystone support#563

Merged
n13 merged 6 commits into
mainfrom
fix/562-multisig-multi-signer-approve
Jul 14, 2026
Merged

Approve multisig proposals with any local signer, Add keystone support#563
n13 merged 6 commits into
mainfrom
fix/562-multisig-multi-signer-approve

Conversation

@n13

@n13 n13 commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Fixes #562: when multiple local accounts are signers of the same multisig, the app only tracked myMemberAccountId, so after that account signed there was no way for another local co-signer to approve.
  • Approval eligibility now considers all local accounts that are multisig members.
  • If more than one eligible local signer remains, tapping Approve opens a picker listing only accounts that have not already signed (or have a pending approval).
  • Keystone hardware signers no longer hit Mnemonic not found for signing — multisig approve/execute/cancel detect Keystone accounts and use the shared QR sign → scan signature → external submit path (same pattern as transfers).

Changes

  • Multi-local-signer helpers + unit tests
  • Signer picker sheet + EN/ID l10n
  • Proposal detail / approve confirm / activity row updates
  • Generic KeystoneExtrinsicSession + sign/scan screens
  • Hardware submit methods for multisig approve/execute/cancel

Test plan

  • Add 2 accounts on one device and create a 2-of-2 (or 2-of-N) multisig with both as signers
  • Create a proposal; first account auto-approves as proposer (or approve as account 1)
  • Open the proposal while account 1 has already signed — Approve remains available
  • With only one remaining unsigned local software signer, Approve goes straight to confirm and signs as that account
  • With two unsigned local signers, Approve shows the picker and excludes accounts that already signed
  • With a Keystone co-signer selected: confirm → Keystone QR screen → scan signature QR → approval submitted / pending state shown
  • Execute / cancel with a Keystone member also uses the QR flow
  • After all local signers have approved, button shows Already Signed / Done as before
  • Single-local-signer software multisigs still behave as before (no picker)

n13 added 4 commits July 11, 2026 19:27
When multiple local accounts are members of the same multisig, the
approve UX previously keyed only off myMemberAccountId. After that
account signed, co-signers on the same device had no path to approve.

Detect all local signers, keep Approve available until every local
member has signed, and show an account picker when more than one
unsigned local signer remains.

Closes #562
Multisig approve/execute/cancel assumed a local mnemonic. When the
selected signer is a Keystone account, hand off to a shared extrinsic
QR sign + scan path (same pattern as transfers) and submit with the
external signature.

Adds KeystoneExtrinsicSession plus generic sign/scan screens, and
hardware submit methods on TransactionSubmissionService.
@n13

n13 commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author
photo_2026-07-11 20 11 45 photo_2026-07-11 20 11 42 photo_2026-07-11 20 11 34 hardware signing

Comment thread mobile-app/lib/services/transaction_submission_service.dart
return signer;
}

bool _isHardwareSigner(Account signer) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we already have the extension for checking if account is hardware wallet or high security or other type of account, so we don't need to create new function everytime

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a small utility method for debugging, it's ok

Comment thread mobile-app/lib/v2/screens/multisig/multisig_action_confirm_sheet.dart Outdated
Comment thread mobile-app/lib/v2/screens/multisig/multisig_activity_section.dart
children: [
Text(
account.name,
style: text.smallParagraph?.copyWith(color: colors.textPrimary, fontWeight: FontWeight.w600),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

property color is unnecessary since we use textPrimary by default.

final frame = (size.width - 96).clamp(220.0, 300.0);
final progress = _expectedParts == null ? null : (_seenSeq.length / _expectedParts!).clamp(0.0, 1.0);

return Scaffold(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember we already have this keystone scan like screen, can't we refactor it to be reusable instead of creating totally new screen?

@n13 n13 Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty bad.

Fixed.

Comment thread mobile-app/lib/v2/screens/send/keystone_sign_extrinsic_screen.dart Outdated
Comment thread mobile-app/lib/v2/screens/send/keystone_sign_extrinsic_screen.dart Outdated

@dewabisma dewabisma left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, does it mean when we have multiple eligible signers, we have to sign twice in the app now?

Some changes needed.

@n13 n13 changed the title fix: allow approving multisig proposals with any local signer Approve multisig proposals with any local signer, Add keystone support Jul 13, 2026
@n13

n13 commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

On the multiple eligible signers question: no, one tap on Approve does not make the user sign twice. The picker only chooses which eligible local account performs this approval, and that submits one signature. If the device owns another multisig member and the threshold still needs its approval, the user can deliberately approve again as that second account in a separate action. This PR makes that second local approval possible; it does not combine or automatically request both signatures.

n13 added 2 commits July 13, 2026 17:07
general architecture improvement, renamed widgets so they make more sense
@n13

n13 commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Fixed two DRY violations, please review again, commented on other comments

Tested the full hardware flow again, both send and msig approve

@dewabisma

Copy link
Copy Markdown
Collaborator

On the multiple eligible signers question: no, one tap on Approve does not make the user sign twice. The picker only chooses which eligible local account performs this approval, and that submits one signature. If the device owns another multisig member and the threshold still needs its approval, the user can deliberately approve again as that second account in a separate action. This PR makes that second local approval possible; it does not combine or automatically request both signatures.

I see, it means, we have to really deliberate even if the signers are both in the mobile app.

if (session.primaryDetail != null)
Text(
session.primaryDetail!,
style: text.smallTitle?.copyWith(color: colors.textPrimary),

@dewabisma dewabisma Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary color override.

style: text.detail?.copyWith(
color: colors.textMuted,
fontFamily: AppTextTheme.fontFamilySecondary,
fontSize: 12,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary fontSize override

@dewabisma dewabisma left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking great! Just few nits.

@n13

n13 commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Co0l.. I do not think default overrides are an error, they're a feature (maybe we don't wanna rely on "default" and not be boxed in with all the other items who are using default, if any)

@n13 n13 merged commit 034d876 into main Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multisig issue: Handle the situation when multiple signers are present in the app

2 participants