From eac8232b56b0091269c9556491ac9354d20ffa18 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Sun, 9 Oct 2022 18:25:38 -0600 Subject: [PATCH 01/33] add tx_summary_digest proposal --- text/0050-tx-summary-digest.md | 204 +++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 text/0050-tx-summary-digest.md diff --git a/text/0050-tx-summary-digest.md b/text/0050-tx-summary-digest.md new file mode 100644 index 00000000..20033aa7 --- /dev/null +++ b/text/0050-tx-summary-digest.md @@ -0,0 +1,204 @@ +- Feature Name: tx_summary_digest +- Start Date: 2022-10-08 +- MCIP PR: [mobilecoinfoundation/mcips#0050](https://github.com/mobilecoinfoundation/mcips/pull/0050) +- Tracking Issue: [mobilecoinfoundation/mobilecoin#2686](https://github.com/mobilecoinfoundation/mobilecoin/issues/2686) + +# Summary +[summary]: #summary + +Introduce an object called `TxSummary` which is significantly smaller than a `Tx`, +but which with small additional data can be used to verify the values of inputs +and outputs, and the destinations of the outputs, in a given `Tx`. + +Where previously the `extended_message_digest` is signed by Ring MLSAGs +in a transaction, now a new digest formed using that digest and the `TxSummary` will +be signed instead. + +# Motivation +[motivation]: #motivation + +Hardware wallets such as Ledger have an expectation that when the user signs a +transaction, the device can display information about how much money will be sent +to what addresses as a result of this transaction, and that the device can verify +that this information is correct. + +However, with the status quo, the only way that this can be accomplished is to put +the entire `Tx` on the device so that it can verify the `extended_message_digest`, +because the `extended_message_digest` is the only thing that connects the `MLSAG` +that the device is signing to the rest of the `Tx`. + +This increases the amount of data that has to be sent to the device from a few kb +to `> 100kb` in the worst case. This is because Merkle proofs are each e.g. 40 bytes +per merkle element and with a height of 20-30, so they may end up being 1 KB each. +Then, there is a merkle proof for each `TxIn` (at most 16) and each mixin (11 per `TxIn`). + +Having to transfer this much data to a tiny device will slow down the user experience +noticeably, and will greatly increase the complexity of implementation, because the device +has much less memory than this and would have to use some kind of "windowing" strategy +to compute the hash. + +On the other hand, if the digest that the Ring MLSAGs sign is changed as proposed, then +we only need to send 32 bytes followed by the `TxSummary` to prove to the device where +the digest that the MLSAG's are signing comes from, and so what the outcome of the `Tx` is. +So we can avoid sending all merkle proofs, bulletproofs, encrypted fog hints, memos, etc. +and reduce the traffic with the device by perhaps a factor of 10 or so in the worst case, +as well as reducing the implementation complexity. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +A `TxSummary` is an object much like the `TxPrefix`, but where instead of the `TxIn` +objects, the corresponding `pseudo_output_commitments` are stored. + +There is exactly one possible `TxSummary` for a given `Tx`. + +The `TxSummary` contains: +* The list of outputs (omitting "extra" parts like encrypted fog hint and encrypted memo). +* The list of pseudo_output_commitments (commitments to the values of the true inputs) + * Any input rules associated to these inputs (if they are [MCIP 42](https://github.com/mobilecoinfoundation/mcips/pull/42) signed contingent inputs) +* The fee and fee token id +* The tombstone block + +During transaction construction, the signer computes the extended message digest as before, +but now creates a merlin transcript using that 32-byte digest, followed by digesting the +`TxSummary`. The MLSAG's (except for SCIs) will sign 32-bytes extracted from this digest. +The verifier similarly computes this +`extended-message-and-tx-summary digest` and verifies that the MLSAGs sign this. + +When a hardware wallet is asked to sign an MLSAG, we can give it now the `extended_message_digest` +and the `TxSummary`, and it can compute the appropriate digest from this for the MLSAG to sign. + +Additionally, we can provide it the `TxSummaryUnblindingData`, which inclues: +* For each pseudo-output-commitment, the amount (value and token id), and blinding factor. +* For each output, the target public address, the amount, and the `tx_private_key`, unless + it is part of an SCI. In that case we can unblind it using the amount shared secret in the + SCI input rules to find it's value, and we can't know + exactly what address is the destination, except that it's associated to the SCI. +* The block version these outputs all targetted. + +These data are not very large and allow the hardware wallet to verify the amounts of all +inputs and outputs in the `TxSummary` and to verify the destination of each output. + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +The `TxSummary` is a new object with the following schema, which is constructed +before signing a `Tx`. + +```mermaid +classDiagram +direction BT +TxOutSummary --> TxSummary +TxInSummary --> TxSummary +TxSummary: Vec~TxOutSummary~ outputs +TxSummary: Vec~TxInSummary~ inputs +TxSummary: uint64 fee_value +TxSummary: uint64 fee_token_id +TxSummary: uint64 tombstone_block +TxSummary: new(&TxPrefix, &[TxInSummary]) +TxOutSummary: CompressedRistrettoPublic public_key +TxOutSummary: CompressedRistrettoPublic target_key +TxOutSummary: MaskedAmount masked_amount +TxOutSummary: from(&TxOut) +TxInSummary: CompressedCommitment pseudo_output_commitment +TxInSummary: Option~InputRules~ input_rules +``` + +In block version 2, MLSAG's (other than the MCIP 42 Signed Contingent Inputs) sign +the `extended_message_digest`. We propose that they should now sign the `extended_message_and_tx_summary_digest`, +which is defined as follows, using the `mc-crypto-digestible` scheme with a Merlin transcript: + +```rust +let mut transcript = + MerlinTranscript::new(EXTENDED_MESSAGE_AND_TX_SUMMARY_DOMAIN_TAG.as_bytes()); +extended_message.append_to_transcript(b"extended_message", &mut transcript); +tx_summary.append_to_transcript(b"tx_summary", &mut transcript); + +let mut extended_message_and_tx_summary_digest = [0u8; 32]; +transcript.extract_digest(&mut extended_message_and_tx_summary_digest); +``` + +This digest is computable given only the 32 byte extended message digest, and the +`TxSummary`, which are together much smaller than an entire `Tx`. + +A hardware wallet which is asked to sign an MLSAG can expect to see that 32 byte digest +and the `TxSummary`. From a security point of view, it can know that it is intractable +for someone to find a different `TxSummary` that produces the same `extended_message_and_tx_summary` +domain tag. The hardware wallet also knows how the validators will compute the `extended_message_and_tx_summary` +based on the `Tx`, and knows that it is infeasible for anyone to find another `Tx` that has the same digest here. + +A hardware wallet can also expect to be supplied with the `TxSummaryUnblindingData` which allows it to see +as much information as possible about where funds are coming from and where they are going in the `Tx`. + +```mermaid +classDiagram +direction BT +TxOutUnblindingData --> TxSummaryUnblindingData +TxSummaryUnblindingData: uint32 block_version +TxSummaryUnblindingData: Vec~UnmaskedAmount~ inputs +TxSummaryUnblindingData: Vec~TxOutUnblindingData~ outputs +TxOutUnblindingData: UnmaskedAmount amount +TxOutUnblindingData: Option address +``` + +# Drawbacks +[drawbacks]: #drawbacks + +The main reason not to do this is that it somewhat increases the complexity of transaction validation. + +It is also inelegant in that we hash a bunch of information into the extended message (by hashing the `TxPrefix`), +and then we hash it again via the `TxSummary`, because the `TxSummary` contains some of this information duplicated. + +# Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +Although doing this increases the complexity of transaction validation, not doing it considerably increases +the complexity of hardware wallet implementation and could delay the ship date of hardware wallet support. + +Although it is inelegant to hash a bunch of stuff a second time, in practical terms, the cost of doing this is very low. + +There are many things that are inelegant about our current `Tx` structure. It is inelegant that the `TxPrefix` hash is not +the only thing that MLSAG's sign and that extra stuff from `SignatureRctBulletproofs` is signed. It would be better if this +`TxSummary` object *were* the `TxPrefix` to some extent, and the merkle proofs, bulletproofs, and other extra stuff were +digested before that. Then we would not need to have an extra round of hashing things at the end. + +However, we do not propose at this time to completely change the `Tx` structure to fix these issues, as this would be +a very complicated breaking change. + +Instead, we view this current proposal as the simplest and most straightforward proposal that will meet the needs of +hardware wallets and help them to avoid complexities around streaming too much data and having to create a state machine to +compute a proper merlin digest of the entire `Tx` object, which would also make the user experience significantly slower. + +## SCI support, definition of `TxSummaryUnblindingData`. + +We have tried to future-proof this design against [MCIP 42](https://github.com/mobilecoinfoundation/mcips/pull/42) Signed Contingent Inputs being present in the `Tx`. +However, these cannot even be used until block version 3, and may not be in common use at the time that hardware wallet support +is actually shipped. + +It may be that hardware wallets will initially cut scope and not seek to support that feature. Then, they could cut the `InputRules` +from the `TxInSummary` and they could assume that `address` is mandatory in `TxOutSummary::address`. + +They might also seek to compress or remove redundancy in some of these structures. Strictly speaking, the `TxSummaryUnblindingData` +has no connection to MobileCoin protocol rules, it's rather a detail of the hardware wallets, so it is not necessary to create an +MCIP for this. + +We view it as the prerogative of hardware wallets to define their own wire format as they see fit and carry out whatever compression / improvements they +think are appropriate. It seems worthwhile to define a "proof of concept" `TxSummaryUnblindingData` object and show how it can be validated +against a `TxSummary` to provide at least a baseline or starting point for such projects, since if there is actually a defect in the +design that prevents `TxSummary` from being unblinded effectively, it would defeat the purpose of this improvement proposal. + +# Prior art +[prior-art]: #prior-art + +None that we know of. + +# Unresolved questions +[unresolved-questions]: #unresolved-questions + +None at this time. + +# Future possibilities +[future-possibilities]: #future-possibilities + +If more fields are added to `Tx` or `TxPrefix` that would be interesting for hardware wallets to have visibility on, we should also add them +to `TxSummary`. From d97018a75e9a6b50d3a25dfd2169c8b739e1bb2a Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Sun, 9 Oct 2022 19:28:31 -0600 Subject: [PATCH 02/33] fixup --- text/{0050-tx-summary-digest.md => 0052-tx-summary-digest.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename text/{0050-tx-summary-digest.md => 0052-tx-summary-digest.md} (99%) diff --git a/text/0050-tx-summary-digest.md b/text/0052-tx-summary-digest.md similarity index 99% rename from text/0050-tx-summary-digest.md rename to text/0052-tx-summary-digest.md index 20033aa7..7c445579 100644 --- a/text/0050-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -1,6 +1,6 @@ - Feature Name: tx_summary_digest - Start Date: 2022-10-08 -- MCIP PR: [mobilecoinfoundation/mcips#0050](https://github.com/mobilecoinfoundation/mcips/pull/0050) +- MCIP PR: [mobilecoinfoundation/mcips#0052](https://github.com/mobilecoinfoundation/mcips/pull/0052) - Tracking Issue: [mobilecoinfoundation/mobilecoin#2686](https://github.com/mobilecoinfoundation/mobilecoin/issues/2686) # Summary From af8740f8c808e73a80e094552f608f7262cf99bd Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Mon, 10 Oct 2022 10:26:22 -0600 Subject: [PATCH 03/33] fixups --- text/0052-tx-summary-digest.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 7c445579..575d69c7 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -8,7 +8,8 @@ Introduce an object called `TxSummary` which is significantly smaller than a `Tx`, but which with small additional data can be used to verify the values of inputs -and outputs, and the destinations of the outputs, in a given `Tx`. +and outputs, and the destinations of the outputs, when a device is asked to sign +a `RingMLSAG` for a new transaction. Where previously the `extended_message_digest` is signed by Ring MLSAGs in a transaction, now a new digest formed using that digest and the `TxSummary` will @@ -138,22 +139,28 @@ TxSummaryUnblindingData: uint32 block_version TxSummaryUnblindingData: Vec~UnmaskedAmount~ inputs TxSummaryUnblindingData: Vec~TxOutUnblindingData~ outputs TxOutUnblindingData: UnmaskedAmount amount -TxOutUnblindingData: Option address +TxOutUnblindingData: Option~PublicAddress~ address ``` +Strictly speaking, the `TxSummaryUnblindingData` is not part of the MobileCoin network's protocol rules, +it's rather a detail of the hardware wallets, and they might choose not to use this schema and do their +own thing. However, it is useful as a proof of concept, to validate that the `TxSummary` design does +actually achieve the goals we set out. This at least provides a starting point for hardware wallet projects. + # Drawbacks [drawbacks]: #drawbacks The main reason not to do this is that it somewhat increases the complexity of transaction validation. +It introduces more types and more schemas, and they have only niche use-cases. It is also inelegant in that we hash a bunch of information into the extended message (by hashing the `TxPrefix`), -and then we hash it again via the `TxSummary`, because the `TxSummary` contains some of this information duplicated. +and then we hash it again via the `TxSummary`. The `TxSummary` contains much of the same information as the `TxPrefix`. # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives Although doing this increases the complexity of transaction validation, not doing it considerably increases -the complexity of hardware wallet implementation and could delay the ship date of hardware wallet support. +the complexity of hardware wallet implementation and could delay the ship date of practical hardware wallet support. Although it is inelegant to hash a bunch of stuff a second time, in practical terms, the cost of doing this is very low. @@ -178,14 +185,8 @@ is actually shipped. It may be that hardware wallets will initially cut scope and not seek to support that feature. Then, they could cut the `InputRules` from the `TxInSummary` and they could assume that `address` is mandatory in `TxOutSummary::address`. -They might also seek to compress or remove redundancy in some of these structures. Strictly speaking, the `TxSummaryUnblindingData` -has no connection to MobileCoin protocol rules, it's rather a detail of the hardware wallets, so it is not necessary to create an -MCIP for this. - We view it as the prerogative of hardware wallets to define their own wire format as they see fit and carry out whatever compression / improvements they -think are appropriate. It seems worthwhile to define a "proof of concept" `TxSummaryUnblindingData` object and show how it can be validated -against a `TxSummary` to provide at least a baseline or starting point for such projects, since if there is actually a defect in the -design that prevents `TxSummary` from being unblinded effectively, it would defeat the purpose of this improvement proposal. +think are appropriate. The `TxSummaryUnblindingData` schema is only meant as a proof of concept and a starting point for such projects. # Prior art [prior-art]: #prior-art From ccad2163e4458f264dc8555be0ff71a46b12edcf Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 11 Oct 2022 10:08:41 -0600 Subject: [PATCH 04/33] fixups, more diagrams --- text/0052-tx-summary-digest.md | 47 ++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 575d69c7..796ca176 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -56,7 +56,7 @@ There is exactly one possible `TxSummary` for a given `Tx`. The `TxSummary` contains: * The list of outputs (omitting "extra" parts like encrypted fog hint and encrypted memo). * The list of pseudo_output_commitments (commitments to the values of the true inputs) - * Any input rules associated to these inputs (if they are [MCIP 42](https://github.com/mobilecoinfoundation/mcips/pull/42) signed contingent inputs) + * Any input rules associated to these inputs (if they are [MCIP 31](https://github.com/mobilecoinfoundation/mcips/pull/31) signed contingent inputs) * The fee and fee token id * The tombstone block @@ -83,6 +83,43 @@ inputs and outputs in the `TxSummary` and to verify the destination of each outp # Reference-level explanation [reference-level-explanation]: #reference-level-explanation +In block version 0, the Ring MLSAG's sign the "extended message" computed roughly as follows: + +```mermaid +graph TB +A[TxPrefix] -->|merlin| B[message] +B --> M +C[pseudo_output_commitments] --> M +D[range_proofs] --> M +M[concatenation] --> N[extended message (many bytes)] +``` + +In block version 2, we changed this (in [MCIP 25](https://github.com/mobilecoinfoundation/mcips/pull/25)) so that the Ring MLSAG's sign the +"extended message digest" which is computed roughly as follows: + +```mermaid +graph TB +A[TxPrefix] -->|merlin| B[message] +B --> M +C[pseudo_output_commitments] --> M +D[range_proofs] --> M +M[merlin] --> N[extended message digest (32 bytes)] +``` + +In the current proposal, we propose that in block version 3 they should sign the following digest: + +```mermaid +graph TB +A[TxPrefix] -->|merlin| B[message] +B --> M +C[pseudo_output_commitments] --> M +D[range_proofs] --> M +M[merlin] --> N[extended message digest (32 bytes)] +N --> P +O[TxSummary] --> P +P[merlin] --> Q[extended message and tx summary digest (32 bytes)] +``` + The `TxSummary` is a new object with the following schema, which is constructed before signing a `Tx`. @@ -105,7 +142,7 @@ TxInSummary: CompressedCommitment pseudo_output_commitment TxInSummary: Option~InputRules~ input_rules ``` -In block version 2, MLSAG's (other than the MCIP 42 Signed Contingent Inputs) sign +In block version 2, MLSAG's (other than the [MCIP 31](https://github.com/mobilecoinfoundation/mcips/pull/31) Signed Contingent Inputs) sign the `extended_message_digest`. We propose that they should now sign the `extended_message_and_tx_summary_digest`, which is defined as follows, using the `mc-crypto-digestible` scheme with a Merlin transcript: @@ -178,15 +215,15 @@ compute a proper merlin digest of the entire `Tx` object, which would also make ## SCI support, definition of `TxSummaryUnblindingData`. -We have tried to future-proof this design against [MCIP 42](https://github.com/mobilecoinfoundation/mcips/pull/42) Signed Contingent Inputs being present in the `Tx`. +We have tried to future-proof this design against [MCIP 31](https://github.com/mobilecoinfoundation/mcips/pull/31) Signed Contingent Inputs being present in the `Tx`. However, these cannot even be used until block version 3, and may not be in common use at the time that hardware wallet support is actually shipped. It may be that hardware wallets will initially cut scope and not seek to support that feature. Then, they could cut the `InputRules` -from the `TxInSummary` and they could assume that `address` is mandatory in `TxOutSummary::address`. +from the `TxInSummary`, (or rather, return an error if they are present) and they could assume that `address` is mandatory in `TxOutSummary::address`. We view it as the prerogative of hardware wallets to define their own wire format as they see fit and carry out whatever compression / improvements they -think are appropriate. The `TxSummaryUnblindingData` schema is only meant as a proof of concept and a starting point for such projects. +think are appropriate. The `TxSummaryUnblindingData` schema is only meant as a proof of concept. # Prior art [prior-art]: #prior-art From 797f0432b65d4038450834e7fbb1499aacc9eebd Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 11 Oct 2022 10:09:30 -0600 Subject: [PATCH 05/33] fixup --- text/0052-tx-summary-digest.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 796ca176..8b2134d6 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -91,7 +91,8 @@ A[TxPrefix] -->|merlin| B[message] B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M -M[concatenation] --> N[extended message (many bytes)] +M[concatenation] --> N +N[extended message (many bytes)] ``` In block version 2, we changed this (in [MCIP 25](https://github.com/mobilecoinfoundation/mcips/pull/25)) so that the Ring MLSAG's sign the @@ -103,7 +104,8 @@ A[TxPrefix] -->|merlin| B[message] B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M -M[merlin] --> N[extended message digest (32 bytes)] +M[merlin] --> N +N[extended message digest (32 bytes)] ``` In the current proposal, we propose that in block version 3 they should sign the following digest: @@ -114,8 +116,8 @@ A[TxPrefix] -->|merlin| B[message] B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M -M[merlin] --> N[extended message digest (32 bytes)] -N --> P +M[merlin] --> N +N[extended message digest (32 bytes)] --> P O[TxSummary] --> P P[merlin] --> Q[extended message and tx summary digest (32 bytes)] ``` From ded6b3773ca64aa6ac7d02748b13cabed8effe09 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 11 Oct 2022 10:11:49 -0600 Subject: [PATCH 06/33] fixup --- text/0052-tx-summary-digest.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 8b2134d6..71a8969c 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -92,7 +92,7 @@ B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M M[concatenation] --> N -N[extended message (many bytes)] +N[[extended message (many bytes)]] ``` In block version 2, we changed this (in [MCIP 25](https://github.com/mobilecoinfoundation/mcips/pull/25)) so that the Ring MLSAG's sign the @@ -105,7 +105,7 @@ B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M M[merlin] --> N -N[extended message digest (32 bytes)] +N[[extended message digest (32 bytes)]] ``` In the current proposal, we propose that in block version 3 they should sign the following digest: @@ -117,9 +117,10 @@ B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M M[merlin] --> N -N[extended message digest (32 bytes)] --> P +N[[extended message digest (32 bytes)]] --> P O[TxSummary] --> P -P[merlin] --> Q[extended message and tx summary digest (32 bytes)] +P[merlin] --> Q +Q[[extended message and tx summary digest (32 bytes)]] ``` The `TxSummary` is a new object with the following schema, which is constructed From d74895d90390a779047c2702c0afa58f5bd092a4 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 11 Oct 2022 10:14:41 -0600 Subject: [PATCH 07/33] fixup mermaid --- text/0052-tx-summary-digest.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 71a8969c..f8966ac2 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -92,7 +92,7 @@ B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M M[concatenation] --> N -N[[extended message (many bytes)]] +N[[extended_message -many bytes-]] ``` In block version 2, we changed this (in [MCIP 25](https://github.com/mobilecoinfoundation/mcips/pull/25)) so that the Ring MLSAG's sign the @@ -105,7 +105,7 @@ B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M M[merlin] --> N -N[[extended message digest (32 bytes)]] +N[[extended_message_digest -32 bytes-]] ``` In the current proposal, we propose that in block version 3 they should sign the following digest: @@ -117,10 +117,10 @@ B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M M[merlin] --> N -N[[extended message digest (32 bytes)]] --> P +N[[extended_message_digest -32 bytes-]] --> P O[TxSummary] --> P P[merlin] --> Q -Q[[extended message and tx summary digest (32 bytes)]] +Q[[extended_message_and_tx_summary_digest -32 bytes-]] ``` The `TxSummary` is a new object with the following schema, which is constructed From 46a91bf92ab9e87dfe4e6a3418dabba4f7960f90 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 11 Oct 2022 10:33:32 -0600 Subject: [PATCH 08/33] restructure the reference level part --- text/0052-tx-summary-digest.md | 47 ++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index f8966ac2..7239abb2 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -108,7 +108,9 @@ M[merlin] --> N N[[extended_message_digest -32 bytes-]] ``` -In the current proposal, we propose that in block version 3 they should sign the following digest: +We propose that in block version 3, Ring MLSAGs (other than the [MCIP 31](https://github.com/mobilecoinfoundation/mcips/pull/31) Signed Contingent Inputs) +should now sign the `extended_message_and_tx_summary_digest`, +which is computed roughly as follows: ```mermaid graph TB @@ -123,8 +125,22 @@ P[merlin] --> Q Q[[extended_message_and_tx_summary_digest -32 bytes-]] ``` -The `TxSummary` is a new object with the following schema, which is constructed -before signing a `Tx`. +Example code computing this new digest in a concrete way using the `mc-crypto-digestible` crate: + +```rust +let mut transcript = + MerlinTranscript::new(EXTENDED_MESSAGE_AND_TX_SUMMARY_DOMAIN_TAG.as_bytes()); +extended_message.append_to_transcript(b"extended_message", &mut transcript); +tx_summary.append_to_transcript(b"tx_summary", &mut transcript); + +let mut extended_message_and_tx_summary_digest = [0u8; 32]; +transcript.extract_digest(&mut extended_message_and_tx_summary_digest); +``` + +This digest is computable given only the 32 byte `extended_message_digest`, and the +`TxSummary`, which are together much smaller than an entire `Tx`. + +The `TxSummary` is a new object with the following schema. ```mermaid classDiagram @@ -145,25 +161,11 @@ TxInSummary: CompressedCommitment pseudo_output_commitment TxInSummary: Option~InputRules~ input_rules ``` -In block version 2, MLSAG's (other than the [MCIP 31](https://github.com/mobilecoinfoundation/mcips/pull/31) Signed Contingent Inputs) sign -the `extended_message_digest`. We propose that they should now sign the `extended_message_and_tx_summary_digest`, -which is defined as follows, using the `mc-crypto-digestible` scheme with a Merlin transcript: - -```rust -let mut transcript = - MerlinTranscript::new(EXTENDED_MESSAGE_AND_TX_SUMMARY_DOMAIN_TAG.as_bytes()); -extended_message.append_to_transcript(b"extended_message", &mut transcript); -tx_summary.append_to_transcript(b"tx_summary", &mut transcript); - -let mut extended_message_and_tx_summary_digest = [0u8; 32]; -transcript.extract_digest(&mut extended_message_and_tx_summary_digest); -``` - -This digest is computable given only the 32 byte extended message digest, and the -`TxSummary`, which are together much smaller than an entire `Tx`. - A hardware wallet which is asked to sign an MLSAG can expect to see that 32 byte digest -and the `TxSummary`. From a security point of view, it can know that it is intractable +and the `TxSummary`. + +**Security**: +From a security point of view, it can know that it is intractable for someone to find a different `TxSummary` that produces the same `extended_message_and_tx_summary` domain tag. The hardware wallet also knows how the validators will compute the `extended_message_and_tx_summary` based on the `Tx`, and knows that it is infeasible for anyone to find another `Tx` that has the same digest here. @@ -185,7 +187,8 @@ TxOutUnblindingData: Option~PublicAddress~ address Strictly speaking, the `TxSummaryUnblindingData` is not part of the MobileCoin network's protocol rules, it's rather a detail of the hardware wallets, and they might choose not to use this schema and do their own thing. However, it is useful as a proof of concept, to validate that the `TxSummary` design does -actually achieve the goals we set out. This at least provides a starting point for hardware wallet projects. +actually achieve the goals we set out. This at least provides a starting point for hardware wallet projects +that does not involve sending the entire `Tx`. # Drawbacks [drawbacks]: #drawbacks From 3a4b2277dc9daaff9d7f9f3c839ad5578aa55cdd Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 11 Oct 2022 10:38:50 -0600 Subject: [PATCH 09/33] improve text --- text/0052-tx-summary-digest.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 7239abb2..af40a0f6 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -165,10 +165,15 @@ A hardware wallet which is asked to sign an MLSAG can expect to see that 32 byte and the `TxSummary`. **Security**: -From a security point of view, it can know that it is intractable -for someone to find a different `TxSummary` that produces the same `extended_message_and_tx_summary` -domain tag. The hardware wallet also knows how the validators will compute the `extended_message_and_tx_summary` +From a security point of view, the hardware wallet can know that it is intractable +for someone to find a different `TxSummary` that produces the same `extended_message_and_tx_summary` digest, +so if it signs the MLSAG, this is the only thing that it can be committing to. +The hardware wallet also knows how the validators will compute the `extended_message_and_tx_summary` digest based on the `Tx`, and knows that it is infeasible for anyone to find another `Tx` that has the same digest here. +So, an attacker (on the computer) could give the device an improperly formed `TxSummary` and lie to the device +this way, but the attacker will not be able to get consensus to accept those signatures. The device therefore +knows that the either the `TxSummary` is accurate, or it's signature doesn't matter because the `Tx` will not +be accepted. A hardware wallet can also expect to be supplied with the `TxSummaryUnblindingData` which allows it to see as much information as possible about where funds are coming from and where they are going in the `Tx`. From 0e4bb482eaa8daabdba9d9eae60b5fc004137bd8 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 11 Oct 2022 17:08:46 -0600 Subject: [PATCH 10/33] improve mermaid annotations --- text/0052-tx-summary-digest.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index af40a0f6..3fc700bf 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -87,12 +87,12 @@ In block version 0, the Ring MLSAG's sign the "extended message" computed roughl ```mermaid graph TB -A[TxPrefix] -->|merlin| B[message] +A[TxPrefix] -->|merlin| B[[message -32 bytes-]] B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M M[concatenation] --> N -N[[extended_message -many bytes-]] +N[extended_message -many bytes-] ``` In block version 2, we changed this (in [MCIP 25](https://github.com/mobilecoinfoundation/mcips/pull/25)) so that the Ring MLSAG's sign the @@ -100,7 +100,7 @@ In block version 2, we changed this (in [MCIP 25](https://github.com/mobilecoinf ```mermaid graph TB -A[TxPrefix] -->|merlin| B[message] +A[TxPrefix] -->|merlin| B[[message -32 bytes-]] B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M @@ -114,7 +114,7 @@ which is computed roughly as follows: ```mermaid graph TB -A[TxPrefix] -->|merlin| B[message] +A[TxPrefix] -->|merlin| B[[message -32 bytes-]] B --> M C[pseudo_output_commitments] --> M D[range_proofs] --> M From f1f67e597189c92c15405e74d10de624d74fbb28 Mon Sep 17 00:00:00 2001 From: isis lovecruft <79881025+isis-mc@users.noreply.github.com> Date: Mon, 17 Oct 2022 12:04:04 -0700 Subject: [PATCH 11/33] Apply suggestions from code review Incorporate several of @remoun's and @nick-mobilecoin's suggestions. Co-authored-by: Remoun Metyas Co-authored-by: Nick Santana --- text/0052-tx-summary-digest.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 3fc700bf..763c3f8e 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -6,7 +6,7 @@ # Summary [summary]: #summary -Introduce an object called `TxSummary` which is significantly smaller than a `Tx`, +Introduce a `TxSummary` that is significantly smaller than a `Tx`, but which with small additional data can be used to verify the values of inputs and outputs, and the destinations of the outputs, when a device is asked to sign a `RingMLSAG` for a new transaction. @@ -28,10 +28,10 @@ the entire `Tx` on the device so that it can verify the `extended_message_digest because the `extended_message_digest` is the only thing that connects the `MLSAG` that the device is signing to the rest of the `Tx`. -This increases the amount of data that has to be sent to the device from a few kb -to `> 100kb` in the worst case. This is because Merkle proofs are each e.g. 40 bytes -per merkle element and with a height of 20-30, so they may end up being 1 KB each. -Then, there is a merkle proof for each `TxIn` (at most 16) and each mixin (11 per `TxIn`). +This increases the amount of data that has to be sent to the device from a few KiB +to over 100KiB in the worst case. This is because Merkle proofs are around 40 bytes +per merkle element. With a height of 20-30 they may end up being 1 KB each. +Then, there is a Merkle proof for each `TxIn` (at most 16) and each mixin (11 per `TxIn`). Having to transfer this much data to a tiny device will slow down the user experience noticeably, and will greatly increase the complexity of implementation, because the device @@ -41,7 +41,7 @@ to compute the hash. On the other hand, if the digest that the Ring MLSAGs sign is changed as proposed, then we only need to send 32 bytes followed by the `TxSummary` to prove to the device where the digest that the MLSAG's are signing comes from, and so what the outcome of the `Tx` is. -So we can avoid sending all merkle proofs, bulletproofs, encrypted fog hints, memos, etc. +So we can avoid sending all Merkle proofs, bulletproofs, encrypted fog hints, memos, etc. and reduce the traffic with the device by perhaps a factor of 10 or so in the worst case, as well as reducing the implementation complexity. @@ -55,8 +55,8 @@ There is exactly one possible `TxSummary` for a given `Tx`. The `TxSummary` contains: * The list of outputs (omitting "extra" parts like encrypted fog hint and encrypted memo). -* The list of pseudo_output_commitments (commitments to the values of the true inputs) - * Any input rules associated to these inputs (if they are [MCIP 31](https://github.com/mobilecoinfoundation/mcips/pull/31) signed contingent inputs) +* The list of `pseudo_output_commitments` (commitments to the values of the true inputs) + * Any input rules associated to these inputs (if they are [MCIP 31](0031-transactions-with-contingent-inputs.md) signed contingent inputs) * The fee and fee token id * The tombstone block @@ -70,7 +70,7 @@ When a hardware wallet is asked to sign an MLSAG, we can give it now the `extend and the `TxSummary`, and it can compute the appropriate digest from this for the MLSAG to sign. Additionally, we can provide it the `TxSummaryUnblindingData`, which inclues: -* For each pseudo-output-commitment, the amount (value and token id), and blinding factor. +* For each `pseudo_output_commitment`, the amount (value and token id), and blinding factor. * For each output, the target public address, the amount, and the `tx_private_key`, unless it is part of an SCI. In that case we can unblind it using the amount shared secret in the SCI input rules to find it's value, and we can't know @@ -172,7 +172,7 @@ The hardware wallet also knows how the validators will compute the `extended_mes based on the `Tx`, and knows that it is infeasible for anyone to find another `Tx` that has the same digest here. So, an attacker (on the computer) could give the device an improperly formed `TxSummary` and lie to the device this way, but the attacker will not be able to get consensus to accept those signatures. The device therefore -knows that the either the `TxSummary` is accurate, or it's signature doesn't matter because the `Tx` will not +knows that either the `TxSummary` is accurate, or it's signature doesn't matter because the `Tx` will not be accepted. A hardware wallet can also expect to be supplied with the `TxSummaryUnblindingData` which allows it to see @@ -224,7 +224,7 @@ Instead, we view this current proposal as the simplest and most straightforward hardware wallets and help them to avoid complexities around streaming too much data and having to create a state machine to compute a proper merlin digest of the entire `Tx` object, which would also make the user experience significantly slower. -## SCI support, definition of `TxSummaryUnblindingData`. +## SCI support, definition of `TxSummaryUnblindingData` We have tried to future-proof this design against [MCIP 31](https://github.com/mobilecoinfoundation/mcips/pull/31) Signed Contingent Inputs being present in the `Tx`. However, these cannot even be used until block version 3, and may not be in common use at the time that hardware wallet support From 1817daf8be69da0419814f76648e8aca0b0787ca Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 11:04:17 -0600 Subject: [PATCH 12/33] Update text/0052-tx-summary-digest.md Co-authored-by: isis lovecruft <79881025+isis-mc@users.noreply.github.com> --- text/0052-tx-summary-digest.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 763c3f8e..1bb09999 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -164,7 +164,8 @@ TxInSummary: Option~InputRules~ input_rules A hardware wallet which is asked to sign an MLSAG can expect to see that 32 byte digest and the `TxSummary`. -**Security**: +# Security +[security]: #security From a security point of view, the hardware wallet can know that it is intractable for someone to find a different `TxSummary` that produces the same `extended_message_and_tx_summary` digest, so if it signs the MLSAG, this is the only thing that it can be committing to. From 2060f3f66418424b1fc33bb5fcba264b4b767fa8 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 11:14:20 -0600 Subject: [PATCH 13/33] rewrite guide-level explanation --- text/0052-tx-summary-digest.md | 163 ++++++++++++++++++++++++++++----- 1 file changed, 141 insertions(+), 22 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 1bb09999..e365c813 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -48,17 +48,37 @@ as well as reducing the implementation complexity. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation -A `TxSummary` is an object much like the `TxPrefix`, but where instead of the `TxIn` -objects, the corresponding `pseudo_output_commitments` are stored. +A `TxSummary` is an object much like the `TxPrefix`, with small but important differences +in exactly what data are stored about inputs and outputs. + +The purpose of a `TxSummary` is that: +* It is much smaller than a `Tx`. +* It can be streamed to a small hardware device, together with the `extended_message_digest`, + in order to efficiently compute the (new) digest which MLSAG's must sign. +* Small additional data (`TxSummaryUnblindingData`) can be streamed with the pieces of the `TxSummary`, allowing + the device to "unblind" the `TxSummary`. +* This can be used to create a `TxSummaryUnblindingReport`, which deduces the following: + * For each output, the amount, and the entity to which it is destined, which is one of three possibilities: + * The signer themselves + * A known contact, identified by their public address + * An anonymous swap counterparty + * For each input, the amount, and the entity from whcih it came, which is one of two possibilities: + * The signer themselves + * An anonymous swap counterparty + +The design goals here are: +* A hardware device which is expected to sign MLSAGs for a transaction, can do so while having **visibility + into how much funds** are being moved **from whom**, and **to whom** they are going. +* A hardware device can use the `TxSummaryUnblindingReport` to display this (verified) information to the user. +* The hardware device need not trust the host computer to verify this information. There is exactly one possible `TxSummary` for a given `Tx`. -The `TxSummary` contains: -* The list of outputs (omitting "extra" parts like encrypted fog hint and encrypted memo). -* The list of `pseudo_output_commitments` (commitments to the values of the true inputs) - * Any input rules associated to these inputs (if they are [MCIP 31](0031-transactions-with-contingent-inputs.md) signed contingent inputs) -* The fee and fee token id -* The tombstone block +To achieve the goals, and make it unnecessary for the device to see the majority of the `Tx`, we have +to change the way that the digest which `RingMLSAG`'s sign is computed. + +**Note**: This change does not impact the digest that [MCIP 31](0031-transactions-with-contingent-inputs.md) signed contingent inputs (SCIs) sign, +those inputs sign the same digest that was specified in MCIP 31. During transaction construction, the signer computes the extended message digest as before, but now creates a merlin transcript using that 32-byte digest, followed by digesting the @@ -66,19 +86,117 @@ but now creates a merlin transcript using that 32-byte digest, followed by diges The verifier similarly computes this `extended-message-and-tx-summary digest` and verifies that the MLSAGs sign this. +**Note**: This means that the `TxSummary` needs to be constructible by the consensus enclave, given only +the `Tx`, and therefore cannot contain any of the transaction secrets needed to unblind the `TxSummary`. These +secrets appear in `TxSummaryUnblindingData` instead. The host computer (ultimately the `TransactionBuilder`) +is responsible to compute this when it creates +a `Tx`, and then it can be streamed to, and verified by, the hardware device which is asked to sign. + When a hardware wallet is asked to sign an MLSAG, we can give it now the `extended_message_digest` -and the `TxSummary`, and it can compute the appropriate digest from this for the MLSAG to sign. +and steam it the `TxSummary` and the `TxSummaryUnblindingData`, and it can compute the appropriate digest from this for the MLSAG to sign. + +## Estimates + +We would like to provide estimates of the impact of this change. + +### Status quo + +In the status quo, MLSAG's sign the 32-byte `extended-message-digest`. + +To compute this digest, the entire `TxPrefix` must be digested, and then most of the +`SignatureRctBulletproofs` must be digested on top of this digest. Substantially all of the `Tx` +must be passed to merlin to verify this digest. + +If hardware wallets do not compute this digest on the device, then they can have no visibility into +the `TxPrefix.outputs` list, which is what must be unblinded and verified to determine where output +funds are actually going in the transaction. (These are the outputs that will actually be added to +the blockchain.) + +Therefore, without this change, the only way to achieve the requirement of giving hardware wallets +visibility into the outcome of the transaction they are signing is to stream substantially all of the `Tx` +to them. + +Koe has previously in [MCIP 21](https://github.com/mobilecoinfoundation/mcips/pull/21) estimated the +size of a Tx, assuming that there are ~4 billion TxOut's in the ledger, leading the Merkle proofs with ~32 +elements. + +> Currently (protocol v0), Merkle membership proofs constitute the bulk of transaction size. A 1-input/1-output transaction is ~21 kB, with membership proofs taking up ~17 kB (assuming membership proofs with 32 elements, representing a Merkle tree 31 layers deep). In a 16-input/16-output transaction (the maximum size of a transaction), membership proofs occupy ~275 kB out of ~325 kB. + +In mainnet at time of writing, with about 1 million blocks in the ledger, this would be only 22 elements, but this is still > 200 KB in total that must be streamed. + +In the proof-of-concept work for this proposal, we measured exactly the size on the wire of a max-size and min-size Tx's with 32 element merkle proofs: + +------------------------------------------------------------------------------------------------------- +| | Min-size (1 input, 1 output) Tx | Max-size (16 input, 16 output) Tx | +|-------------------------------|---------------------------------|-----------------------------------| +| Proto-encoded tx size (bytes) | 20_020 | 309_238 | +------------------------------------------------------------------------------------------------------- + +Note that this still does not give the device enough to actually compute the data in the `TxSummaryUnblindingReport`, +it would still need at least the data in the `TxSummaryUnblindingData` to see the amounts and entities associated to +the inputs and outputs. + +### This proposal + +In the proof of concept, MLSAG's sign the 32 byte `extended-message-and-tx-summary-digest`. + +To verify this digest, the amounts and destinations of the outputs, and the amounts and sources of the inputs, we must send to the device: +* The 32-byte `extended-message-digest` +* The `TxSummary` (piecewise) +* The `TxSummaryUnblindingData` (piecewise) + +-------------------------------------------------------------------------------------------------------------- +| | Min-size (1 input, 1 output) Tx | Max-size (16 input, 16 output) Tx | +|--------------------------------------|---------------------------------|-----------------------------------| +| Proto-encoded TxSummary size (bytes) | 176 | 2_726 | +| " TxSummaryUnblindingData (bytes) | 295 | 4_690 | +| Total (+ 32) | 503 | 7_416 | +-------------------------------------------------------------------------------------------------------------- + +The size on the stack of the `TxSummaryStreamingVerifier` (using `heapless`) is 1_302 bytes. + +The `TxSummaryStreamingVerifier` has four steps in its protocol: +* Initialization +* Digest output +* Digest input +* Finalization + +The sizes of the payloads which must be transferred to make each step (in the POC) are: + +-------------------------------------------------------------------------- +| | Wire size (proto-encoded bytes) | +|--------------------------------------|---------------------------------| +| Initialization | 32 + 32 + 4 + 2 * 8 = 84 | +| Digest output | 129 + 243 = 372 | +| Digest input | 36 + 45 = 81 | +| Finalization | 3 * (2 + 8) = 30 | +-------------------------------------------------------------------------- + +The largest value in the above is the Digest output step, and the bulk of this is coming +from the need to send a `PublicAddress` in order to verify that a `TxOut` was +correctly addressed to a `PublicAddress` and then display b58 (or an associated hash) +of this `PublicAddress`. + +Verifying each output / input unblinding data entails a few elliptic curve operations in the above. + +### Conclusions + +The proposal always reduces the total amount of data that needs to be streamed by a factor of >40x. + +Anecdotally, it takes about 10s to install an 80 KB app on the ledger nano S. + +This suggests about 2.5s to stream the entire `Tx` to the ledger nano S when the `Tx` has the minimum possible size, +and about 40s to stream a max-size `Tx`. + +It suggests that it should take <.25s to stream all of the data required by the `TxSummaryStreamingVerifier`, +even for a max-size `Tx`. -Additionally, we can provide it the `TxSummaryUnblindingData`, which inclues: -* For each `pseudo_output_commitment`, the amount (value and token id), and blinding factor. -* For each output, the target public address, the amount, and the `tx_private_key`, unless - it is part of an SCI. In that case we can unblind it using the amount shared secret in the - SCI input rules to find it's value, and we can't know - exactly what address is the destination, except that it's associated to the SCI. -* The block version these outputs all targetted. +90% of the impact of this change comes from making it so that we don't have to stream merkle proofs to the hardware device. +The hardware device does not care about these merkle proofs anyways, and isn't capable of checking them. -These data are not very large and allow the hardware wallet to verify the amounts of all -inputs and outputs in the `TxSummary` and to verify the destination of each output. +More savings comes from omitting the encrypted fog hints and encrypted memos of Tx's, as well as all of the TxOut's associated +to input rings. Only the pseudo output commitments and pseudo output blinding factors associated to inputs, as well as a flag +indicating if there are associated input rules, are streamed to the device. # Reference-level explanation [reference-level-explanation]: #reference-level-explanation @@ -152,13 +270,13 @@ TxSummary: Vec~TxInSummary~ inputs TxSummary: uint64 fee_value TxSummary: uint64 fee_token_id TxSummary: uint64 tombstone_block -TxSummary: new(&TxPrefix, &[TxInSummary]) +TxSummary: new(&TxPrefix, &[CompressedCommitment]) TxOutSummary: CompressedRistrettoPublic public_key TxOutSummary: CompressedRistrettoPublic target_key TxOutSummary: MaskedAmount masked_amount -TxOutSummary: from(&TxOut) +TxOutSummary: bool associated_to_input_rules TxInSummary: CompressedCommitment pseudo_output_commitment -TxInSummary: Option~InputRules~ input_rules +TxInSummary: bool has_input_rules ``` A hardware wallet which is asked to sign an MLSAG can expect to see that 32 byte digest @@ -188,12 +306,13 @@ TxSummaryUnblindingData: Vec~UnmaskedAmount~ inputs TxSummaryUnblindingData: Vec~TxOutUnblindingData~ outputs TxOutUnblindingData: UnmaskedAmount amount TxOutUnblindingData: Option~PublicAddress~ address +TxOutUnblindingData: Option~RistrettoPrivate~ tx_private_key ``` Strictly speaking, the `TxSummaryUnblindingData` is not part of the MobileCoin network's protocol rules, it's rather a detail of the hardware wallets, and they might choose not to use this schema and do their own thing. However, it is useful as a proof of concept, to validate that the `TxSummary` design does -actually achieve the goals we set out. This at least provides a starting point for hardware wallet projects +actually achieve the goals we set out. It at least provides a starting point for hardware wallet projects that does not involve sending the entire `Tx`. # Drawbacks From 3c862bd4eda12ea789d5bcd13ccd49d2c396d9ee Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 12:11:25 -0600 Subject: [PATCH 14/33] Update text/0052-tx-summary-digest.md Co-authored-by: isis lovecruft <79881025+isis-mc@users.noreply.github.com> --- text/0052-tx-summary-digest.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index e365c813..6d6154a7 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -35,8 +35,8 @@ Then, there is a Merkle proof for each `TxIn` (at most 16) and each mixin (11 pe Having to transfer this much data to a tiny device will slow down the user experience noticeably, and will greatly increase the complexity of implementation, because the device -has much less memory than this and would have to use some kind of "windowing" strategy -to compute the hash. +has much less memory than this and would have to incrementally stream chunks of data +to the hardware device to compute the hash. On the other hand, if the digest that the Ring MLSAGs sign is changed as proposed, then we only need to send 32 bytes followed by the `TxSummary` to prove to the device where From 6f870fc77be30949a5ff0124cfe2d2cd0aa784fe Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 12:12:35 -0600 Subject: [PATCH 15/33] Update text/0052-tx-summary-digest.md Co-authored-by: isis lovecruft <79881025+isis-mc@users.noreply.github.com> --- text/0052-tx-summary-digest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 6d6154a7..325a6e66 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -226,7 +226,7 @@ M[merlin] --> N N[[extended_message_digest -32 bytes-]] ``` -We propose that in block version 3, Ring MLSAGs (other than the [MCIP 31](https://github.com/mobilecoinfoundation/mcips/pull/31) Signed Contingent Inputs) +We propose that in block version 3, Ring MLSAGs (other than the [MCIP 31](0031-transactions-with-contingent-inputs.md) Signed Contingent Inputs) should now sign the `extended_message_and_tx_summary_digest`, which is computed roughly as follows: From d8ba50be486875da37b35a13d2a0704b09f1005d Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 12:12:49 -0600 Subject: [PATCH 16/33] Update text/0052-tx-summary-digest.md Co-authored-by: Nick Santana --- text/0052-tx-summary-digest.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 325a6e66..fb6bacd1 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -39,8 +39,8 @@ has much less memory than this and would have to incrementally stream chunks of to the hardware device to compute the hash. On the other hand, if the digest that the Ring MLSAGs sign is changed as proposed, then -we only need to send 32 bytes followed by the `TxSummary` to prove to the device where -the digest that the MLSAG's are signing comes from, and so what the outcome of the `Tx` is. +we only need to send 32 bytes followed by the `TxSummary`. This will be enough to prove +to the device what the outcome of the `Tx` is. So we can avoid sending all Merkle proofs, bulletproofs, encrypted fog hints, memos, etc. and reduce the traffic with the device by perhaps a factor of 10 or so in the worst case, as well as reducing the implementation complexity. From abce0978ee2a9dd6ac801cd28853b9d57d8d21a1 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 12:13:51 -0600 Subject: [PATCH 17/33] Update text/0052-tx-summary-digest.md Co-authored-by: isis lovecruft <79881025+isis-mc@users.noreply.github.com> --- text/0052-tx-summary-digest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index fb6bacd1..f4090b36 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -346,7 +346,7 @@ compute a proper merlin digest of the entire `Tx` object, which would also make ## SCI support, definition of `TxSummaryUnblindingData` -We have tried to future-proof this design against [MCIP 31](https://github.com/mobilecoinfoundation/mcips/pull/31) Signed Contingent Inputs being present in the `Tx`. +We have tried to future-proof this design against [MCIP 31](0031-transactions-with-contingent-inputs.md) Signed Contingent Inputs being present in the `Tx`. However, these cannot even be used until block version 3, and may not be in common use at the time that hardware wallet support is actually shipped. From a603a99d3aa78ca19b0b09822d169399479340f3 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 17:15:25 -0600 Subject: [PATCH 18/33] Update text/0052-tx-summary-digest.md Co-authored-by: isis lovecruft <79881025+isis-mc@users.noreply.github.com> --- text/0052-tx-summary-digest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index f4090b36..f21be465 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -213,7 +213,7 @@ M[concatenation] --> N N[extended_message -many bytes-] ``` -In block version 2, we changed this (in [MCIP 25](https://github.com/mobilecoinfoundation/mcips/pull/25)) so that the Ring MLSAG's sign the +In block version 2, we changed this (in [MCIP 25](0025-confidential-token-ids.md)) so that the Ring MLSAG's sign the "extended message digest" which is computed roughly as follows: ```mermaid From 3d266115f7c9c4e9a327d79fe535595bc6171163 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 19:22:28 -0600 Subject: [PATCH 19/33] fixups, add discussion about chain of trust --- text/0052-tx-summary-digest.md | 107 ++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 2 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index f21be465..20403685 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -282,7 +282,7 @@ TxInSummary: bool has_input_rules A hardware wallet which is asked to sign an MLSAG can expect to see that 32 byte digest and the `TxSummary`. -# Security +## Security [security]: #security From a security point of view, the hardware wallet can know that it is intractable for someone to find a different `TxSummary` that produces the same `extended_message_and_tx_summary` digest, @@ -304,7 +304,7 @@ TxOutUnblindingData --> TxSummaryUnblindingData TxSummaryUnblindingData: uint32 block_version TxSummaryUnblindingData: Vec~UnmaskedAmount~ inputs TxSummaryUnblindingData: Vec~TxOutUnblindingData~ outputs -TxOutUnblindingData: UnmaskedAmount amount +TxOutUnblindingData: UnmaskedAmount masked_amount TxOutUnblindingData: Option~PublicAddress~ address TxOutUnblindingData: Option~RistrettoPrivate~ tx_private_key ``` @@ -315,6 +315,109 @@ own thing. However, it is useful as a proof of concept, to validate that the `Tx actually achieve the goals we set out. It at least provides a starting point for hardware wallet projects that does not involve sending the entire `Tx`. +### Unblinding proofs and verification + +Recall that we must consider the following cases and successfully obtain the desired data: + +* For each output, the amount, and the entity to which it is destined, which is one of three possibilities: + * The signer themselves + * A known contact, identified by their public address + * An anonymous swap counterparty +* For each input, the amount, and the entity from which it came, which is one of two possibilities: + * The signer themselves + * An anonymous swap counterparty + +For outputs, we can use the following decision tree: +* Given a `TxOutSummary`, we have the public key, target key, and masked amount of the TxOut + On the hardware device, we have the account view private key of the signer. We can attempt to view-key match the TxOut, + performing key-exchange against the public key, obtaining the `TxOut` shared secret. This can be tested against the + `MaskedAmount` and yields an unblinded amount if it works. This amount is correct -- it is discrete-log hard to find + two Pedersen commitments with different unmaskings. So in case of successful view key matching, the device + can always know that this amount is going to themselves, regardless of any subaddress considerations. +* Then, if view-key matching fails, we can check the `TxOutUnblindingData` and see if it contains both + an address and a `tx_private_key`. This is the expected case whenever the host computer creates a TxOut to a known + contact using e.g. `TransactionBuilder.add_output`. The `TransactionBuilder` is responsible to handle the public address, + and call `TxOut::new` using a randomly chosen `tx_private_key`. Given these data, and the amount from the + `TxOutSummaryUnblindingData.masked_amount`, as well as the block version being targetted, the hardware device is capable of recreating + the call to `TxOut::new` enough to reproduce the `TxOut` public key, the `TxOut` target key, and the `TxOut` masked amount. + If all of these are a match for the `TxOutSummary`, then the device has established that the `TxOut` was originally addressed to + this person with this amount -- it is discrete-log hard to find another amount with the same commitment. It is also generally + impossible to make an account that belongs to two addresses -- starting from two addresses with different view public keys, + finding two different tx_private keys that produce the same tx out public key implies knowledge of a linear relation between + the view private keys. Also obtaining a collision of tx target keys requires finding a hash collision which has negligible success + probability. +* The final case occurs when the `TxOut` was not addressed to ourselves or created using `TransactionBuilder.add_output`, but rather + came as a required (or partial fill) output from a Signed Contingent Input. In this case it is not addressed to ourself, and due + to the anonyminity properties of the MCIP 31 atomic swaps, we cannot know who it is actually addressed to. We can only know that + it goes to our anonymous swap counterparty. + However, it's not okay to say that addresses / tx_private keys are optional for things that don't match to ourselves, because this + allows the (adversarial) host computer to simply omit the address when they don't want to tell the hardware wallet where a payment is going. + To prevent this tampering, `TxOutSummary` has a flag `associated_to_input_rules`, and this is in the `TxSummary`, checked also by the enclave + when it derives `TxSummary` from `TxPrefix`. If this flag is false, then the hardware device knows that the host computer has lied to it, by + witholding the address information and trying to pretend this is an SCI output. + + +**Note**: There is an assumption which is worth explaining here, that outputs that match to `InputRules` never belong to a person signing the transaction. +This is reasonable because it is never sensible for a person to be a counterparty to their own Signed Contingent Input. `InputRules` can only be used +to constrain the person who uses a particular signed input in a transaction. If you are in fact the signer of the input, you could always remove the input +rules and sign the input normally, and your transaction would be valid if it were valid before (in strictly more cases). A real client would always prefer +not to make their own input into an SCI, for simplicity. Regardless, in the above decision tree, we test if a `TxOut` belongs to the signer using view-key +matching before reaching the last case and checking the `associated_to_input_rules` flag. + +For inputs, we can use the following decision tree: +* Given a `TxInSummary`, the `TxSummaryUnblindingData` contains a corresponding `UnmaskedAmount`. + This include the value, token id, and blinding factor corresponding to the pseudo-output commitment. + We can compute the corresponding Pedersen commitment to these deterministically, and check if this matches + the pseudo-output commitment in the `TxInSummary`. This came from the `TxSummary` which is checked by the enclave, + and so we know that it must be accurate. If we manage to unblind it, then we know this is the correct unblinding, + because it is discrete-log hard to find another unmasking of the Pedersen commitment. If we can't unblind it, then + the hardware device knows that the computer has lied / provided a false unmasking, but there is no legitimate reason + for the computer to fail to do this, because regardless of whether this is our own input or a signed input from a + counterparty, we can expect to have the unmasked amount or there is no way we can possibly spend it. +* Now having the amount in hand, the next step is to check the `has_input_rules` flag from `TxInSummary`. We know that + this flag is accurate because the consensus enclave checks the `TxSummary` and can see which inputs actually have rules. + If there are no rules, then we know that we must be signing for this transaction. If there are rules then we attribute + the input to an anonymous swap counterparty. + +**FIXME**: Here we are making a similar assumption, that inputs with `InputRules` never belong to the person signing the transaction. +However, in this case, we don't have a similar mechanism where we can view-key-match the input, because we didn't include enough parts of +the input in the summary for that to happen. This has a consequence -- if a host computer tries to trick the device following the decision +tree above, by taking a normal transaction, and arbitrarily attaching empty `InputRules` to the `TxIn`, creating an SCI, they gain some advantage +over the device, in that they can now manipulate the device into thinking that the user is making money from an anonymous swap counterparty, when +in fact we are just moving the user's own money. + +* Is that an important attack? +* Suppose that we want to mitigate this. What is the smallest / least amount of data that we could attach to the `TxInSummary` to allow that? +* Do we actually have to attach more data? Can we rely on the idea that the device will later have to sign anything that comes from us, and so if an MLSAG +is subsequently sent to the device that actually has rules, the device can flag that as unexpected (or simply produce an invalid signature by +ignoring the rules?) + +### Discussion + +It may seem odd that the design of the `TxSummary` completely omits the `InputRules`. After all, the `InputRules` schema is pretty open-ended. +Is it really true that the hardware device doesn't need direct visibility on them? + +We offer the following justification: +* It is not necessary (or desirable) for the hardware wallet to check that the Tx is well-formed. Indeed it has to see the entire Tx to know that +and the goal is to avoid that. +* Given this, it is necessarily going to be possible for the host computer to create a Tx that is not well-formed, and get the hardware device to sign it. +* That is not considered an attack in the threat model -- the design goal here is, the hardware wallet can prove that if it is signing the digest of a valid `Tx`, +then it knows what the balance changes due to the `Tx` are going to be. Either, the thing it expects to happen will happen, or nothing will happen. + +Recall that the goal here is, the hardware wallet has visibility on: +* The amount of each input and output +* Who those inputs and outputs come from and are going to + +If the hardware wallet can see input rules, then it can know e.g. "you filled a partial fill swap at this fill rate". But this is not a requirement for the +hardware device. + +The main difficulty that the input rules create is that they force case analysis to happen around outputs and inputs. +This is because, for any output that the signer is creating, they know the public address to which it was destined, the amount, the blinding factors, +the `tx_private_key`. They can produce all this evidence for the device about where the `TxOut` came from. But if an output comes from an SCI, then we +did not create it, and we have no visibility into any of this, and there is no way that we can provide this evidence to the device. The input rules flags +are present in the `TxSummary` in order to convince the device that this is really the case, and the host computer is not just withholding evidence in order +to manipulate the logic in the device. + # Drawbacks [drawbacks]: #drawbacks From 9b6f6d5facb8c929ccdc2da3f0d516c379bb1ca2 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 19:23:49 -0600 Subject: [PATCH 20/33] fixup formatting --- text/0052-tx-summary-digest.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 20403685..0fca5bf0 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -126,11 +126,9 @@ In mainnet at time of writing, with about 1 million blocks in the ledger, this w In the proof-of-concept work for this proposal, we measured exactly the size on the wire of a max-size and min-size Tx's with 32 element merkle proofs: -------------------------------------------------------------------------------------------------------- | | Min-size (1 input, 1 output) Tx | Max-size (16 input, 16 output) Tx | |-------------------------------|---------------------------------|-----------------------------------| | Proto-encoded tx size (bytes) | 20_020 | 309_238 | -------------------------------------------------------------------------------------------------------- Note that this still does not give the device enough to actually compute the data in the `TxSummaryUnblindingReport`, it would still need at least the data in the `TxSummaryUnblindingData` to see the amounts and entities associated to @@ -145,13 +143,11 @@ To verify this digest, the amounts and destinations of the outputs, and the amou * The `TxSummary` (piecewise) * The `TxSummaryUnblindingData` (piecewise) --------------------------------------------------------------------------------------------------------------- | | Min-size (1 input, 1 output) Tx | Max-size (16 input, 16 output) Tx | |--------------------------------------|---------------------------------|-----------------------------------| | Proto-encoded TxSummary size (bytes) | 176 | 2_726 | | " TxSummaryUnblindingData (bytes) | 295 | 4_690 | | Total (+ 32) | 503 | 7_416 | --------------------------------------------------------------------------------------------------------------- The size on the stack of the `TxSummaryStreamingVerifier` (using `heapless`) is 1_302 bytes. @@ -163,14 +159,12 @@ The `TxSummaryStreamingVerifier` has four steps in its protocol: The sizes of the payloads which must be transferred to make each step (in the POC) are: --------------------------------------------------------------------------- | | Wire size (proto-encoded bytes) | |--------------------------------------|---------------------------------| | Initialization | 32 + 32 + 4 + 2 * 8 = 84 | | Digest output | 129 + 243 = 372 | | Digest input | 36 + 45 = 81 | | Finalization | 3 * (2 + 8) = 30 | --------------------------------------------------------------------------- The largest value in the above is the Digest output step, and the bulk of this is coming from the need to send a `PublicAddress` in order to verify that a `TxOut` was From 379f1147984f2a1d35d31af72c4465f7cbc7f888 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 19:48:37 -0600 Subject: [PATCH 21/33] fix typos --- text/0052-tx-summary-digest.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 0fca5bf0..ee0e6785 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -322,7 +322,7 @@ Recall that we must consider the following cases and successfully obtain the des * An anonymous swap counterparty For outputs, we can use the following decision tree: -* Given a `TxOutSummary`, we have the public key, target key, and masked amount of the TxOut +* Given a `TxOutSummary`, we have the public key, target key, and masked amount of the TxOut. On the hardware device, we have the account view private key of the signer. We can attempt to view-key match the TxOut, performing key-exchange against the public key, obtaining the `TxOut` shared secret. This can be tested against the `MaskedAmount` and yields an unblinded amount if it works. This amount is correct -- it is discrete-log hard to find @@ -336,10 +336,10 @@ For outputs, we can use the following decision tree: the call to `TxOut::new` enough to reproduce the `TxOut` public key, the `TxOut` target key, and the `TxOut` masked amount. If all of these are a match for the `TxOutSummary`, then the device has established that the `TxOut` was originally addressed to this person with this amount -- it is discrete-log hard to find another amount with the same commitment. It is also generally - impossible to make an account that belongs to two addresses -- starting from two addresses with different view public keys, + impossible to make a TxOut that belongs to two addresses -- starting from two addresses with different view public keys, finding two different tx_private keys that produce the same tx out public key implies knowledge of a linear relation between the view private keys. Also obtaining a collision of tx target keys requires finding a hash collision which has negligible success - probability. + probability. (TODO maybe more detail on this? I think it's a pretty fundamental security property of mobilecoin though.) * The final case occurs when the `TxOut` was not addressed to ourselves or created using `TransactionBuilder.add_output`, but rather came as a required (or partial fill) output from a Signed Contingent Input. In this case it is not addressed to ourself, and due to the anonyminity properties of the MCIP 31 atomic swaps, we cannot know who it is actually addressed to. We can only know that From 4753259c75f68a83bc2851ba8ed894562476dbb6 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 19:52:18 -0600 Subject: [PATCH 22/33] fixup language --- text/0052-tx-summary-digest.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index ee0e6785..7a2fdd50 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -355,8 +355,11 @@ For outputs, we can use the following decision tree: This is reasonable because it is never sensible for a person to be a counterparty to their own Signed Contingent Input. `InputRules` can only be used to constrain the person who uses a particular signed input in a transaction. If you are in fact the signer of the input, you could always remove the input rules and sign the input normally, and your transaction would be valid if it were valid before (in strictly more cases). A real client would always prefer -not to make their own input into an SCI, for simplicity. Regardless, in the above decision tree, we test if a `TxOut` belongs to the signer using view-key -matching before reaching the last case and checking the `associated_to_input_rules` flag. +not to make their own input into an SCI, for simplicity. This observation applies no matter what future kinds of `InputRules` we create -- if you are capable +of signing for a given input on your own, you can always bypass any `InputRules` on an SCI by just signing that input, not as an SCI. +Regardless, in the above decision tree, we test if a `TxOut` belongs to the signer using view-key +matching before reaching the last case and checking the `associated_to_input_rules` flag. So if we do actually own an input, we will identify it thusly, even +if it happens to be associated to some `InputRules`. For inputs, we can use the following decision tree: * Given a `TxInSummary`, the `TxSummaryUnblindingData` contains a corresponding `UnmaskedAmount`. From 9316d54bd3690f87152a12d53c3100333ab7dfb3 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 20:17:36 -0600 Subject: [PATCH 23/33] address isis comment --- text/0052-tx-summary-digest.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 7a2fdd50..fbbe52c7 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -80,10 +80,15 @@ to change the way that the digest which `RingMLSAG`'s sign is computed. **Note**: This change does not impact the digest that [MCIP 31](0031-transactions-with-contingent-inputs.md) signed contingent inputs (SCIs) sign, those inputs sign the same digest that was specified in MCIP 31. -During transaction construction, the signer computes the extended message digest as before, -but now creates a merlin transcript using that 32-byte digest, followed by digesting the -`TxSummary`. The MLSAG's (except for SCIs) will sign 32-bytes extracted from this digest. -The verifier similarly computes this +During transaction construction, the signer: +1. Computes the `extended-message-digest` as before +1. Creates a merlin transcript, appending that digest (using the `mc-crypto-digestible-scheme`) +1. Appends `TxSummary` (using the `mc-crypto-digestible` scheme) +1. Extracts 32 bytes from this digest, the `extended-message-and-tx-summary-digest`. + +The MLSAG's (except for SCIs) will now sign this digest (instead of the `extended-message-digest` as previously). + +The transaction verifier similarly computes this `extended-message-and-tx-summary digest` and verifies that the MLSAGs sign this. **Note**: This means that the `TxSummary` needs to be constructible by the consensus enclave, given only From 22dd341c53130986dc0c6c9c0f721eb78d8d1822 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 18 Oct 2022 20:39:15 -0600 Subject: [PATCH 24/33] add a disclaimer --- text/0052-tx-summary-digest.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index fbbe52c7..a7d5ebcf 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -190,6 +190,8 @@ and about 40s to stream a max-size `Tx`. It suggests that it should take <.25s to stream all of the data required by the `TxSummaryStreamingVerifier`, even for a max-size `Tx`. +(Note that this is extrapolating from anecdotes and may be wildly off.) + 90% of the impact of this change comes from making it so that we don't have to stream merkle proofs to the hardware device. The hardware device does not care about these merkle proofs anyways, and isn't capable of checking them. From 7928a22bafdab67a32fc75b5f3932ca39267d763 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Wed, 19 Oct 2022 09:59:25 -0600 Subject: [PATCH 25/33] add clarifying text --- text/0052-tx-summary-digest.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index a7d5ebcf..7200d836 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -359,10 +359,15 @@ For outputs, we can use the following decision tree: **Note**: There is an assumption which is worth explaining here, that outputs that match to `InputRules` never belong to a person signing the transaction. -This is reasonable because it is never sensible for a person to be a counterparty to their own Signed Contingent Input. `InputRules` can only be used +This is reasonable because it is never sensible for a person to be a counterparty to their own Signed Contingent Input. Conceptually, an SCI is a signed input +with "strings attached", and the `InputRules` are those strings. So the nature of the interaction is "here is my input which you can use, as long as you +follow these rules". `InputRules` can only be used to constrain the person who uses a particular signed input in a transaction. If you are in fact the signer of the input, you could always remove the input -rules and sign the input normally, and your transaction would be valid if it were valid before (in strictly more cases). A real client would always prefer -not to make their own input into an SCI, for simplicity. This observation applies no matter what future kinds of `InputRules` we create -- if you are capable +rules and sign the input normally, and your transaction would be valid if it were valid before (in strictly more cases). Offering yourself one of your own +inputs "with strings attached" never makes sense, because you already had the input and could just sign it again without the strings. + +A real client would always prefer not to make their own input into an SCI, for simplicity. +This observation applies no matter what future kinds of `InputRules` we create -- if you are capable of signing for a given input on your own, you can always bypass any `InputRules` on an SCI by just signing that input, not as an SCI. Regardless, in the above decision tree, we test if a `TxOut` belongs to the signer using view-key matching before reaching the last case and checking the `associated_to_input_rules` flag. So if we do actually own an input, we will identify it thusly, even From f56ca8e722cc31dc62ef82c2ea3da9b5d2f20c72 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 20 Oct 2022 09:47:03 -0600 Subject: [PATCH 26/33] update with discussion about inputs with rules, rearrange slightly --- text/0052-tx-summary-digest.md | 290 ++++++++++++++++++--------------- 1 file changed, 156 insertions(+), 134 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 7200d836..d213ebe5 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -100,105 +100,6 @@ a `Tx`, and then it can be streamed to, and verified by, the hardware device whi When a hardware wallet is asked to sign an MLSAG, we can give it now the `extended_message_digest` and steam it the `TxSummary` and the `TxSummaryUnblindingData`, and it can compute the appropriate digest from this for the MLSAG to sign. -## Estimates - -We would like to provide estimates of the impact of this change. - -### Status quo - -In the status quo, MLSAG's sign the 32-byte `extended-message-digest`. - -To compute this digest, the entire `TxPrefix` must be digested, and then most of the -`SignatureRctBulletproofs` must be digested on top of this digest. Substantially all of the `Tx` -must be passed to merlin to verify this digest. - -If hardware wallets do not compute this digest on the device, then they can have no visibility into -the `TxPrefix.outputs` list, which is what must be unblinded and verified to determine where output -funds are actually going in the transaction. (These are the outputs that will actually be added to -the blockchain.) - -Therefore, without this change, the only way to achieve the requirement of giving hardware wallets -visibility into the outcome of the transaction they are signing is to stream substantially all of the `Tx` -to them. - -Koe has previously in [MCIP 21](https://github.com/mobilecoinfoundation/mcips/pull/21) estimated the -size of a Tx, assuming that there are ~4 billion TxOut's in the ledger, leading the Merkle proofs with ~32 -elements. - -> Currently (protocol v0), Merkle membership proofs constitute the bulk of transaction size. A 1-input/1-output transaction is ~21 kB, with membership proofs taking up ~17 kB (assuming membership proofs with 32 elements, representing a Merkle tree 31 layers deep). In a 16-input/16-output transaction (the maximum size of a transaction), membership proofs occupy ~275 kB out of ~325 kB. - -In mainnet at time of writing, with about 1 million blocks in the ledger, this would be only 22 elements, but this is still > 200 KB in total that must be streamed. - -In the proof-of-concept work for this proposal, we measured exactly the size on the wire of a max-size and min-size Tx's with 32 element merkle proofs: - -| | Min-size (1 input, 1 output) Tx | Max-size (16 input, 16 output) Tx | -|-------------------------------|---------------------------------|-----------------------------------| -| Proto-encoded tx size (bytes) | 20_020 | 309_238 | - -Note that this still does not give the device enough to actually compute the data in the `TxSummaryUnblindingReport`, -it would still need at least the data in the `TxSummaryUnblindingData` to see the amounts and entities associated to -the inputs and outputs. - -### This proposal - -In the proof of concept, MLSAG's sign the 32 byte `extended-message-and-tx-summary-digest`. - -To verify this digest, the amounts and destinations of the outputs, and the amounts and sources of the inputs, we must send to the device: -* The 32-byte `extended-message-digest` -* The `TxSummary` (piecewise) -* The `TxSummaryUnblindingData` (piecewise) - -| | Min-size (1 input, 1 output) Tx | Max-size (16 input, 16 output) Tx | -|--------------------------------------|---------------------------------|-----------------------------------| -| Proto-encoded TxSummary size (bytes) | 176 | 2_726 | -| " TxSummaryUnblindingData (bytes) | 295 | 4_690 | -| Total (+ 32) | 503 | 7_416 | - -The size on the stack of the `TxSummaryStreamingVerifier` (using `heapless`) is 1_302 bytes. - -The `TxSummaryStreamingVerifier` has four steps in its protocol: -* Initialization -* Digest output -* Digest input -* Finalization - -The sizes of the payloads which must be transferred to make each step (in the POC) are: - -| | Wire size (proto-encoded bytes) | -|--------------------------------------|---------------------------------| -| Initialization | 32 + 32 + 4 + 2 * 8 = 84 | -| Digest output | 129 + 243 = 372 | -| Digest input | 36 + 45 = 81 | -| Finalization | 3 * (2 + 8) = 30 | - -The largest value in the above is the Digest output step, and the bulk of this is coming -from the need to send a `PublicAddress` in order to verify that a `TxOut` was -correctly addressed to a `PublicAddress` and then display b58 (or an associated hash) -of this `PublicAddress`. - -Verifying each output / input unblinding data entails a few elliptic curve operations in the above. - -### Conclusions - -The proposal always reduces the total amount of data that needs to be streamed by a factor of >40x. - -Anecdotally, it takes about 10s to install an 80 KB app on the ledger nano S. - -This suggests about 2.5s to stream the entire `Tx` to the ledger nano S when the `Tx` has the minimum possible size, -and about 40s to stream a max-size `Tx`. - -It suggests that it should take <.25s to stream all of the data required by the `TxSummaryStreamingVerifier`, -even for a max-size `Tx`. - -(Note that this is extrapolating from anecdotes and may be wildly off.) - -90% of the impact of this change comes from making it so that we don't have to stream merkle proofs to the hardware device. -The hardware device does not care about these merkle proofs anyways, and isn't capable of checking them. - -More savings comes from omitting the encrypted fog hints and encrypted memos of Tx's, as well as all of the TxOut's associated -to input rings. Only the pseudo output commitments and pseudo output blinding factors associated to inputs, as well as a flag -indicating if there are associated input rules, are streamed to the device. - # Reference-level explanation [reference-level-explanation]: #reference-level-explanation @@ -346,32 +247,20 @@ For outputs, we can use the following decision tree: impossible to make a TxOut that belongs to two addresses -- starting from two addresses with different view public keys, finding two different tx_private keys that produce the same tx out public key implies knowledge of a linear relation between the view private keys. Also obtaining a collision of tx target keys requires finding a hash collision which has negligible success - probability. (TODO maybe more detail on this? I think it's a pretty fundamental security property of mobilecoin though.) -* The final case occurs when the `TxOut` was not addressed to ourselves or created using `TransactionBuilder.add_output`, but rather - came as a required (or partial fill) output from a Signed Contingent Input. In this case it is not addressed to ourself, and due - to the anonyminity properties of the MCIP 31 atomic swaps, we cannot know who it is actually addressed to. We can only know that - it goes to our anonymous swap counterparty. + probability. +* In the final case, the `TxOutUnblindingData` doesn't contain an address or `tx_private_key`. This can occur normally when the `TxOut` + was not created using `TransactionBuilder.add_output` interface, but rather + came as a required (or partial fill) output from a Signed Contingent Input which was added to the `Tx`. + In this case it is not addressed to ourself, and due to the anonyminity properties of the MCIP 31 atomic swaps, we cannot know who + it is actually addressed to. We can only know that it goes to our anonymous swap counterparty. However, it's not okay to say that addresses / tx_private keys are optional for things that don't match to ourselves, because this allows the (adversarial) host computer to simply omit the address when they don't want to tell the hardware wallet where a payment is going. To prevent this tampering, `TxOutSummary` has a flag `associated_to_input_rules`, and this is in the `TxSummary`, checked also by the enclave when it derives `TxSummary` from `TxPrefix`. If this flag is false, then the hardware device knows that the host computer has lied to it, by witholding the address information and trying to pretend this is an SCI output. - - -**Note**: There is an assumption which is worth explaining here, that outputs that match to `InputRules` never belong to a person signing the transaction. -This is reasonable because it is never sensible for a person to be a counterparty to their own Signed Contingent Input. Conceptually, an SCI is a signed input -with "strings attached", and the `InputRules` are those strings. So the nature of the interaction is "here is my input which you can use, as long as you -follow these rules". `InputRules` can only be used -to constrain the person who uses a particular signed input in a transaction. If you are in fact the signer of the input, you could always remove the input -rules and sign the input normally, and your transaction would be valid if it were valid before (in strictly more cases). Offering yourself one of your own -inputs "with strings attached" never makes sense, because you already had the input and could just sign it again without the strings. - -A real client would always prefer not to make their own input into an SCI, for simplicity. -This observation applies no matter what future kinds of `InputRules` we create -- if you are capable -of signing for a given input on your own, you can always bypass any `InputRules` on an SCI by just signing that input, not as an SCI. -Regardless, in the above decision tree, we test if a `TxOut` belongs to the signer using view-key -matching before reaching the last case and checking the `associated_to_input_rules` flag. So if we do actually own an input, we will identify it thusly, even -if it happens to be associated to some `InputRules`. + Therefore the decision tree for this third and final case is simply, check if the `TxOutSummary.associated_input_rules` flags is true, and if + so, attribute it to the swap counterparty. Otherwise, signal an error, that the host computer did not provide enough information for validation + to proceed. For inputs, we can use the following decision tree: * Given a `TxInSummary`, the `TxSummaryUnblindingData` contains a corresponding `UnmaskedAmount`. @@ -388,18 +277,48 @@ For inputs, we can use the following decision tree: If there are no rules, then we know that we must be signing for this transaction. If there are rules then we attribute the input to an anonymous swap counterparty. -**FIXME**: Here we are making a similar assumption, that inputs with `InputRules` never belong to the person signing the transaction. -However, in this case, we don't have a similar mechanism where we can view-key-match the input, because we didn't include enough parts of -the input in the summary for that to happen. This has a consequence -- if a host computer tries to trick the device following the decision -tree above, by taking a normal transaction, and arbitrarily attaching empty `InputRules` to the `TxIn`, creating an SCI, they gain some advantage -over the device, in that they can now manipulate the device into thinking that the user is making money from an anonymous swap counterparty, when -in fact we are just moving the user's own money. +#### Assumptions around `InputRules` -* Is that an important attack? -* Suppose that we want to mitigate this. What is the smallest / least amount of data that we could attach to the `TxInSummary` to allow that? -* Do we actually have to attach more data? Can we rely on the idea that the device will later have to sign anything that comes from us, and so if an MLSAG -is subsequently sent to the device that actually has rules, the device can flag that as unexpected (or simply produce an invalid signature by -ignoring the rules?) +There is an assumption which is worth explaining here, that inputs and outputs that match to `InputRules` never belong to the person signing the transaction. + +This is reasonable because it is never sensible for a person to be a counterparty to their own Signed Contingent Input. Conceptually, an SCI is a signed input +with "strings attached", and the `InputRules` are those strings. So the nature of the interaction is "here is my input which you can use, as long as you +follow these rules". `InputRules` can only be used +to constrain the person who uses a particular signed input in a transaction. If you are in fact the signer of the input, you could always remove the input +rules and sign the input normally, and your transaction would be valid if it were valid before (in strictly more cases). Offering yourself one of your own +inputs "with strings attached" never makes sense, because you already had the input and could just sign it again without the strings. + +So, a real user would generally prefer not to make their own input into an SCI and then spend it in a transaction, for simplicity. +This observation applies no matter what future kinds of `InputRules` we create. + +However, because of the threat model, we may be concerned that a malicious host computer would arbitrarily attach empty input rules to the user's inputs, +in order to confuse the hardware wallet signing device, and cause it to display "self" inputs as "swap counterparty" inputs. And could similarly do so for +outputs. + +The following analysis explains why these attempts fail: +* For `TxOut`'s, the decision tree is specified so that we view-key match it first, and if it matches to use, we short circuit and declare it to be + a credit to ourself, regardless of whether it is associated to input rules. +* For inputs, simply attaching input rules to an input, and then later asking the device to sign it as if there are no input rules, will not work. + In MCIP 31, inputs that have associated input rules have to sign a different digest that does not depend on the entire Tx. If instead the entire Tx + digest is signed, then the transaction will fail validation. + +There is an additional possibility: Suppose that the hardware wallet has features that also support signing the MCIP 31 SCIs. Then it could be possible +that we authorize an sign an SCI, and then later we build a transaction that matches against it, so that we are essentially "trading with ourselves". +In this scenario, a device using the above decision tree would (accurately) identify `TxOut`'s as going to ourselves, but identify the SCI input as +coming from an "anonymous swap counterparty". + +We think this is as-intended: +* If the anonymous swap counterparty is actually ourselves, the report produced by the decision tree is still accurate, as long as the user coalesces + "ourself" and "swap counterparty". +* In most trading systems, it is the user's responsbility to ensure that they are not trading with themselves, and not the system's responsibility to + detect wash trading. +* It is not technically possible for us to "view key scan" an SCI and determine that it was signed by ourselves. The only obvious way for a user + to determine that an SCI is their own is to see that the key image associated to the SCI corresponds to one of our own TxOut's. But in the threat + model that we have, the hardware wallet does not have insight into the totality of `TxOut`'s and key images belonging to the user's account, they + rely on the host computer to provide such `TxOut`'s, and cannot afford to store them all locally or anything like this. +* Since the user would have to have earlier signed for any SCIs that come from their account, if the spend key really is only on the hardware wallet, + it is impossible that the attacker creates an SCI from the user's inputs without their knowledge. The user therefore has considerable insight into + when they might possibly be matching their own SCI and has the means to avoid this situation. ### Discussion @@ -462,11 +381,114 @@ We have tried to future-proof this design against [MCIP 31](0031-transactions-wi However, these cannot even be used until block version 3, and may not be in common use at the time that hardware wallet support is actually shipped. -It may be that hardware wallets will initially cut scope and not seek to support that feature. Then, they could cut the `InputRules` -from the `TxInSummary`, (or rather, return an error if they are present) and they could assume that `address` is mandatory in `TxOutSummary::address`. +It may be that hardware wallets will initially cut scope and not seek to support that feature. If hardware wallets do not support signing +SCI's, it simplifies the security analysis around the verifier, since we will really know that an input that has associated input rules +cannot come from ourselves if the transaction is valid. + +It may also be that hardware wallets want to use a different decision tree or a different `TxOutSummaryUnblindingData` schema. We view it as the prerogative of hardware wallets to define their own wire format as they see fit and carry out whatever compression / improvements they -think are appropriate. The `TxSummaryUnblindingData` schema is only meant as a proof of concept. +think are appropriate. The `TxSummaryUnblindingData` schema is only meant as a proof of concept, to demonstrate that the introduction of `TxSummary` +is useful, provides an improvement over the status quo, and achieves the goals we set out initially. + +## Estimates + +We would like to provide estimates of the impact of this change. + +### Status quo + +In the status quo, MLSAG's sign the 32-byte `extended-message-digest`. + +To compute this digest, the entire `TxPrefix` must be digested, and then most of the +`SignatureRctBulletproofs` must be digested on top of this digest. Substantially all of the `Tx` +must be passed to merlin to verify this digest. + +If hardware wallets do not compute this digest on the device, then they can have no visibility into +the `TxPrefix.outputs` list, which is what must be unblinded and verified to determine where output +funds are actually going in the transaction. (These are the outputs that will actually be added to +the blockchain.) + +Therefore, without this change, the only way to achieve the requirement of giving hardware wallets +visibility into the outcome of the transaction they are signing is to stream substantially all of the `Tx` +to them. + +Koe has previously in [MCIP 21](https://github.com/mobilecoinfoundation/mcips/pull/21) estimated the +size of a Tx, assuming that there are ~4 billion TxOut's in the ledger, leading the Merkle proofs with ~32 +elements. + +> Currently (protocol v0), Merkle membership proofs constitute the bulk of transaction size. A 1-input/1-output transaction is ~21 kB, with membership proofs taking up ~17 kB (assuming membership proofs with 32 elements, representing a Merkle tree 31 layers deep). In a 16-input/16-output transaction (the maximum size of a transaction), membership proofs occupy ~275 kB out of ~325 kB. + +In mainnet at time of writing, with about 1 million blocks in the ledger, this would be only 22 elements, but this is still > 200 KB in total that must be streamed. + +In the proof-of-concept work for this proposal, we measured exactly the size on the wire of a max-size and min-size Tx's with 32 element merkle proofs: + +| | Min-size (1 input, 1 output) Tx | Max-size (16 input, 16 output) Tx | +|-------------------------------|---------------------------------|-----------------------------------| +| Proto-encoded tx size (bytes) | 20_020 | 309_238 | + +Note that this still does not give the device enough to actually compute the data in the `TxSummaryUnblindingReport`, +it would still need at least the data in the `TxSummaryUnblindingData` to see the amounts and entities associated to +the inputs and outputs. + +### This proposal + +In the proof of concept, MLSAG's sign the 32 byte `extended-message-and-tx-summary-digest`. + +To verify this digest, the amounts and destinations of the outputs, and the amounts and sources of the inputs, we must send to the device: +* The 32-byte `extended-message-digest` +* The `TxSummary` (piecewise) +* The `TxSummaryUnblindingData` (piecewise) + +| | Min-size (1 input, 1 output) Tx | Max-size (16 input, 16 output) Tx | +|--------------------------------------|---------------------------------|-----------------------------------| +| Proto-encoded TxSummary size (bytes) | 176 | 2_726 | +| " TxSummaryUnblindingData (bytes) | 295 | 4_690 | +| Total (+ 32) | 503 | 7_416 | + +The size on the stack of the proof-of-concept `TxSummaryStreamingVerifier` (using `heapless`) is 1_600 bytes. + +The `TxSummaryStreamingVerifier` has four steps in its protocol: +* Initialization +* Digest output +* Digest input +* Finalization + +The sizes of the payloads which must be transferred to make each step (in the POC) are: + +| | Wire size (proto-encoded bytes) | +|--------------------------------------|---------------------------------| +| Initialization | 32 + 32 + 4 + 2 * 8 = 84 | +| Digest output | 129 + 243 = 372 | +| Digest input | 36 + 45 = 81 | +| Finalization | 3 * (2 + 8) = 30 | + +The largest value in the above is the Digest output step, and the bulk of this is coming +from the need to send a `PublicAddress` in order to verify that a `TxOut` was +correctly addressed to a `PublicAddress` and then display b58 (or an associated hash) +of this `PublicAddress`. + +Verifying each output / input unblinding data entails a few elliptic curve operations in the above. + +### Conclusions + +The proposal always reduces the total amount of data that needs to be streamed by a factor of >40x. + +Anecdotally, it takes about 10s to install an 80 KB app on the ledger nano S. + +This suggests about 2.5s to stream the entire `Tx` to the ledger nano S when the `Tx` has the minimum possible size, +and about 40s to stream a max-size `Tx`. + +It suggests that it should take <.25s to stream all of the data required by the `TxSummaryStreamingVerifier`, +even for a max-size `Tx`. + +(Note that this is extrapolating from anecdotes and may be wildly off.) + +90% of the impact of this change comes from making it so that we don't have to stream merkle proofs to the hardware device. +The hardware device does not care about these merkle proofs anyways, and isn't capable of checking them. + +More savings comes from omitting the encrypted fog hints and encrypted memos of Tx's, as well as all of the TxOut's associated +to input rings. Only the pseudo output commitments and pseudo output blinding factors associated to inputs, as well as a flag +indicating if there are associated input rules, are streamed to the device. # Prior art [prior-art]: #prior-art From 3d14da9434a3cc03897c74d517f1e1e0ad011194 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Wed, 2 Nov 2022 21:31:44 -0600 Subject: [PATCH 27/33] update with input rules digest --- text/0052-tx-summary-digest.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index d213ebe5..72bb5ec6 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -178,12 +178,15 @@ TxOutSummary: CompressedRistrettoPublic target_key TxOutSummary: MaskedAmount masked_amount TxOutSummary: bool associated_to_input_rules TxInSummary: CompressedCommitment pseudo_output_commitment -TxInSummary: bool has_input_rules +TxInSummary: bytes input_rules_digest ``` A hardware wallet which is asked to sign an MLSAG can expect to see that 32 byte digest and the `TxSummary`. +The `TxInSummary::input_rules_digest` is a canonical 32-byte digest of the `InputRules` object in the `TxIn` +if any exists. Otherwise it is 0 bytes. + ## Security [security]: #security From a security point of view, the hardware wallet can know that it is intractable @@ -439,11 +442,11 @@ To verify this digest, the amounts and destinations of the outputs, and the amou * The `TxSummary` (piecewise) * The `TxSummaryUnblindingData` (piecewise) -| | Min-size (1 input, 1 output) Tx | Max-size (16 input, 16 output) Tx | -|--------------------------------------|---------------------------------|-----------------------------------| -| Proto-encoded TxSummary size (bytes) | 176 | 2_726 | -| " TxSummaryUnblindingData (bytes) | 295 | 4_690 | -| Total (+ 32) | 503 | 7_416 | +| | Min-size (1 input, 1 output) Tx | Max-size (16 input, 16 output) Tx | +|--------------------------------------------------|---------------------------------|-----------------------------------| +| Proto-encoded TxSummary size (bytes) | 176 | 2_726 | +| Proto-encoded TxSummaryUnblindingData (bytes) | 295 | 4_690 | +| Total (+ 32) | 503 | 7_416 | The size on the stack of the proof-of-concept `TxSummaryStreamingVerifier` (using `heapless`) is 1_600 bytes. @@ -459,7 +462,7 @@ The sizes of the payloads which must be transferred to make each step (in the PO |--------------------------------------|---------------------------------| | Initialization | 32 + 32 + 4 + 2 * 8 = 84 | | Digest output | 129 + 243 = 372 | -| Digest input | 36 + 45 = 81 | +| Digest input | 78 + 45 = 123 | | Finalization | 3 * (2 + 8) = 30 | The largest value in the above is the Digest output step, and the bulk of this is coming From 08ea9f6c24ad5351ca6907ff74b4e7bd75034560 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 3 Nov 2022 10:18:59 -0600 Subject: [PATCH 28/33] add a note about the input rules digest --- text/0052-tx-summary-digest.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 72bb5ec6..fe888b9c 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -349,6 +349,11 @@ did not create it, and we have no visibility into any of this, and there is no w are present in the `TxSummary` in order to convince the device that this is really the case, and the host computer is not just withholding evidence in order to manipulate the logic in the device. +**Note**: In the final draft, we decided to include a 32-byte merlin digest of the input rules in the TxSummary, rather than just a flag. This allows that +if in the future we decide that the device needs visibility into the input rules, we can add this without a breaking change to the consensus enclave. +However, in the decision tree for the device, the device does not actually check this digest against anything, it simply checks if this digest is present +to infer whether this input has input rules. + # Drawbacks [drawbacks]: #drawbacks From 708b897f8588e6668b8481e34308522b68354a97 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 3 Nov 2022 12:54:13 -0600 Subject: [PATCH 29/33] Update text/0052-tx-summary-digest.md Co-authored-by: Eran Rundstein --- text/0052-tx-summary-digest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index fe888b9c..8b9983ef 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -62,7 +62,7 @@ The purpose of a `TxSummary` is that: * The signer themselves * A known contact, identified by their public address * An anonymous swap counterparty - * For each input, the amount, and the entity from whcih it came, which is one of two possibilities: + * For each input, the amount, and the entity from which it came, which is one of two possibilities: * The signer themselves * An anonymous swap counterparty From 6767ba35c013ce75d029224cd854754f2af41c8e Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 3 Nov 2022 12:54:27 -0600 Subject: [PATCH 30/33] Update text/0052-tx-summary-digest.md Co-authored-by: Eran Rundstein --- text/0052-tx-summary-digest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 8b9983ef..b7f20172 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -98,7 +98,7 @@ is responsible to compute this when it creates a `Tx`, and then it can be streamed to, and verified by, the hardware device which is asked to sign. When a hardware wallet is asked to sign an MLSAG, we can give it now the `extended_message_digest` -and steam it the `TxSummary` and the `TxSummaryUnblindingData`, and it can compute the appropriate digest from this for the MLSAG to sign. +and stream it the `TxSummary` and the `TxSummaryUnblindingData`, and it can compute the appropriate digest from this for the MLSAG to sign. # Reference-level explanation [reference-level-explanation]: #reference-level-explanation From 400ebf2361df27f1dd8997514678ee00cd244c3d Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 3 Nov 2022 12:54:51 -0600 Subject: [PATCH 31/33] Update text/0052-tx-summary-digest.md Co-authored-by: Eran Rundstein --- text/0052-tx-summary-digest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index b7f20172..7e6bf74a 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -254,7 +254,7 @@ For outputs, we can use the following decision tree: * In the final case, the `TxOutUnblindingData` doesn't contain an address or `tx_private_key`. This can occur normally when the `TxOut` was not created using `TransactionBuilder.add_output` interface, but rather came as a required (or partial fill) output from a Signed Contingent Input which was added to the `Tx`. - In this case it is not addressed to ourself, and due to the anonyminity properties of the MCIP 31 atomic swaps, we cannot know who + In this case it is not addressed to ourself, and due to the anonymity properties of the MCIP 31 atomic swaps, we cannot know who it is actually addressed to. We can only know that it goes to our anonymous swap counterparty. However, it's not okay to say that addresses / tx_private keys are optional for things that don't match to ourselves, because this allows the (adversarial) host computer to simply omit the address when they don't want to tell the hardware wallet where a payment is going. From 5462771db7804cba077888da8bce65efdabbff5f Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 3 Nov 2022 12:55:05 -0600 Subject: [PATCH 32/33] Update text/0052-tx-summary-digest.md Co-authored-by: Eran Rundstein --- text/0052-tx-summary-digest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index 7e6bf74a..fa38af22 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -306,7 +306,7 @@ The following analysis explains why these attempts fail: digest is signed, then the transaction will fail validation. There is an additional possibility: Suppose that the hardware wallet has features that also support signing the MCIP 31 SCIs. Then it could be possible -that we authorize an sign an SCI, and then later we build a transaction that matches against it, so that we are essentially "trading with ourselves". +that we authorize and sign an SCI, and then later we build a transaction that matches against it, so that we are essentially "trading with ourselves". In this scenario, a device using the above decision tree would (accurately) identify `TxOut`'s as going to ourselves, but identify the SCI input as coming from an "anonymous swap counterparty". From 5c82be64f48739fb16d12b20897838fdba972a89 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 3 Nov 2022 13:12:17 -0600 Subject: [PATCH 33/33] add note about signing oracle --- text/0052-tx-summary-digest.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/text/0052-tx-summary-digest.md b/text/0052-tx-summary-digest.md index fa38af22..3b4bcead 100644 --- a/text/0052-tx-summary-digest.md +++ b/text/0052-tx-summary-digest.md @@ -199,6 +199,12 @@ this way, but the attacker will not be able to get consensus to accept those sig knows that either the `TxSummary` is accurate, or it's signature doesn't matter because the `Tx` will not be accepted. +**Note**: One concern here is that, we do not want to create a "signing oracle" whereby the host computer +can trick the hardware wallet into signing something that has a meaning that they never intended. It's important +here that the host computer gives the device an extended message digest, followed by the `TxSummary`, and the +device computes a (domain separated) Merlin digest based on this. If there is a second, alternate meaning to +this digest, it means that the attacker found a collision in Merlin. + A hardware wallet can also expect to be supplied with the `TxSummaryUnblindingData` which allows it to see as much information as possible about where funds are coming from and where they are going in the `Tx`. @@ -275,9 +281,10 @@ For inputs, we can use the following decision tree: the hardware device knows that the computer has lied / provided a false unmasking, but there is no legitimate reason for the computer to fail to do this, because regardless of whether this is our own input or a signed input from a counterparty, we can expect to have the unmasked amount or there is no way we can possibly spend it. -* Now having the amount in hand, the next step is to check the `has_input_rules` flag from `TxInSummary`. We know that - this flag is accurate because the consensus enclave checks the `TxSummary` and can see which inputs actually have rules. - If there are no rules, then we know that we must be signing for this transaction. If there are rules then we attribute +* Now having the amount in hand, the next step is to check if `input_rules_digest` is nonempty in `TxInSummary`. We know that + this is nonempty exactly when there are rules, because the consensus enclave checks the `TxSummary` and can see which + inputs actually have rules, and generates a digest of those rules exactly when they are present. + If there are no rules, then we know that we must be signing for this input. If there are rules then we attribute the input to an anonymous swap counterparty. #### Assumptions around `InputRules`