From b565917bbfab0aaaf8ffeb54b2cbea23a5b6813d Mon Sep 17 00:00:00 2001 From: valdok Date: Tue, 16 Dec 2025 23:15:11 +0200 Subject: [PATCH 01/13] Create 0023-multisig-wallet.md WIP --- text/0023-multisig-wallet.md | 119 +++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 text/0023-multisig-wallet.md diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md new file mode 100644 index 0000000..6608c29 --- /dev/null +++ b/text/0023-multisig-wallet.md @@ -0,0 +1,119 @@ + +- Title: multisig-wallet +- Authors: [valdok](https://github.com/valdok) +- Start date: Dec 16, 2025 + +--- + +## Summary +Support an M/N multisig wallet. + +## Motivation +The idea is to allow a wallet to be co-owned by several users, whereas a quorum of N/M is both required and sufficient to build a valid transaction (i.e. send or receive funds). + + +## Reference-level explanation + +The core idea is based on Shamir's secret sharing (SSS) scheme, which allows the reconstruction of a secret by a quorum of M/N. And due to the homomorphic nature of ECC, the secret will not be reconstructed in a plain way. It will only be used to compute the shared pubkey, and to calculate the signatures required to build transactions (such as Schnorr's signature, and UTXO rangeproof) + +Normal wallet has a master secret (usually derived from the seed phrase), which is then used to derive various keys, including the blinding factors for coins (like BIP44). + +The multisig wallet requires 2 changes: + +1. It will have 2 keys. One will be used in a deterministic key derivation (like HKDF / BIP44). The other, called a **co-factor**, will be constant, and act as a multiplier. It will be split among N co-owners via SSS scheme. +2. Key derivation can proceed accoring to BIP44, but the key path must include the coin value, not just the coin number. +More about this later, but in principle this should guarantee that each collectively built transaction spends and produces coins exactly as agreed, without amount being replaced/tampered. + + +### Key concepts + +Here we'll define key terms and concept + - **Secret key** - EC (elliptic curve) scalar + - **Pubkey** - EC point (group element). + - **Actor** - a user that co-owns a wallet. + - **Moniker** - a unique user name/alias, that the actor chooses for identification (such as `Alice`, `Bob`, and etc.) + + **Message authentication** + + The protocol doesn't always require a secret P2P communication between individual actors, most messages are shared between all the actors and considered non-secret. However some messages must be protected against tampering. Hence we assume that each message broadcasted by an actor + is signed by its private key, and then verified by others vs its pubkey + +**Scalar derivation** +We'll need a function to generate a scalar from arbitrary arguments. Basically it's implemented via a hash function (such as SHA-256). However additional steps are required to make sure the result is a valid EC scalar (clamping). +We'll call this function $Hash_s(msg)$ + +**Moniker -> scalar function** +While actors use monikers for identification, the SSS operates on arguments in terms of EC scalars. Each actor will be assigned a scalar $x_i = Hash_s(moniker_i)$. There should be no duplicates. In a highly unlikely case of collision, the actor will have to choose another moniker. + +**Mutual antisymmetric secret** + +For each pair of actors $i \neq j$ we'll define this function: + +$\delta(i,j,context) = Hash_s( DH(i,j) | context) \cdot (x_i - x_j)$ + +whereas $DH(i,j)$ stands for Diffie-Hellman shared secret, $context$ is arbitrary message, and $x_i$ is derived from the actor's moniker. +Not that this function is antisymmetric: $\delta(i,j) + \delta(j,i) = 0$ + + +### Wallet initialization/recovery + +In this process, M initial users initialize/restore the wallet + +(1) Each actor generates (or restores) its master key $sk_i$ (perhaps derived from its private seed phrase), and then broadcasts a message with those fields: +- Pubkey: $P_i = G \cdot sk_i$ +- Moniker + +This message **must** be signed by the actor pubkey. Not only to protect against tampering, but also to prevent a rogue-key attack. + +(2) After actors exhange this information, everyone verifies there're indeed M different actors, and there're no duplicates. Then the following SSS polynomial is defined: + +$$ +sk(x) = \sum_{i=1}^{M} sk_i \cdot \prod_{i \neq j} \frac{x - x_j}{x_i - x_j} +$$ + +Or, in terms of pubkeys: + +$$ +P(x) = \sum_{i=1}^{M} P_i \cdot \prod_{j \neq i} \frac{x - x_j}{x_i - x_j} +$$ + +The secret co-factor is defined as: $sk_{cf} = sk(0)$ + +The co-factor image is defined as this: $P_{cf} = P(0)$ + +**Note**: The $P_{cf}$ is computed by every actor individually, and is known among actors. In contrast the $sk_{cf}$ is never computed in a plain form. + +(3) Finally each actors initalizes its multisig wallet. The master secret used in BIP44/HKDF is initialized from $(P_{cf} | M)$. Each actor can individually calculate any pubkey: + +$$ +Pubkey(path) = BIP44(path) \cdot P_{cf} +$$ + +### Adding an actor + +A quorum of M current actors can add an additional actor. For this the following steps are performed. + +(1) New actor picks and shares a unique moniker. Unlike initial actors, that can generate/restore an arbitrary secret key, new actor's key is uniquely defined by its moniker. + +(2) Each actor computes ands sends **privately** the following key share: + +$$ +sk_{share_i} = sk_{i} \cdot \prod_{j \neq i} \frac{x_{new} - x_j}{x_i - x_j} + \sum_{j \neq i} \delta(i,j, context_{msg}) +$$ + +whereas $context_{msg}$ includes all the parameters of the ritual: $P_{cf}$, $x_{new}$, and the selected quorum of M existing actors. This is to make sure $\delta(i,j, context_{msg})$ is unique in each ritual + +The new actor then performs the summation of all the shares: + +$$ +sk_{new} = \sum_{i} sk_{share_i} +$$ + +Finally it verifies the correctness of its secret key, by checking if its appropriate pubkey sits on the same SSS polynome. + +$$ +G \cdot sk_{new} = P_{x_{new}} +$$ + +### Building a transaction + From 60e55dadea07398e37b5876eb1ccfc4060372c4c Mon Sep 17 00:00:00 2001 From: valdok Date: Wed, 17 Dec 2025 00:44:53 +0200 Subject: [PATCH 02/13] Update 0023-multisig-wallet.md --- text/0023-multisig-wallet.md | 57 ++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index 6608c29..ce49983 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -16,7 +16,7 @@ The idea is to allow a wallet to be co-owned by several users, whereas a quorum The core idea is based on Shamir's secret sharing (SSS) scheme, which allows the reconstruction of a secret by a quorum of M/N. And due to the homomorphic nature of ECC, the secret will not be reconstructed in a plain way. It will only be used to compute the shared pubkey, and to calculate the signatures required to build transactions (such as Schnorr's signature, and UTXO rangeproof) -Normal wallet has a master secret (usually derived from the seed phrase), which is then used to derive various keys, including the blinding factors for coins (like BIP44). +Normal wallet has a master secret (usually derived from the seed phrase), which is then used to derive various keys, including the blinding factors for coins (like \vf). The multisig wallet requires 2 changes: @@ -109,11 +109,62 @@ $$ sk_{new} = \sum_{i} sk_{share_i} $$ -Finally it verifies the correctness of its secret key, by checking if its appropriate pubkey sits on the same SSS polynome. +Note that during this summation, all the $\delta(i,j)$ terms are cancelled-out. They are needed to blind each actor's secret key, but don't affect the sum of all the shares. + +Finally the new actor verifies the correctness of its secret key, by checking if its appropriate pubkey sits on the same SSS polynome. $$ -G \cdot sk_{new} = P_{x_{new}} +G \cdot sk_{new} = P_{x_{new}} = P(x_{new}) $$ + ### Building a transaction +MW transaction consists of inputs, outputs at least one kernel. In order to build a valid transaction, a subset of M/N actors are selected. Each actor gets the transaction parameters: +- list of input coins (coin number + value) +- list of output coins (coin number + value) +- any additional metadata (current blockchain height, fee, the identity of the tx peer, memo, etc.) + +Each actor receives and realizes the tx parameters. In particular, the tx balance (outputs minus inputs) is calculated. And then it decides if it wishes to take a part. Then the selected actors perform an MPC to build the transaction. + +Inputs are represented by Pedersen commitments (or, alternatively, Switch commitments). Since they are EC points, the knowledge of $sk_{cf}$ is not necessary, they can be calculated by each actor from $P_{cf}$ alone. + +$$ +C(number, value) = BIP44(CoinPath(number, value)) \cdot P_{cf} + H \cdot value +$$ + +Now we'll define how output TXOs and the transaction kernel are created and signed + +#### UTXO + +The UTXO is represented by its commitment and the Rangeproof (a.k.a. bulletproof). The commitment is computed exactly as for inputs, by each actor individually. So, only the rangeproof requires MPC. + +During the rangeproof creation, various pseudo-random EC scalars are generated. There're 2 sources of the randomness: +1. Randomness to obscure the UTXO value, also used to "color" it, make it possible to recognize by the owner, and recover the parameters (coin number and the value). +2. Randomness to protect the UTXO blinding factor. + +In standard wallet (not multisig) it's possible to use a single source of randomness for both purposes. It also means that UTXO recognition is in fact its full reverse-engineering. + +In multisigned wallet it's essential to use 2 distinct sources of randomness. The (1) is derived from the $P_{cf}$ (which is known to all the actors) and the UTXO commitment. The (2) is derived by each actor individually to obscure its key share. +Moreover, since we're tralking about multisig, each actor will rely on non-deterministic random. + +The rangeproof protocol between (P)rover and (V)erifier is defined like this: +- P: Commitment, A, S (commitments) +- V: y, z (challenges) +- P: T1, T2 (commitments) +- V: x (challenges) +- P: $Tau_X$ (scalar) +- (continued) + +The $Tau_X$ is a linear combination of the UTXO blinding factor, and 2 nonces, whereas EC points T1 and T2 are commitments to those nonces. So, the modified algorithm to create the rangeproof looks like this: + +- Each actor proceeds according to the scheme, up to where T1,T2 should be revealed. +- Each actor generates 2 nonces, using true random (i.e. non-deterministic), uses them to calculate its share of T1,T2, and reveals its shares. +- Once M actors reveal their shares, they're aggregated to compute the final T1,T2. +- Each validator derives the next nonce, and uses it to compute and reveal its share of $Tau_X$ +- Once M actors reveal their shares, they're aggregated to compute the $Tau_X$ +- All the consequent steps are performed individually by each actor (no more MPC is required) + + +#### Transaction Kernel + From 3119f8f2e2e0fbaa065fcce67614228abac31bda Mon Sep 17 00:00:00 2001 From: valdok Date: Wed, 17 Dec 2025 12:26:38 +0200 Subject: [PATCH 03/13] 0023-multisig-wallet WIP --- text/0023-multisig-wallet.md | 58 ++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index ce49983..a60e03a 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -163,8 +163,66 @@ The $Tau_X$ is a linear combination of the UTXO blinding factor, and 2 nonces, w - Once M actors reveal their shares, they're aggregated to compute the final T1,T2. - Each validator derives the next nonce, and uses it to compute and reveal its share of $Tau_X$ - Once M actors reveal their shares, they're aggregated to compute the $Tau_X$ + - Note: it's possible to verify the correctness of each partial contribution to $Tau_X$ - All the consequent steps are performed individually by each actor (no more MPC is required) #### Transaction Kernel +In order to create and sign the transaction kernel, the MPC is required as well. Even in normal transactions, where both the sender and the receiver are standard wallets, the MPC is used to create and sign the transaction kernel. + +Here we'll generalize this to the case where either side of the transaction (either the sender or the receiver or both) is a multisig wallet. + +The difference of the inputs-outputs blinding factors contributes to the transaction excess, and should be compensated by the transaction kernel. Each actor calculates its share of this excess, +this is its share of the secret key that's used to sign the kernel. + +An important addition to the classical MW is the so-called transaction **offset**. The total transaction blinding factor excess is split into 2 parts. One is compensated by the transaction kernel, and the other part is revealed in a plain form (EC scalar). This makes it infeasible for the attacker to reverse engineer the coinjoined transactions. To support this, each actor splits its key share into 2 parts as well. + +Then the principle is similar to that of UTXO. During the first round each actor creates a non-deterministic nonce, reveals its image, the image of its share to the kernel excess, and the offset. Then, once all the nonces and kernel commitment shares are known and aggregated (from both sides of the transaction), the kernel is fully built. During the second round, each actor derives the signature challenge, and reveals its share of the blinded secret key. + +#### E2E flow + +Here we'll consider an example where Alice sends funds to Bob, both are in fact multisig wallets + +- Alice side + - A quorum of $M_A$ actors that co-own the Alice wallet decides to send funds to Bob. A list of input coins is selected, fee is decided, the coin number for the exchange coin is choosen. + - The information is distributed among the actors. + - They generate appropriate nonces (2 for output UTXO, one for tx kernel) + - Round 1: they reveal the images: T1,T2 for the UTXO, kernel Commitment and the noce image. + - The semi-build kernel is sent to the Bob, among with the general transaction info +- Bob side + - A quorum of $M_B$ Bob's actors decides to accept the funds. They choose the coin number for the output UTXO + - Each actor generates the appropriate nonces (2 for output UTXO, and 1 for kernel). + - Round 1: they reveal the images: T1,T2 for the UTXO, kernel Commitment and the noce image. + - Round 2: each actor receives the aggregates for the UTXO and the kernel. And reveals its partial signatures, and its share to the offset + - The aggregated kernel with the signed Bob's UTXO is sent to Alice +- Alice side + - Round 2: each actor receives the aggregates for the UTXO and the kernel. And reveals its partial signatures, and its share to the offset +- The transaction is aggregated, and can be sent to the network + +As can be seen from the above, the roles of Bob and Alice actors are symmetric. Both participate in 2 rounds of MPC. + +## Security considerations + +### Adding the new actor, and the role of $\delta(i,j)$ + +During the new actor addition, each current actor reveals its secret key in a plain form to the new actor. It's multiplied by the SSS coefficient, but this coefficient is widely known. So without the addition of $\delta(i,j)$ terms each actor secret key would be trivial to compute. + +This is why $\delta(i,j)$ terms are essential, they perform the perfect blinding of the actor secret key. Moreover, even if several current actors collude with the new actor, still its key is perfectly blinded as long as there is at least a single honest actor that doesn't disclose its $\delta(i,j)$ term. + +The only situation where the actor key can be compromised is wherer all M-1 other actors collude with the new one. But this essentially means that they togetther form a quorum of M malicious actors. And obviously a quorum of M actors can calculate and compromise any key. + +### UTXO and kernel signing, why rely on non-deterministic random + +It's generally considered better to rely on deterministic nonce generation scheme, such as RFC-6979. However such schemes can't be used as-is in multisig rituals. There're advanced schemes, such as those used in MuSig-DN, that rely on ZKP to verify that each actor generated its nonce deterministically. + +For the sake of simplicity, we'll stick to random (non-deterministic) nonces. In the future it'll be possible to upgrade the protocol, and use the PRF (pseudo-random function) together with Bulletproof ZKP to generate and verify the correctness of the nonces. +In either case, the general flow remains the same. +And as long as the main principle holds: each nonce is used to only answer one challenge - the secret keys are safe. + +### Rogue key attack +The only situation where such an attack is possible is during the wallet initialization by the quorum of M inital actors. If not mitigated, an actor can essentially cancel the keys of other actors, and gain an exclusive access. +As we mentioned, this is mitigated by the fact that all messages sent by the actors are supposed to be signed by them. + +### Wagner attack + From 020e5e655d5f2e39022be798b4c834cfc3a06a1a Mon Sep 17 00:00:00 2001 From: valdok Date: Wed, 17 Dec 2025 14:12:01 +0200 Subject: [PATCH 04/13] 0023-multisig-wallet WIP(2) --- text/0023-multisig-wallet.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index a60e03a..d6265d7 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -30,6 +30,7 @@ More about this later, but in principle this should guarantee that each collecti Here we'll define key terms and concept - **Secret key** - EC (elliptic curve) scalar - **Pubkey** - EC point (group element). + - We'll use the additive notation for the ECC operations (i.e. adding points, and multiplying points by scalars) - **Actor** - a user that co-owns a wallet. - **Moniker** - a unique user name/alias, that the actor chooses for identification (such as `Alice`, `Bob`, and etc.) @@ -224,5 +225,32 @@ And as long as the main principle holds: each nonce is used to only answer one c The only situation where such an attack is possible is during the wallet initialization by the quorum of M inital actors. If not mitigated, an actor can essentially cancel the keys of other actors, and gain an exclusive access. As we mentioned, this is mitigated by the fact that all messages sent by the actors are supposed to be signed by them. -### Wagner attack +### Coin key generation, and Wagner attack + +The main potential weakness of the described scheme is that, after the agreed transaction is built and signed by the actors, a malicious actor can try to replace transaction inputs (or outputs) by the other ones, containing a lower value. Then, the value excess can be compensated by attacker's UTXO added to the transaction. + +Suppose a multisig wallet owns two coins, with values $V1 < V2$. There's a decision to spend the coin with value $V1$ in a transaction. It's collectively built and signed, but then a malicious actor changes the input to $V2$, and appends its UTXO that absorbs the value $V2-V1$. + +Actions such as replacing coins are generally not possible, because different coins have different blinding factors, and it's not feasible to build a valid transaction when the blinding factor balance isn't compensated. But what if yjr attacker can manipulate inputs and outputs such that the **resulting blinding factor balance is unchanged**? + +This is a real threat, and we'll describe why it's possible, and how to mitigate possible attacks. + +#### 1. Why the coin value should be used together with the coin number in its key derivation +Coins with different numbers (i.e. IDs) will have different blinding factors. But what if a wallet owns several coins with different values but the same number? +Normally actors should not take part in UTXO creation with coin number that was already used. But the situation may be confusing because of the blockchain state volatility. There can be potential reorgs, whereas transactions may be reverted, and then, after some time, included again in a block. +By such it's theoretically possible the wallet will own several coins with the same ID, but different values. If the same blinding factor is used in all of them, then it's trivial to replace them in an already-built transaction. + +**Mitigation:** include the coin value in the blidning factor derivation too. That is, if the BIP44 is used, both the coin number and its value must be included in the derivation path. + +#### Wagner attack + +Due to the nature of MW, a transaction may contain multiple inputs and outputs. And it's generally feasible to find different sets of inputs/outputs, such that the excess of blinding factors will be the same: + +$$ +\sum_{i}^{inputs_1} Key(number_i, value_i) - \sum_{j}^{outputs_1} Key(number_j, value_j) = \sum_{i}^{inputs_2} Key(number_i, value_i) - \sum_{j}^{outputs_2} Key(number_j, value_j) +$$ + +If the sets of inputs/outputs are large enough, then this may be a feasible task. + +Now, we know that the coins keys are not known to the attacker because on actor fully has the co-factor $sk_{cf}$. But, turns out, this is not important here. The co-factor is constant for all the coins. And if the attacker can find such sets with equal blinding factor excess before they're multiplied by the co-factor - the equivalence will hold after the co-factor is applied as well. From 7d7a3c985a8f3dd00924ca0f2dc1a38d510d1c36 Mon Sep 17 00:00:00 2001 From: valdok Date: Wed, 17 Dec 2025 15:15:38 +0200 Subject: [PATCH 05/13] 0023-multisig-wallet WIP(3) --- text/0023-multisig-wallet.md | 48 +++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index d6265d7..381535e 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -14,15 +14,11 @@ The idea is to allow a wallet to be co-owned by several users, whereas a quorum ## Reference-level explanation -The core idea is based on Shamir's secret sharing (SSS) scheme, which allows the reconstruction of a secret by a quorum of M/N. And due to the homomorphic nature of ECC, the secret will not be reconstructed in a plain way. It will only be used to compute the shared pubkey, and to calculate the signatures required to build transactions (such as Schnorr's signature, and UTXO rangeproof) +The core idea is based on Shamir's secret sharing (SSS) scheme, which allows the reconstruction of a secret by a quorum of M/N. And due to the homomorphic nature of ECC, the secret keys will not be calculated in a plain way. It will only be used to compute the public keys, and to calculate the signatures in an MPC ritual required to build transactions (such as Schnorr's signature, and UTXO rangeproof) -Normal wallet has a master secret (usually derived from the seed phrase), which is then used to derive various keys, including the blinding factors for coins (like \vf). +Normal wallet has a master secret (usually derived from the seed phrase), which is then used to derive various keys, including the blinding factors for coins (BIP44). -The multisig wallet requires 2 changes: - -1. It will have 2 keys. One will be used in a deterministic key derivation (like HKDF / BIP44). The other, called a **co-factor**, will be constant, and act as a multiplier. It will be split among N co-owners via SSS scheme. -2. Key derivation can proceed accoring to BIP44, but the key path must include the coin value, not just the coin number. -More about this later, but in principle this should guarantee that each collectively built transaction spends and produces coins exactly as agreed, without amount being replaced/tampered. +Multisig wallet will instead rely on SSS to generate the keys. The BIP44 can still be used as an addition, to increase the security of the wallet (more about this later). ### Key concepts @@ -40,11 +36,11 @@ Here we'll define key terms and concept is signed by its private key, and then verified by others vs its pubkey **Scalar derivation** -We'll need a function to generate a scalar from arbitrary arguments. Basically it's implemented via a hash function (such as SHA-256). However additional steps are required to make sure the result is a valid EC scalar (clamping). +We'll need a collision-resistant function to generate a scalar from arbitrary arguments. Basically it's implemented via a hash function (such as SHA-256). However additional steps are required to make sure the result is a valid EC scalar (clamping). We'll call this function $Hash_s(msg)$ **Moniker -> scalar function** -While actors use monikers for identification, the SSS operates on arguments in terms of EC scalars. Each actor will be assigned a scalar $x_i = Hash_s(moniker_i)$. There should be no duplicates. In a highly unlikely case of collision, the actor will have to choose another moniker. +While actors use monikers for identification, the SSS operates on arguments in terms of EC scalars. Each actor will be assigned a scalar $x_i = Hash_s("actor-" | moniker_i)$. There should be no duplicates. In a highly unlikely case of collision, the actor will have to choose another moniker. **Mutual antisymmetric secret** @@ -75,21 +71,31 @@ $$ Or, in terms of pubkeys: $$ -P(x) = \sum_{i=1}^{M} P_i \cdot \prod_{j \neq i} \frac{x - x_j}{x_i - x_j} +P(x) = \sum_{i=1}^{M} P_i \cdot \prod_{j \neq i} \frac{x - x_j}{x_i - x_j} = \sum_{n=0}^{M-1}S_n \cdot x^n $$ -The secret co-factor is defined as: $sk_{cf} = sk(0)$ +Upon ritual completion, the public polynome coefficients $S_n$ become known to all the actors. The set { $\{ S_n \}$ } defines the wallet account. + +Finally each actor initalizes its multisig wallet. The coefficients { $\{ S_n \}$ } are saved, in addition to its secret key and the moniker. -The co-factor image is defined as this: $P_{cf} = P(0)$ +(3) Coin blinding factor is defined according to this formula: -**Note**: The $P_{cf}$ is computed by every actor individually, and is known among actors. In contrast the $sk_{cf}$ is never computed in a plain form. +$$ +x_{coin}(number, value) = Hash_s("coin-" | number | value) +$$ -(3) Finally each actors initalizes its multisig wallet. The master secret used in BIP44/HKDF is initialized from $(P_{cf} | M)$. Each actor can individually calculate any pubkey: +and then: $$ -Pubkey(path) = BIP44(path) \cdot P_{cf} +sk_{coin}(number, value) = sk(x_{coin}) + HKDF(S_0, x_{coin}) $$ +whereas $number$ specifies the coin ID (number or any unique parameters), and ${S_0}$ is used as a seed to derive a complemental key via HKDF. While this term is known among actors, it's important to keep it, since it can increase the overall security (more about this later). + +Note that the coin blinding factor can't be calculated by individual actors (since the function $sk_(x)$ is unknown). Actors can only calculate their shares to the coin blinding factor. +But the public key, and the coin commitment can be calculated be each actor individually. + + ### Adding an actor A quorum of M current actors can add an additional actor. For this the following steps are performed. @@ -99,10 +105,10 @@ A quorum of M current actors can add an additional actor. For this the following (2) Each actor computes ands sends **privately** the following key share: $$ -sk_{share_i} = sk_{i} \cdot \prod_{j \neq i} \frac{x_{new} - x_j}{x_i - x_j} + \sum_{j \neq i} \delta(i,j, context_{msg}) +sk_{share_i} = sk_{i} \cdot \prod_{j \neq i} \frac{x_{new} - x_j}{x_i - x_j} + \sum_{j \neq i} \delta(i,j, context) $$ -whereas $context_{msg}$ includes all the parameters of the ritual: $P_{cf}$, $x_{new}$, and the selected quorum of M existing actors. This is to make sure $\delta(i,j, context_{msg})$ is unique in each ritual +whereas $context$ includes all the parameters of the ritual: $S_0$, $x_{new}$, and the selected quorum of M existing actors. This is to make sure $\delta(i,j, context)$ is unique in each ritual The new actor then performs the summation of all the shares: @@ -128,10 +134,12 @@ MW transaction consists of inputs, outputs at least one kernel. In order to buil Each actor receives and realizes the tx parameters. In particular, the tx balance (outputs minus inputs) is calculated. And then it decides if it wishes to take a part. Then the selected actors perform an MPC to build the transaction. -Inputs are represented by Pedersen commitments (or, alternatively, Switch commitments). Since they are EC points, the knowledge of $sk_{cf}$ is not necessary, they can be calculated by each actor from $P_{cf}$ alone. +### Inputs + +Inputs are represented by Pedersen commitments (or, alternatively, Switch commitments). Since they are EC points, they can be calculated by each actor: $$ -C(number, value) = BIP44(CoinPath(number, value)) \cdot P_{cf} + H \cdot value +C(number, value) = P(x_{coin}(number, value)) + H \cdot value $$ Now we'll define how output TXOs and the transaction kernel are created and signed @@ -162,7 +170,7 @@ The $Tau_X$ is a linear combination of the UTXO blinding factor, and 2 nonces, w - Each actor proceeds according to the scheme, up to where T1,T2 should be revealed. - Each actor generates 2 nonces, using true random (i.e. non-deterministic), uses them to calculate its share of T1,T2, and reveals its shares. - Once M actors reveal their shares, they're aggregated to compute the final T1,T2. -- Each validator derives the next nonce, and uses it to compute and reveal its share of $Tau_X$ +- Each actor derives the next nonce, and uses it to compute and reveal its share of $Tau_X$ - Once M actors reveal their shares, they're aggregated to compute the $Tau_X$ - Note: it's possible to verify the correctness of each partial contribution to $Tau_X$ - All the consequent steps are performed individually by each actor (no more MPC is required) From a487fd7713dd74594bb358c6c8db954d7ca3559a Mon Sep 17 00:00:00 2001 From: valdok Date: Wed, 17 Dec 2025 17:42:02 +0200 Subject: [PATCH 06/13] 0023-multisig-wallet WIP(4) --- text/0023-multisig-wallet.md | 84 ++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index 381535e..3fd0eec 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -16,9 +16,9 @@ The idea is to allow a wallet to be co-owned by several users, whereas a quorum The core idea is based on Shamir's secret sharing (SSS) scheme, which allows the reconstruction of a secret by a quorum of M/N. And due to the homomorphic nature of ECC, the secret keys will not be calculated in a plain way. It will only be used to compute the public keys, and to calculate the signatures in an MPC ritual required to build transactions (such as Schnorr's signature, and UTXO rangeproof) -Normal wallet has a master secret (usually derived from the seed phrase), which is then used to derive various keys, including the blinding factors for coins (BIP44). +Normal wallet has a master secret (usually derived from the seed phrase), which is then used to derive various keys, including the blinding factors for coins (such as BIP44). -Multisig wallet will instead rely on SSS to generate the keys. The BIP44 can still be used as an addition, to increase the security of the wallet (more about this later). +Multisig wallet will instead rely on SSS to generate the keys. The BIP44 can still be used in addition, to increase the security of the wallet (more about this later). ### Key concepts @@ -36,7 +36,7 @@ Here we'll define key terms and concept is signed by its private key, and then verified by others vs its pubkey **Scalar derivation** -We'll need a collision-resistant function to generate a scalar from arbitrary arguments. Basically it's implemented via a hash function (such as SHA-256). However additional steps are required to make sure the result is a valid EC scalar (clamping). +We'll need a collision-resistant function to generate a scalar from arbitrary public arguments. Basically it's implemented via a hash function (such as SHA-256). However additional steps are required to make sure the result is a valid EC scalar (clamping). We'll call this function $Hash_s(msg)$ **Moniker -> scalar function** @@ -74,7 +74,7 @@ $$ P(x) = \sum_{i=1}^{M} P_i \cdot \prod_{j \neq i} \frac{x - x_j}{x_i - x_j} = \sum_{n=0}^{M-1}S_n \cdot x^n $$ -Upon ritual completion, the public polynome coefficients $S_n$ become known to all the actors. The set { $\{ S_n \}$ } defines the wallet account. +Upon ritual completion, the public polynome coefficients { $S_n$ } become known to all the actors. Finally each actor initalizes its multisig wallet. The coefficients { $\{ S_n \}$ } are saved, in addition to its secret key and the moniker. @@ -132,19 +132,17 @@ MW transaction consists of inputs, outputs at least one kernel. In order to buil - list of output coins (coin number + value) - any additional metadata (current blockchain height, fee, the identity of the tx peer, memo, etc.) -Each actor receives and realizes the tx parameters. In particular, the tx balance (outputs minus inputs) is calculated. And then it decides if it wishes to take a part. Then the selected actors perform an MPC to build the transaction. +Each actor receives and realizes the tx parameters. In particular, the tx balance (outputs minus inputs, the net value received/sent) is calculated. And then it decides if it wishes to take a part. Then the selected actors perform an MPC to build the transaction. ### Inputs Inputs are represented by Pedersen commitments (or, alternatively, Switch commitments). Since they are EC points, they can be calculated by each actor: $$ -C(number, value) = P(x_{coin}(number, value)) + H \cdot value +C(coin) = P(x_{coin}) + G \cdot HKDF(S_0, x_{coin}) + H \cdot value $$ -Now we'll define how output TXOs and the transaction kernel are created and signed - -#### UTXO +#### Outputs The UTXO is represented by its commitment and the Rangeproof (a.k.a. bulletproof). The commitment is computed exactly as for inputs, by each actor individually. So, only the rangeproof requires MPC. @@ -154,14 +152,14 @@ During the rangeproof creation, various pseudo-random EC scalars are generated. In standard wallet (not multisig) it's possible to use a single source of randomness for both purposes. It also means that UTXO recognition is in fact its full reverse-engineering. -In multisigned wallet it's essential to use 2 distinct sources of randomness. The (1) is derived from the $P_{cf}$ (which is known to all the actors) and the UTXO commitment. The (2) is derived by each actor individually to obscure its key share. -Moreover, since we're tralking about multisig, each actor will rely on non-deterministic random. +In multisigned wallet it's essential to use 2 distinct sources of randomness. The (1) is derived from the $S_0$ (which is known to all the actors) and the UTXO commitment. The (2) is derived by each actor individually to obscure its key share. +Since it's a multisig, each actor will rely on non-deterministic nonces (random). The rangeproof protocol between (P)rover and (V)erifier is defined like this: - P: Commitment, A, S (commitments) - V: y, z (challenges) - P: T1, T2 (commitments) -- V: x (challenges) +- V: x (challenge) - P: $Tau_X$ (scalar) - (continued) @@ -170,7 +168,7 @@ The $Tau_X$ is a linear combination of the UTXO blinding factor, and 2 nonces, w - Each actor proceeds according to the scheme, up to where T1,T2 should be revealed. - Each actor generates 2 nonces, using true random (i.e. non-deterministic), uses them to calculate its share of T1,T2, and reveals its shares. - Once M actors reveal their shares, they're aggregated to compute the final T1,T2. -- Each actor derives the next nonce, and uses it to compute and reveal its share of $Tau_X$ +- Each actor derives the next challenge, and uses it to compute and reveal its share of $Tau_X$ - Once M actors reveal their shares, they're aggregated to compute the $Tau_X$ - Note: it's possible to verify the correctness of each partial contribution to $Tau_X$ - All the consequent steps are performed individually by each actor (no more MPC is required) @@ -185,9 +183,10 @@ Here we'll generalize this to the case where either side of the transaction (eit The difference of the inputs-outputs blinding factors contributes to the transaction excess, and should be compensated by the transaction kernel. Each actor calculates its share of this excess, this is its share of the secret key that's used to sign the kernel. -An important addition to the classical MW is the so-called transaction **offset**. The total transaction blinding factor excess is split into 2 parts. One is compensated by the transaction kernel, and the other part is revealed in a plain form (EC scalar). This makes it infeasible for the attacker to reverse engineer the coinjoined transactions. To support this, each actor splits its key share into 2 parts as well. +An important addition to the classical MW is the so-called transaction **offset**. The total transaction blinding factor excess is split into 2 parts. One is compensated by the transaction kernel, and the other part is revealed in a plain form (EC scalar). This makes it infeasible for the attacker to reverse engineer the coinjoined transactions. To support this, the offset is generated in a deterministic way: $offset = HKDF(S_0, context)$ whereas $context$ accounts for all the transaction parameters: list of coins, metadata, selected quorum, etc. +Then it's accounted in the kernel commitment, and in the signature (during the aggregation stage). -Then the principle is similar to that of UTXO. During the first round each actor creates a non-deterministic nonce, reveals its image, the image of its share to the kernel excess, and the offset. Then, once all the nonces and kernel commitment shares are known and aggregated (from both sides of the transaction), the kernel is fully built. During the second round, each actor derives the signature challenge, and reveals its share of the blinded secret key. +Then the principle is similar to that of UTXO. During the first round each actor creates a non-deterministic nonce, and reveals its image. Then, once all the nonces and kernel commitment shares are known and aggregated (from both sides of the transaction), the kernel is fully built. During the second round, each actor derives the signature challenge, and reveals its share of the blinded secret key. #### E2E flow @@ -197,16 +196,16 @@ Here we'll consider an example where Alice sends funds to Bob, both are in fact - A quorum of $M_A$ actors that co-own the Alice wallet decides to send funds to Bob. A list of input coins is selected, fee is decided, the coin number for the exchange coin is choosen. - The information is distributed among the actors. - They generate appropriate nonces (2 for output UTXO, one for tx kernel) - - Round 1: they reveal the images: T1,T2 for the UTXO, kernel Commitment and the noce image. - - The semi-build kernel is sent to the Bob, among with the general transaction info + - Round 1: they reveal the images: T1,T2 for the UTXO, and the kernel nonce image. + - The semi-built kernel is sent to the Bob, among with the general transaction info - Bob side - A quorum of $M_B$ Bob's actors decides to accept the funds. They choose the coin number for the output UTXO - Each actor generates the appropriate nonces (2 for output UTXO, and 1 for kernel). - - Round 1: they reveal the images: T1,T2 for the UTXO, kernel Commitment and the noce image. - - Round 2: each actor receives the aggregates for the UTXO and the kernel. And reveals its partial signatures, and its share to the offset - - The aggregated kernel with the signed Bob's UTXO is sent to Alice + - Round 1: they reveal the images: T1,T2 for the UTXO, and the kernel noce image. + - Round 2: each actor receives the aggregates for the UTXO and the kernel. And reveals its partial signatures + - The aggregated kernel, offset and Bob's UTXO is sent to Alice - Alice side - - Round 2: each actor receives the aggregates for the UTXO and the kernel. And reveals its partial signatures, and its share to the offset + - Round 2: each actor receives the aggregates for the UTXO and the kernel. And reveals its partial signatures - The transaction is aggregated, and can be sent to the network As can be seen from the above, the roles of Bob and Alice actors are symmetric. Both participate in 2 rounds of MPC. @@ -217,9 +216,9 @@ As can be seen from the above, the roles of Bob and Alice actors are symmetric. During the new actor addition, each current actor reveals its secret key in a plain form to the new actor. It's multiplied by the SSS coefficient, but this coefficient is widely known. So without the addition of $\delta(i,j)$ terms each actor secret key would be trivial to compute. -This is why $\delta(i,j)$ terms are essential, they perform the perfect blinding of the actor secret key. Moreover, even if several current actors collude with the new actor, still its key is perfectly blinded as long as there is at least a single honest actor that doesn't disclose its $\delta(i,j)$ term. +This is why $\delta(i,j)$ terms are essential, they perform the perfect hiding of the actor secret key. Moreover, even if several current actors collude with the new actor, still its key is perfectly hidden as long as there is at least a single honest actor that doesn't disclose its $\delta(i,j)$ term. -The only situation where the actor key can be compromised is wherer all M-1 other actors collude with the new one. But this essentially means that they togetther form a quorum of M malicious actors. And obviously a quorum of M actors can calculate and compromise any key. +The only situation where the actor key can be compromised is where all M-1 other actors collude with the new one. But this essentially means that they together form a quorum of M malicious actors. And obviously a quorum of M actors can calculate and compromise any key. ### UTXO and kernel signing, why rely on non-deterministic random @@ -233,32 +232,51 @@ And as long as the main principle holds: each nonce is used to only answer one c The only situation where such an attack is possible is during the wallet initialization by the quorum of M inital actors. If not mitigated, an actor can essentially cancel the keys of other actors, and gain an exclusive access. As we mentioned, this is mitigated by the fact that all messages sent by the actors are supposed to be signed by them. -### Coin key generation, and Wagner attack +### Why the coin value should be used together with the coin number in its key derivation -The main potential weakness of the described scheme is that, after the agreed transaction is built and signed by the actors, a malicious actor can try to replace transaction inputs (or outputs) by the other ones, containing a lower value. Then, the value excess can be compensated by attacker's UTXO added to the transaction. +After the agreed transaction is built and signed by the actors, a malicious actor can try to replace transaction inputs (or outputs) by the other ones, containing a lower value. Then, the value excess can be compensated by attacker's UTXO added to the transaction. Suppose a multisig wallet owns two coins, with values $V1 < V2$. There's a decision to spend the coin with value $V1$ in a transaction. It's collectively built and signed, but then a malicious actor changes the input to $V2$, and appends its UTXO that absorbs the value $V2-V1$. -Actions such as replacing coins are generally not possible, because different coins have different blinding factors, and it's not feasible to build a valid transaction when the blinding factor balance isn't compensated. But what if yjr attacker can manipulate inputs and outputs such that the **resulting blinding factor balance is unchanged**? +Actions such as replacing coins are generally not possible, because different coins have different blinding factors, and it's not feasible to build a valid transaction when the blinding factor balance isn't compensated. But what if rgw attacker can manipulate inputs and outputs such that the **resulting blinding factor balance is unchanged**? -This is a real threat, and we'll describe why it's possible, and how to mitigate possible attacks. -#### 1. Why the coin value should be used together with the coin number in its key derivation Coins with different numbers (i.e. IDs) will have different blinding factors. But what if a wallet owns several coins with different values but the same number? Normally actors should not take part in UTXO creation with coin number that was already used. But the situation may be confusing because of the blockchain state volatility. There can be potential reorgs, whereas transactions may be reverted, and then, after some time, included again in a block. By such it's theoretically possible the wallet will own several coins with the same ID, but different values. If the same blinding factor is used in all of them, then it's trivial to replace them in an already-built transaction. **Mitigation:** include the coin value in the blidning factor derivation too. That is, if the BIP44 is used, both the coin number and its value must be included in the derivation path. -#### Wagner attack +### Wagner attack, Prouhet-Tarry-Escott (PTE) problem -Due to the nature of MW, a transaction may contain multiple inputs and outputs. And it's generally feasible to find different sets of inputs/outputs, such that the excess of blinding factors will be the same: +Due to the nature of MW, a transaction may contain multiple inputs and outputs. And the attacker can try to find different sets of inputs/outputs, such that the excess of blinding factors will be the same: $$ -\sum_{i}^{inputs_1} Key(number_i, value_i) - \sum_{j}^{outputs_1} Key(number_j, value_j) = \sum_{i}^{inputs_2} Key(number_i, value_i) - \sum_{j}^{outputs_2} Key(number_j, value_j) +\sum_{i}^{inputs_1} Key(coin_i) - \sum_{j}^{outputs_1} Key(coin_j) = \sum_{i}^{inputs_2} Key(coin_i) - \sum_{j}^{outputs_2} Key(coin_j) +$$ + +Note that if the attacker could derive blinding factors for arbitrary coin parameters, then it'd be a feasible task for a large enough set. This is known as the Generalized Birthday problem, or Wagner attack. + +However, in our particular case, coin blinding factors are derived from the SSS polynome, whose coefficients are secret. + +So, the only way for the attacker to find such sets is to try to find the sets where different powers of $x^n$ are equal for different sets. That is: + $$ +\sum_{i}^{inputs_1} x^n(coin_i) - \sum_{j}^{outputs_1} x^n(coin_j) = \sum_{i}^{inputs_2} x^n(coin_i) - \sum_{j}^{outputs_2} x^n(coin_j) +$$ + +$$\forall\, n \in \{0, \dots, M-1\}$$ + + +(This is like trying to solve M-1 generalized birthday problems simultaneously). + +It's a known problem, called Prouhet-Tarry-Escott (PTE) problem. And it's considered generally infeasible to solve, especially for large M -If the sets of inputs/outputs are large enough, then this may be a feasible task. +However, since real-world M doesn't have to be large, additional steps can be taken by the actors to prevent the possibility of such attacks (though not sure if they're really needed). Those include the following: +- Ensure the being-spent coins actually exist and unspent (i.e. don't build transaction for non-existing inputs) +- Stick to consequent coin number allocation. Each new coin number should not be completely random. +- Don't create excessive number of outputs in a transaction. Normal transaction creates only a single output (per each side). -Now, we know that the coins keys are not known to the attacker because on actor fully has the co-factor $sk_{cf}$. But, turns out, this is not important here. The co-factor is constant for all the coins. And if the attacker can find such sets with equal blinding factor excess before they're multiplied by the co-factor - the equivalence will hold after the co-factor is applied as well. +### Why it's beneficial to include the commonly-known HKDF-based key complement +Theoretically even withouth the HKDF-based key the described scheme should be secure, and the coin blinding factors should never be revealed. However, if a coin blinding factor is leaked (for whatever reason) - it may compromise all the secret keys. From cabf6f2e2df3622e6c9f52dcb7582a64fc60a8ba Mon Sep 17 00:00:00 2001 From: valdok Date: Wed, 17 Dec 2025 17:49:40 +0200 Subject: [PATCH 07/13] 0023-multisig-wallet WIP(5) --- text/0023-multisig-wallet.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index 3fd0eec..891cf74 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -279,4 +279,14 @@ However, since real-world M doesn't have to be large, additional steps can be ta ### Why it's beneficial to include the commonly-known HKDF-based key complement -Theoretically even withouth the HKDF-based key the described scheme should be secure, and the coin blinding factors should never be revealed. However, if a coin blinding factor is leaked (for whatever reason) - it may compromise all the secret keys. +Theoretically coin blinding factors should never be revealed. However, if a coin blinding factor is leaked (for whatever reason), withouth the HKDF-based blinding factor it may compromise all the secret keys. + +Without the HKDF part, the coin blinding factor is: + +$$ +sk(x) = \sum_{n=0}^{M-1} s_n \cdot x^n +$$ + +whereas $s_n$ are the unknown coefficient. If the coin blinding factor and its number is leaked, then this gives an equation. If M different blinding factors are leaked - then there're M linear equations for $s_n$ coefficients, that can easily be solved. + +So, keeping this in mind, it's beneficial to add additional "shared" blinding factor to each key. From cd91261c979eb80260fdc811508f6d505b7ba23b Mon Sep 17 00:00:00 2001 From: valdok Date: Wed, 17 Dec 2025 18:14:04 +0200 Subject: [PATCH 08/13] small corrections --- text/0023-multisig-wallet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index 891cf74..0a4ae8a 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -245,7 +245,7 @@ Coins with different numbers (i.e. IDs) will have different blinding factors. Bu Normally actors should not take part in UTXO creation with coin number that was already used. But the situation may be confusing because of the blockchain state volatility. There can be potential reorgs, whereas transactions may be reverted, and then, after some time, included again in a block. By such it's theoretically possible the wallet will own several coins with the same ID, but different values. If the same blinding factor is used in all of them, then it's trivial to replace them in an already-built transaction. -**Mitigation:** include the coin value in the blidning factor derivation too. That is, if the BIP44 is used, both the coin number and its value must be included in the derivation path. +**Mitigation:** include the coin value in the blidning factor derivation too. ### Wagner attack, Prouhet-Tarry-Escott (PTE) problem From 64fbe56735117512a9b3f2bc20d7c45c37fea379 Mon Sep 17 00:00:00 2001 From: valdok Date: Wed, 17 Dec 2025 18:15:13 +0200 Subject: [PATCH 09/13] typo --- text/0023-multisig-wallet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index 0a4ae8a..6aa1696 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -279,7 +279,7 @@ However, since real-world M doesn't have to be large, additional steps can be ta ### Why it's beneficial to include the commonly-known HKDF-based key complement -Theoretically coin blinding factors should never be revealed. However, if a coin blinding factor is leaked (for whatever reason), withouth the HKDF-based blinding factor it may compromise all the secret keys. +Theoretically coin blinding factors should never be revealed. However, if a coin blinding factor is leaked (for whatever reason), without the HKDF-based blinding factor it may compromise all the secret keys. Without the HKDF part, the coin blinding factor is: From 7a657b79737202d0bf951a418527731b326f94cb Mon Sep 17 00:00:00 2001 From: valdok Date: Sun, 28 Dec 2025 19:27:14 +0200 Subject: [PATCH 10/13] Update 0023-multisig-wallet, reworked initialization ceremony --- text/0023-multisig-wallet.md | 132 +++++++++++++++++++++++++---------- 1 file changed, 96 insertions(+), 36 deletions(-) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index 6aa1696..f827c54 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -24,61 +24,113 @@ Multisig wallet will instead rely on SSS to generate the keys. The BIP44 can sti ### Key concepts Here we'll define key terms and concept + - We'll operate on secp256k1 curve (the native for Grin). - **Secret key** - EC (elliptic curve) scalar - **Pubkey** - EC point (group element). - - We'll use the additive notation for the ECC operations (i.e. adding points, and multiplying points by scalars) - **Actor** - a user that co-owns a wallet. - - **Moniker** - a unique user name/alias, that the actor chooses for identification (such as `Alice`, `Bob`, and etc.) - - **Message authentication** + - **Address** - the Grin SlatepackAddress. Each actor will have the address for both identification, and communication (encryption of messages). + - Not that Grin Slatepack addresses are defined over a different EC: ed25519. - The protocol doesn't always require a secret P2P communication between individual actors, most messages are shared between all the actors and considered non-secret. However some messages must be protected against tampering. Hence we assume that each message broadcasted by an actor - is signed by its private key, and then verified by others vs its pubkey + **Communication** + The protocol requires a communication between the actors. Some messages must be sent secretly P2P, whereas the rest are "broadcasted", i.e. sent to all the actors. In either case, we assume there's the underlying mechanism for this. In particular we require the following: + - All the messages are protected against tampering + - Impersonation is not feasible, each message's sender can be verified + - P2P message contents are secret, i.e. only the recipient should be able to read it in plaintext. The messaging metadata (the even fact of communication, message size, etc.) is not secret. **Scalar derivation** We'll need a collision-resistant function to generate a scalar from arbitrary public arguments. Basically it's implemented via a hash function (such as SHA-256). However additional steps are required to make sure the result is a valid EC scalar (clamping). We'll call this function $Hash_s(msg)$ -**Moniker -> scalar function** -While actors use monikers for identification, the SSS operates on arguments in terms of EC scalars. Each actor will be assigned a scalar $x_i = Hash_s("actor-" | moniker_i)$. There should be no duplicates. In a highly unlikely case of collision, the actor will have to choose another moniker. - **Mutual antisymmetric secret** For each pair of actors $i \neq j$ we'll define this function: -$\delta(i,j,context) = Hash_s( DH(i,j) | context) \cdot (x_i - x_j)$ +$$ +\delta(i,j,context) = Hash_s( DH(i,j) | context) \cdot (x_i - x_j) +$$ + +whereas: +- $DH(i,j)$ stands for Diffie-Hellman shared secret (in terms of their SlatepackAddress) +- $context$ is arbitrary message +- $x_i$ is derived from the actor's address (more about this later) -whereas $DH(i,j)$ stands for Diffie-Hellman shared secret, $context$ is arbitrary message, and $x_i$ is derived from the actor's moniker. -Not that this function is antisymmetric: $\delta(i,j) + \delta(j,i) = 0$ +Note that this function is antisymmetric: $\delta(i,j) + \delta(j,i) = 0$ -### Wallet initialization/recovery +### Wallet initialization -In this process, M initial users initialize/restore the wallet +In this process, N users initialize the wallet -(1) Each actor generates (or restores) its master key $sk_i$ (perhaps derived from its private seed phrase), and then broadcasts a message with those fields: -- Pubkey: $P_i = G \cdot sk_i$ -- Moniker +(1) N initial actors decide to initialize/restore the wallet. They agree on M: the minimal quorum needed to build future transactions. -This message **must** be signed by the actor pubkey. Not only to protect against tampering, but also to prevent a rogue-key attack. +Each actor creates M pseudo-random initial coefficients (perhaps derived from its seed phrase). This information is broadcasted: +- M Commitments to the coefficients: $C_{i,m} = G \cdot\ r_{i,m}$ +- Commitment to its address: $Hash(addr_i)$ +- PoP (proof of possession) to the above commitments. Schnorr's signatures of its address commitment, signed by its secret coefficients $r_{i,m}$ -(2) After actors exhange this information, everyone verifies there're indeed M different actors, and there're no duplicates. Then the following SSS polynomial is defined: +(2) Each actor receives and verifies this information. The SSS polynomial is defined as the sum of the partial polynomials provided by N actors: $$ -sk(x) = \sum_{i=1}^{M} sk_i \cdot \prod_{i \neq j} \frac{x - x_j}{x_i - x_j} +sk(x) = \sum_{m=0}^M x^m \cdot \sum_{i=1}^N r_{i,m} = \sum_{m=0}^M x^m \cdot s_m $$ -Or, in terms of pubkeys: +or in terms of pubkeys: $$ -P(x) = \sum_{i=1}^{M} P_i \cdot \prod_{j \neq i} \frac{x - x_j}{x_i - x_j} = \sum_{n=0}^{M-1}S_n \cdot x^n +P(x) = \sum_{m=0}^M x^m \cdot \sum_{i=1}^N C_{i,m} = \sum_{m=0}^M x^m \cdot S_m $$ -Upon ritual completion, the public polynome coefficients { $S_n$ } become known to all the actors. +Note that the coefficients { $S_m$ } and the polynomial $P(x)$ are known, whereas { $s_m$ } are secret, and never computed in a plain form. -Finally each actor initalizes its multisig wallet. The coefficients { $\{ S_n \}$ } are saved, in addition to its secret key and the moniker. +Each validator broadcasts this: +- $addr_i$ - its address -(3) Coin blinding factor is defined according to this formula: +(3) Each actor receives and verifies this information. +- each other actor's address matches its previously-revealed commitment. +- There're no duplicates + +At this point the x-coordinate for each validator is computed: + +$$x_i = Hash_s("actor-" | addr_i)$$ + +Each actor computes ands sends **privately** the following partial shares to other validators: + +$$ +sk_{i,j} = \sum_{m=0}^M r_{i,m} \cdot x_j^m + \sum_{k \neq i} \delta(i,k, context | j) +$$ + +whereas $context$ stands for all the parameters that uniquely define this ceremony + +(4) Each actor that receives its designated partial shares finally calculates its share: + +$$ +sk_j = \sum_{i=1}^N sk_{i,j} = \sum_{i=1}^N \sum_{m=0}^M r_{i,m} \cdot x_j^m = sk(x_j) +$$ + +(we used the fact that all the $\delta(i,k, context | j)$ terms cancel-out) + +Each actor verifies that its share is correct: + +$$ +G \cdot sk_j = P(x_j) +$$ + +Finally the secret polynomial is redefined in terms of the secret shares. For each argument $x$ the polynomial is evaluated by a quorum Q of M actors as: + +$$ +sk(x) = \sum_{j \in Q} sk_j \cdot \prod_{i \in Q, i \neq j} \frac{x - x_i}{x_j - x_i} = \sum_j sk_{j,Q}(x) +$$ + +The terms $sk_{j,Q}(x)$ will be called **partial keys**. + +Once the ceremony is complete, each actor saves this information: +- Public polynomial coefficients: { $S_m$ } +- Its address: $addr_j$ +- Its share: $sk_j$ + + + +(5) Coin blinding factor is defined according to this formula: $$ x_{coin}(number, value) = Hash_s("coin-" | number | value) @@ -98,17 +150,17 @@ But the public key, and the coin commitment can be calculated be each actor indi ### Adding an actor -A quorum of M current actors can add an additional actor. For this the following steps are performed. +A quorum Q of M current actors can add an additional actor. For this the following steps are performed. -(1) New actor picks and shares a unique moniker. Unlike initial actors, that can generate/restore an arbitrary secret key, new actor's key is uniquely defined by its moniker. +(1) New actor picks and shares its unique address. The address must be unique (no duplicates with existing actors) -(2) Each actor computes ands sends **privately** the following key share: +(2) Each actor computes and sends **privately** the following key share: $$ -sk_{share_i} = sk_{i} \cdot \prod_{j \neq i} \frac{x_{new} - x_j}{x_i - x_j} + \sum_{j \neq i} \delta(i,j, context) +sk_{share_i} = sk_{i,Q}(x_{new}) + \sum_{j \in Q, j \neq i} \delta(i,j, context) $$ -whereas $context$ includes all the parameters of the ritual: $S_0$, $x_{new}$, and the selected quorum of M existing actors. This is to make sure $\delta(i,j, context)$ is unique in each ritual +whereas $context$ includes all the parameters of the ceremony: $S_0$, $x_{new}$, and the selected quorum Q. This is to make sure $\delta(i,j, context)$ is unique in each ceremony The new actor then performs the summation of all the shares: @@ -118,16 +170,22 @@ $$ Note that during this summation, all the $\delta(i,j)$ terms are cancelled-out. They are needed to blind each actor's secret key, but don't affect the sum of all the shares. -Finally the new actor verifies the correctness of its secret key, by checking if its appropriate pubkey sits on the same SSS polynome. +Finally the new actor verifies the correctness of its secret key, by checking if its appropriate pubkey sits on the same SSS polynomial. $$ -G \cdot sk_{new} = P_{x_{new}} = P(x_{new}) +G \cdot sk_{new} = P(x_{new}) $$ +### Wallet restoration + +If some actors lost access to their data, whereas at least M other actors retain their wallets - they can re-evaluate the shares of those actors by the procedure described above: "Adding an actor". +Otherwise, if there're fewer validators remaining, the wallet initialization procedure can be repeated from scratch. Since the whole procedure is deterministic, then the same set of N actors will yield the same secret polynomial and the same shares will be computed. +Otherwise, if there're less than M valid actors remain, and it's not possible to get the initial N actors to repeat the initialization ceremony - it won't be possible to restore the wallet. + ### Building a transaction -MW transaction consists of inputs, outputs at least one kernel. In order to build a valid transaction, a subset of M/N actors are selected. Each actor gets the transaction parameters: +MW transaction consists of inputs, outputs at least one kernel. In order to build a valid transaction, a quorum of M actors is selected. Each actor gets the transaction parameters: - list of input coins (coin number + value) - list of output coins (coin number + value) - any additional metadata (current blockchain height, fee, the identity of the tx peer, memo, etc.) @@ -220,6 +278,8 @@ This is why $\delta(i,j)$ terms are essential, they perform the perfect hiding o The only situation where the actor key can be compromised is where all M-1 other actors collude with the new one. But this essentially means that they together form a quorum of M malicious actors. And obviously a quorum of M actors can calculate and compromise any key. +**Note:** The same applies to the wallet initialization too. Although the partial shares are calculated differently, still each share is a linear combination of their secret coefficients { $r_{i,m}$ }, hence it should be masked by $\delta(i,j)$ terms. + ### UTXO and kernel signing, why rely on non-deterministic random It's generally considered better to rely on deterministic nonce generation scheme, such as RFC-6979. However such schemes can't be used as-is in multisig rituals. There're advanced schemes, such as those used in MuSig-DN, that rely on ZKP to verify that each actor generated its nonce deterministically. @@ -229,8 +289,8 @@ In either case, the general flow remains the same. And as long as the main principle holds: each nonce is used to only answer one challenge - the secret keys are safe. ### Rogue key attack -The only situation where such an attack is possible is during the wallet initialization by the quorum of M inital actors. If not mitigated, an actor can essentially cancel the keys of other actors, and gain an exclusive access. -As we mentioned, this is mitigated by the fact that all messages sent by the actors are supposed to be signed by them. +The only situation where such an attack is possible is during the wallet initialization, where each actor reveals broadcasts the commitments to its coefficients $C_{i,m} = G \cdot\ r_{i,m}$. If not mitigated, an actor can essentially cancel the keys of other actors, and gain an exclusive access. +As we mentioned, this is mitigated by mandatory inclusion of PoP (proof-of-possession) for each commitment. ### Why the coin value should be used together with the coin number in its key derivation @@ -257,7 +317,7 @@ $$ Note that if the attacker could derive blinding factors for arbitrary coin parameters, then it'd be a feasible task for a large enough set. This is known as the Generalized Birthday problem, or Wagner attack. -However, in our particular case, coin blinding factors are derived from the SSS polynome, whose coefficients are secret. +However, in our particular case, coin blinding factors are derived from the SSS polynomial, whose coefficients are secret. So, the only way for the attacker to find such sets is to try to find the sets where different powers of $x^n$ are equal for different sets. That is: From 22c68fccd1596eec90aa394c8cee2ffa13a7c4d9 Mon Sep 17 00:00:00 2001 From: valdok Date: Sun, 28 Dec 2025 20:12:06 +0200 Subject: [PATCH 11/13] Update 0023-multisig-wallet.md --- text/0023-multisig-wallet.md | 50 ++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index f827c54..58bd728 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -64,11 +64,15 @@ In this process, N users initialize the wallet (1) N initial actors decide to initialize/restore the wallet. They agree on M: the minimal quorum needed to build future transactions. Each actor creates M pseudo-random initial coefficients (perhaps derived from its seed phrase). This information is broadcasted: +- Its address: $addr_i$ - M Commitments to the coefficients: $C_{i,m} = G \cdot\ r_{i,m}$ -- Commitment to its address: $Hash(addr_i)$ - PoP (proof of possession) to the above commitments. Schnorr's signatures of its address commitment, signed by its secret coefficients $r_{i,m}$ -(2) Each actor receives and verifies this information. The SSS polynomial is defined as the sum of the partial polynomials provided by N actors: +(2) Each actor receives and verifies this information: +- All addresses must be distinct +- All Commitments must be valid (valid EC points), and appropriate PoP are valid as well + +The SSS polynomial is defined as the sum of the partial polynomials provided by N actors: $$ sk(x) = \sum_{m=0}^M x^m \cdot \sum_{i=1}^N r_{i,m} = \sum_{m=0}^M x^m \cdot s_m @@ -82,17 +86,12 @@ $$ Note that the coefficients { $S_m$ } and the polynomial $P(x)$ are known, whereas { $s_m$ } are secret, and never computed in a plain form. -Each validator broadcasts this: -- $addr_i$ - its address - -(3) Each actor receives and verifies this information. -- each other actor's address matches its previously-revealed commitment. -- There're no duplicates - At this point the x-coordinate for each validator is computed: $$x_i = Hash_s("actor-" | addr_i)$$ +All the { $x_i$ } must be distinct. Since the addresses of the actors are distinct, we assume the probability of collision of $x_i$ can be neglected. + Each actor computes ands sends **privately** the following partial shares to other validators: $$ @@ -101,7 +100,7 @@ $$ whereas $context$ stands for all the parameters that uniquely define this ceremony -(4) Each actor that receives its designated partial shares finally calculates its share: +(3) Each actor that receives its designated partial shares finally calculates its share: $$ sk_j = \sum_{i=1}^N sk_{i,j} = \sum_{i=1}^N \sum_{m=0}^M r_{i,m} \cdot x_j^m = sk(x_j) @@ -130,7 +129,7 @@ Once the ceremony is complete, each actor saves this information: -(5) Coin blinding factor is defined according to this formula: +(4) Coin blinding factor is defined according to this formula: $$ x_{coin}(number, value) = Hash_s("coin-" | number | value) @@ -280,6 +279,24 @@ The only situation where the actor key can be compromised is where all M-1 other **Note:** The same applies to the wallet initialization too. Although the partial shares are calculated differently, still each share is a linear combination of their secret coefficients { $r_{i,m}$ }, hence it should be masked by $\delta(i,j)$ terms. +### Why this initialization procedure + +In a previous variant of the proposal, during the initialization M initial actors contributed each a single point to the polynomial. And then, a polynomial of degree M-1 was fully defined by M distinct points. The remaining N-M validators got their shares evaluated later, by the "Add new actor" ceremony. + +In the current version, the scheme was changed, it's now equvalent to the standard Feldman DKG scheme. Its advantages are: +- All N actors take part in the initialization, and contribute to the randomness +- It's well-studied, and considered secure + +The drawback of this scheme, perhaps minor but should be mentioned, is that actors cannot restore their shares solely from their seed phrase. In the previous share M initial actors computed their shares in advance, solely from their seed phrases. In the current scheme this is not possible, because the polynomial structure and its value at any point is affected by all N actors. + +### Address grinding + +By grinding we assume that an actor can try different variants of its address "for free", until it gets a desired $x_i$. It's not fesible to reach a collision, whereas its $x_i$ will coincide with other actor's $x_j$, or with $x_coin(number, value)$, the argument of a coin blinding factor. However, it's believed that attacker _may_ obtain a desired $x$ to influence the algebraic structure of the Lagrance coefficients ( $\frac{x - x_i}{x_j - x_i}$ ). By such it won't be able to obtain the secret keys, but it can try to cause some correlation between different derived keys (which otherwise should be looking perfectly random). + +While there's no direct attacks, and it's more like a paranoid threat, still such things should be avoided nevertheless. If actor addresses are known in advance, then there's no problem. The problem may manifest if the last actor has the ability to observe all other addresses and then grind its own address. This situation should be avoided. + +If the latter is the case, then the initialization, and adding new actor schemes should be extended to an additional pre-step. First and foremost, all actors must send a commitment of their address. Only then, after all the commitments are exchanged, all the actors reveal their addresses. + ### UTXO and kernel signing, why rely on non-deterministic random It's generally considered better to rely on deterministic nonce generation scheme, such as RFC-6979. However such schemes can't be used as-is in multisig rituals. There're advanced schemes, such as those used in MuSig-DN, that rely on ZKP to verify that each actor generated its nonce deterministically. @@ -330,9 +347,16 @@ $$\forall\, n \in \{0, \dots, M-1\}$$ (This is like trying to solve M-1 generalized birthday problems simultaneously). -It's a known problem, called Prouhet-Tarry-Escott (PTE) problem. And it's considered generally infeasible to solve, especially for large M +It's a known problem, called Prouhet-Tarry-Escott (PTE) problem. And it's considered generally infeasible to solve, especially for large + +So, the first mitigation would be: M must be high enough (TBD). If the signature threshold (M/N) needs to be low, then the initialization scheme can be generalized in this way: +- Use higher polynomial degree +- Generate more shares +- Give each actor more shares + +In simple words: make each actor behave as several ones, by such artificially raise the number of shares and the degree of the polynomial. -However, since real-world M doesn't have to be large, additional steps can be taken by the actors to prevent the possibility of such attacks (though not sure if they're really needed). Those include the following: +Additional steps can be taken by the actors to prevent the possibility of such attacks (though not sure if they're really needed). Those include the following: - Ensure the being-spent coins actually exist and unspent (i.e. don't build transaction for non-existing inputs) - Stick to consequent coin number allocation. Each new coin number should not be completely random. - Don't create excessive number of outputs in a transaction. Normal transaction creates only a single output (per each side). From 18141b027553aad0c57483dc1ccce277bbb59048 Mon Sep 17 00:00:00 2001 From: valdok Date: Tue, 30 Dec 2025 12:04:55 +0200 Subject: [PATCH 12/13] 0023-multisig-wallet - fixed typos --- text/0023-multisig-wallet.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index 58bd728..61d77c5 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -9,7 +9,7 @@ Support an M/N multisig wallet. ## Motivation -The idea is to allow a wallet to be co-owned by several users, whereas a quorum of N/M is both required and sufficient to build a valid transaction (i.e. send or receive funds). +The idea is to allow a wallet to be co-owned by several users, whereas a quorum of M/N is both required and sufficient to build a valid transaction (i.e. send or receive funds). ## Reference-level explanation @@ -29,7 +29,7 @@ Here we'll define key terms and concept - **Pubkey** - EC point (group element). - **Actor** - a user that co-owns a wallet. - **Address** - the Grin SlatepackAddress. Each actor will have the address for both identification, and communication (encryption of messages). - - Not that Grin Slatepack addresses are defined over a different EC: ed25519. + - Note that Grin Slatepack addresses are defined over a different EC: ed25519. **Communication** The protocol requires a communication between the actors. Some messages must be sent secretly P2P, whereas the rest are "broadcasted", i.e. sent to all the actors. In either case, we assume there's the underlying mechanism for this. In particular we require the following: @@ -143,7 +143,7 @@ $$ whereas $number$ specifies the coin ID (number or any unique parameters), and ${S_0}$ is used as a seed to derive a complemental key via HKDF. While this term is known among actors, it's important to keep it, since it can increase the overall security (more about this later). -Note that the coin blinding factor can't be calculated by individual actors (since the function $sk_(x)$ is unknown). Actors can only calculate their shares to the coin blinding factor. +Note that the coin blinding factor can't be calculated by individual actors (since the function $sk(x)$ is unknown). Actors can only calculate their shares to the coin blinding factor. But the public key, and the coin commitment can be calculated be each actor individually. @@ -258,7 +258,7 @@ Here we'll consider an example where Alice sends funds to Bob, both are in fact - Bob side - A quorum of $M_B$ Bob's actors decides to accept the funds. They choose the coin number for the output UTXO - Each actor generates the appropriate nonces (2 for output UTXO, and 1 for kernel). - - Round 1: they reveal the images: T1,T2 for the UTXO, and the kernel noce image. + - Round 1: they reveal the images: T1,T2 for the UTXO, and the kernel nonce image. - Round 2: each actor receives the aggregates for the UTXO and the kernel. And reveals its partial signatures - The aggregated kernel, offset and Bob's UTXO is sent to Alice - Alice side @@ -291,7 +291,7 @@ The drawback of this scheme, perhaps minor but should be mentioned, is that acto ### Address grinding -By grinding we assume that an actor can try different variants of its address "for free", until it gets a desired $x_i$. It's not fesible to reach a collision, whereas its $x_i$ will coincide with other actor's $x_j$, or with $x_coin(number, value)$, the argument of a coin blinding factor. However, it's believed that attacker _may_ obtain a desired $x$ to influence the algebraic structure of the Lagrance coefficients ( $\frac{x - x_i}{x_j - x_i}$ ). By such it won't be able to obtain the secret keys, but it can try to cause some correlation between different derived keys (which otherwise should be looking perfectly random). +By grinding we assume that an actor can try different variants of its address "for free", until it gets a desired $x_i$. It's not fesible to reach a collision, whereas its $x_i$ will coincide with other actor's $x_j$, or with $x_{coin}(number, value)$, the argument of a coin blinding factor. However, it's believed that attacker _may_ obtain a desired $x$ to influence the algebraic structure of the Lagrance coefficients ( $\frac{x - x_i}{x_j - x_i}$ ). By such it won't be able to obtain the secret keys, but it can try to cause some correlation between different derived keys (which otherwise should be looking perfectly random). While there's no direct attacks, and it's more like a paranoid threat, still such things should be avoided nevertheless. If actor addresses are known in advance, then there's no problem. The problem may manifest if the last actor has the ability to observe all other addresses and then grind its own address. This situation should be avoided. @@ -315,14 +315,14 @@ After the agreed transaction is built and signed by the actors, a malicious acto Suppose a multisig wallet owns two coins, with values $V1 < V2$. There's a decision to spend the coin with value $V1$ in a transaction. It's collectively built and signed, but then a malicious actor changes the input to $V2$, and appends its UTXO that absorbs the value $V2-V1$. -Actions such as replacing coins are generally not possible, because different coins have different blinding factors, and it's not feasible to build a valid transaction when the blinding factor balance isn't compensated. But what if rgw attacker can manipulate inputs and outputs such that the **resulting blinding factor balance is unchanged**? +Actions such as replacing coins are generally not possible, because different coins have different blinding factors, and it's not feasible to build a valid transaction when the blinding factor balance isn't compensated. But what if the attacker can manipulate inputs and outputs such that the **resulting blinding factor balance is unchanged**? Coins with different numbers (i.e. IDs) will have different blinding factors. But what if a wallet owns several coins with different values but the same number? Normally actors should not take part in UTXO creation with coin number that was already used. But the situation may be confusing because of the blockchain state volatility. There can be potential reorgs, whereas transactions may be reverted, and then, after some time, included again in a block. By such it's theoretically possible the wallet will own several coins with the same ID, but different values. If the same blinding factor is used in all of them, then it's trivial to replace them in an already-built transaction. -**Mitigation:** include the coin value in the blidning factor derivation too. +**Mitigation:** include the coin value in the blinding factor derivation too. ### Wagner attack, Prouhet-Tarry-Escott (PTE) problem @@ -347,7 +347,7 @@ $$\forall\, n \in \{0, \dots, M-1\}$$ (This is like trying to solve M-1 generalized birthday problems simultaneously). -It's a known problem, called Prouhet-Tarry-Escott (PTE) problem. And it's considered generally infeasible to solve, especially for large +It's a known problem, called Prouhet-Tarry-Escott (PTE) problem. And it's considered generally infeasible to solve, especially for large M. So, the first mitigation would be: M must be high enough (TBD). If the signature threshold (M/N) needs to be low, then the initialization scheme can be generalized in this way: - Use higher polynomial degree From c2bb6b2f04e1d856f1708be6e8db791caad90877 Mon Sep 17 00:00:00 2001 From: valdok Date: Thu, 15 Jan 2026 15:27:35 +0200 Subject: [PATCH 13/13] Update 0023-multisig-wallet.md remove \delta(i,j) for init ceremony, not needed --- text/0023-multisig-wallet.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/text/0023-multisig-wallet.md b/text/0023-multisig-wallet.md index 61d77c5..5b2f6d7 100644 --- a/text/0023-multisig-wallet.md +++ b/text/0023-multisig-wallet.md @@ -95,19 +95,15 @@ All the { $x_i$ } must be distinct. Since the addresses of the actors are distin Each actor computes ands sends **privately** the following partial shares to other validators: $$ -sk_{i,j} = \sum_{m=0}^M r_{i,m} \cdot x_j^m + \sum_{k \neq i} \delta(i,k, context | j) +sk_{i,j} = \sum_{m=0}^M r_{i,m} \cdot x_j^m $$ -whereas $context$ stands for all the parameters that uniquely define this ceremony - (3) Each actor that receives its designated partial shares finally calculates its share: $$ sk_j = \sum_{i=1}^N sk_{i,j} = \sum_{i=1}^N \sum_{m=0}^M r_{i,m} \cdot x_j^m = sk(x_j) $$ -(we used the fact that all the $\delta(i,k, context | j)$ terms cancel-out) - Each actor verifies that its share is correct: $$ @@ -277,8 +273,6 @@ This is why $\delta(i,j)$ terms are essential, they perform the perfect hiding o The only situation where the actor key can be compromised is where all M-1 other actors collude with the new one. But this essentially means that they together form a quorum of M malicious actors. And obviously a quorum of M actors can calculate and compromise any key. -**Note:** The same applies to the wallet initialization too. Although the partial shares are calculated differently, still each share is a linear combination of their secret coefficients { $r_{i,m}$ }, hence it should be masked by $\delta(i,j)$ terms. - ### Why this initialization procedure In a previous variant of the proposal, during the initialization M initial actors contributed each a single point to the polynomial. And then, a polynomial of degree M-1 was fully defined by M distinct points. The remaining N-M validators got their shares evaluated later, by the "Add new actor" ceremony.