Repository navigation
Add multisig propose approve for a multisig that signs another multisig - #189
exocognosis wants to merge 2 commits into
Conversation
A multisig has no key, so when it is a signer of another multisig it cannot call approve. Its vote is Multisig::approve dispatched from its own account when one of its proposals executes. propose custom cannot build that call, so recovering such a setup meant hand-encoding it. propose approve checks that the proposer signs the member multisig, that the member signs the target, and that the target proposal exists, is live and is not already approved by the member. It fetches the target proposal's stored call to bind the approval, and caps the default expiry at the target proposal's expiry. Refs Quantus-Network/quantus-apps#708
|
Ran it end to end on a local dev chain (quantus-node v1.0.2-Qm, spec 153), same shape as the incident:
Refusals, all before submitting: member not a signer of target, proposal already executed, proposer not a signer of the member. Not covered live: the high-security refusal and the expiry warning. |
|
With #13 in, the follow-through set from the October incident is complete on my side: #708 tracks it, #715 is the creation guard, #189 here is the recovery path, and #13 closes the import gap underneath them. I do this kind of work as scoped engagements. If the wallet and CLI security follow-through is worth scoping as a two-week piece on your side, I am happy to walk through it on a short call. Is there a better channel than issue threads for that, email or Discord? |
Recovery half of Quantus-Network/quantus-apps#708.
A multisig has no key, so as a signer of another multisig it cannot call approve. Its vote is Multisig::approve(target, proposal_id, call) dispatched with the member multisig as origin when one of the member's proposals executes. approve takes the target proposal's stored call, so the approval is bound to it.
propose custom cannot build that call (build_runtime_call only encodes Balances transfers and System remark), so recovering this setup meant hand-encoding call bytes.
quantus multisig propose approve --address --target --proposal-id --from
Weight: approve(MaxCallSize) is about 23e9 ref time and 17 KB proof against MaxInnerCallWeight of 1e12 and 2.6 MB, so it passes the propose weight check. A high-security member multisig cannot propose it (HS whitelist; propose burns the fee on rejection), so the command refuses that case before submitting.
Tests: the call decodes back to Multisig::approve with the target, id and stored bytes, and uses the metadata's pallet and call indices. cargo test and clippy pass.
README: new section under the multisig commands.
Ran end to end against a local dev node (v1.0.2-Qm); results in the comment below. High-security refusal and the expiry warning not exercised live.
Side note: README still documents quantus multisig dissolve and a deposit "returned on dissolution". There is no dissolve call in the pallet or the bindings. Left alone here.