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

multisig: add key exchange round booster #8203

Merged
merged 1 commit into from
Jul 16, 2024

Conversation

UkoeHB
Copy link
Contributor

@UkoeHB UkoeHB commented Mar 3, 2022

This PR adds a small optimization to multisig account creation that is especially useful for 2-of-3 groups (disclaimer: there is a bounty for it here).

Multisig account creation is a series of rounds. Each round consists of sending messages to all the other group members. A member cannot complete a round until they have received a message for that round from each other member.

A standard 2-of-3 setup ceremony looks like this:
Round 1: Members A, B, C send initial messages to all other members.
Round 2: Members A, B, C use the previous round's messages to make their personal shares of the final key. They send a second message to all other members.
Finalization: Once a member has a full set of round 2 messages, they can finish the account.

That setup ceremony requires 2 communication rounds. For 2-of-3 escrowed markets, the buyer party should instead be able to complete the ceremony in one step so they can fund the multisig wallet right away.

With boosting, we can instead have this setup ceremony:

  1. Members A, B send initial messages to each other and to member C.
  2. Members A, B create 'round 2 booster' messages and send them to member C.
  3. Member C completes round 1 immediately. He creates a round 1 and a round 2 message and sends them to members A, B. Member C then uses the booster messages to complete round 2, finalizing his local multisig account in the same step.
  4. Members A, B complete round 1 then make round 2 messages and send them to each other.
  5. Members A, B complete round 2 and finalize the multisig account.

So, by adding rounds to members A and B, member C can complete a 2-of-3 multisig account in one step.

DISCLAIMER: Kex boosting is expected to be used in conjunction with account force-updating. Extreme care must be taken when designing a system that uses these features to avoid attack vectors that lead to funds getting stuck or possibly stolen (I'd hesitate to use it at all until I or someone else does a write-up on how to do it safely).

TODO

  • Still need to update simplewallet (and the mms presumably @rbrunner7 ).
  • This PR is missing functional tests for the expanded wallet2 api (tests/functional_tests/multisig.py). It would be cool if someone who likes Python could help me with this.

Future Work

  • Try to refactor wallet2 so creating a multisig wallet doesn't involve converting an existing normal wallet's keys. Once a multisig wallet has been created, there should be no way to 'recreate' it using a different M/N configuration. Without that refactor, a user could boost a multisig account using one M/N configuration with a normal account (before converting their normal account to multisig), then later on when they actually convert to a multisig account use a different M/N configuration. If either of those M/N configs was an (N-1)-of-N, then the user will leak their multisig private key shares for that setup when setting up the other configuration (via the key exchange ceremony).

@UkoeHB
Copy link
Contributor Author

UkoeHB commented Mar 17, 2022

This PR should not be merged until after #8220.

@gs522084
Copy link

I'm not a programmer, I don't quite understand the logic of this solution, can you explain its benefits in detail? thanks。。。

@UkoeHB
Copy link
Contributor Author

UkoeHB commented Apr 17, 2022

@gs522084 the PR description is written for non-programmers. Not sure what else I can add to it.

@UkoeHB
Copy link
Contributor Author

UkoeHB commented May 15, 2022

This PR requires PR #8329.

Copy link
Contributor

@vtnerd vtnerd left a comment

Choose a reason for hiding this comment

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

I don't see one of the functions, so I'm wondering whether there is a missing file or something.

epee::misc_utils::auto_scope_leave_caller keys_reencryptor;
if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only)
{
crypto::chacha_key chacha_key;
crypto::generate_chacha_key(password.data(), password.size(), chacha_key, m_kdf_rounds);
m_account.encrypt_viewkey(chacha_key);
m_account.decrypt_keys(chacha_key);
decrypt_keys(password);
Copy link
Contributor

Choose a reason for hiding this comment

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

This line didn't have to change, and arguably shouldn't change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just trying to remove some code duplication while I'm here

src/wallet/wallet2.cpp Show resolved Hide resolved
src/wallet/wallet2.cpp Outdated Show resolved Hide resolved
src/multisig/multisig_account_kex_impl.cpp Outdated Show resolved Hide resolved
else
{
// make_multisig() has not been called
// DANGER: If 'num_signers - threshold > 1', but this wallet's future multisig settings
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be a hard error (exception)? Why allow it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case, the user passed in num_signers and threshold manually for a multisig account that doesn't exist yet (e.g. because you are missing one participant's initial kex message - this will happen when boosting round 2 of a 2-of-3 setup where you get the round 1 initial kex message of one participant and then boost round 2 for the other who isn't available). If the manually defined num_signers and threshold are different from the num_signers and threshold that the actual future multisig account gets, then there can be a problem (as described in the code comment).

Copy link
Contributor

@vtnerd vtnerd Oct 28, 2022

Choose a reason for hiding this comment

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

Yikes. Should the wallet track the values given in the booster request to ensure that they don't change in the future? Downstream projects can enforce this policy, but it seems doing it here if possible is best.

Copy link
Contributor Author

@UkoeHB UkoeHB Oct 28, 2022

Choose a reason for hiding this comment

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

The wallet should not couple multisig and normal wallet code, so that the first step of making a multisig wallet is defining M and N and those values are baked into the multisig core account file (even before initializing key exchange by defining the set of signers). But here we are...

In general, this boosting mechanism is very easy to use incorrectly since it only makes sense to use in combination with force updating the post-kex verification round (which is unsafe if used without nailing down the trust matrix/MPC theory of your use-case), so it should only be used by people who know what they are doing. Maybe we need some kind of gate for this 'enterprise-level' feature...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updating wallet2 to have safer multisig-wallet-creation semantics is out of scope for this PR. I will mark it as a 'todo potential future PR'.

@UkoeHB
Copy link
Contributor Author

UkoeHB commented Oct 19, 2022

Rebased, should be good to go now

@UkoeHB
Copy link
Contributor Author

UkoeHB commented Oct 19, 2022

Force-pushed again to update the unit test for boosting a multisig wallet so that the boosted wallet uses force-update to finish the post-kex round.

Comment on lines +5118 to +5611
// expect that self is in the input list (this guarantees that the input list size always equals the number of intended
// signers for the account [when combined with duplicate checking])
CHECK_AND_ASSERT_THROW_MES(std::find(signers.begin(), signers.end(), multisig_account.get_base_pubkey()) != signers.end(),
"The local account's signer key was not found in initial multisig kex messages when converting a wallet to multisig.");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a breaking change. In existing code, adding your own initial message to the make_multisig() command is optional.

Copy link
Contributor

@vtnerd vtnerd left a comment

Choose a reason for hiding this comment

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

The only thing holding me from approving this is whether the error tracking on the uninitialized account can be improved (without too much hassle).

src/wallet/wallet_rpc_server_commands_defs.h Show resolved Hide resolved
src/wallet/wallet2.cpp Show resolved Hide resolved
else
{
// make_multisig() has not been called
// DANGER: If 'num_signers - threshold > 1', but this wallet's future multisig settings
Copy link
Contributor

@vtnerd vtnerd Oct 28, 2022

Choose a reason for hiding this comment

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

Yikes. Should the wallet track the values given in the booster request to ensure that they don't change in the future? Downstream projects can enforce this policy, but it seems doing it here if possible is best.

@UkoeHB
Copy link
Contributor Author

UkoeHB commented May 16, 2023

Rebased so I can rebase the seraphis library onto this branch.

@selsta
Copy link
Collaborator

selsta commented May 21, 2024

@UkoeHB needs a rebase

@UkoeHB
Copy link
Contributor Author

UkoeHB commented May 21, 2024

Rebased

@luigi1111 luigi1111 merged commit 15b47b4 into monero-project:master Jul 16, 2024
18 checks passed
@UkoeHB UkoeHB deleted the multisig_addr_v2_boost branch August 2, 2024 18:21
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.

5 participants