mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 11:31:08 +03:00
5cb8025ddd
* cleanup legacy "3 dot" check (#2625)
* Allow to peers behind NAT to get up to preferred_max connections (#2543)
Allow to peers behind NAT to get up to preffered_max connections
If peer has only outbound connections it's mot likely behind NAT and we should not stop it from getting more outbound connections
* Reduce usage of unwrap in p2p crate (#2627)
Also change store crate a bit
* Simplify (and fix) output_pos cleanup during chain compaction (#2609)
* expose leaf pos iterator
use it for various things in txhashset when iterating over outputs
* fix
* cleanup
* rebuild output_pos index (and clear it out first) when compacting the chain
* fixup tests
* refactor to match on (output, proof) tuple
* add comments to compact() to explain what is going on.
* get rid of some boxing around the leaf_set iterator
* cleanup
* [docs] Add switch commitment documentation (#2526)
* remove references to no-longer existing switch commitment hash
(as switch commitments were removed in ca8447f3bd
and moved into the blinding factor of the Pedersen Commitment)
* some rewording (points vs curves) and fix of small formatting issues
* Add switch commitment documentation
* [docs] Documents in grin repo had translated in Korean. (#2604)
* Start to M/W intro translate in Korean
* translate in Korean
* add korean translation on intro
* table_of_content.md translate in Korean.
* table_of_content_KR.md finish translate in Korean, start to translate State_KR.md
* add state_KR.md & commit some translation in State_KR.md
* WIP stat_KR.md translation
* add build_KR.md && stratum_KR.md
* finish translate stratum_KR.md & table_of_content_KR.md
* rename intro.KR.md to intro_KR.md
* add intro_KR.md file path each language's intro.md
* add Korean translation file path to stratum.md & table_of_contents.md
* fix difference with grin/master
* Fix TxHashSet file filter for Windows. (#2641)
* Fix TxHashSet file filter for Windows.
* rustfmt
* Updating regexp
* Adding in test case
* Display the current download rate rather than the average when syncing the chain (#2633)
* When syncing the chain, calculate the displayed download speed using the current rate from the most recent iteration, rather than the average download speed from the entire syncing process.
* Replace the explicitly ignored variables in the pattern with an implicit ignore
* remove root = true from editorconfig (#2655)
* Add Medium post to intro (#2654)
Spoke to @yeastplume who agreed it makes sense to add the "Grin Transactions Explained, Step-by-Step" Medium post to intro.md
Open for suggestions on a better location.
* add a new configure item for log_max_files (#2601)
* add a new configure item for log_max_files
* rustfmt
* use a constant instead of multiple 32
* rustfmt
* Fix the build warning of deprecated trim_right_matches (#2662)
* [DOC] state.md, build.md and chain directory documents translate in Korean. (#2649)
* add md files for translation.
* start to translation fast-sync, code_structure. add file build_KR.md, states_KR.md
* add dandelion_KR.md && simulation_KR.md for Korean translation.
* add md files for translation.
* start to translation fast-sync, code_structure. add file build_KR.md, states_KR.md
* add dandelion_KR.md && simulation_KR.md for Korean translation.
* remove some useless md files for translation. this is rearrange set up translation order.
* add dot end of sentence & translate build.md in korean
* remove fast-sync_KR.md
* finish build_KR.md translation
* finish build_KR.md translation
* finish translation state_KR.md & add phrase in state.md to move other language md file
* translate blocks_and_headers.md && chain_sync.md in Korean
* add . in chain_sync.md , translation finished in doc/chain dir.
* fix some miss typos
* Api documentation fixes (#2646)
* Fix the API documentation for Chain Validate (v1/chain/validate). It was documented as a POST, but it is actually a GET request, which can be seen in its handler ChainValidationHandler
* Update the API V1 route list response to include the headers and merkleproof routes. Also clarify that for the chain/outputs route you must specify either byids or byheight to select outputs.
* refactor(ci): reorganize CI related code (#2658)
Break-down the CI related code into smaller more maintainable pieces.
* Specify grin or nanogrins in API docs where applicable (#2642)
* Set Content-Type in API client (#2680)
* Reduce number of unwraps in chain crate (#2679)
* fix: the restart of state sync doesn't work sometimes (#2687)
* let check_txhashset_needed return true on abnormal case (#2684)
* Reduce number of unwwaps in api crate (#2681)
* Reduce number of unwwaps in api crate
* Format use section
* Small QoL improvements for wallet developers (#2651)
* Small changes for wallet devs
* Move create_nonce into Keychain trait
* Replace match by map_err
* Add flag to Slate to skip fee check
* Fix secp dependency
* Remove check_fee flag in Slate
* Add Japanese edition of build.md (#2697)
* catch the panic to avoid peer thread quit early (#2686)
* catch the panic to avoid peer thread quit before taking the chance to ban
* move catch wrapper logic down into the util crate
* log the panic info
* keep txhashset.rs untouched
* remove a warning
* [DOC] dandelion.md, simulation.md ,fast-sync.md and pruning.md documents translate in Korean. (#2678)
* Show response code in API client error message (#2683)
It's hard to investigate what happens when an API client error is
printed out
* Add some better logging for get_outputs_by_id failure states (#2705)
* Switch commitment doc fixes (#2645)
Fix some typos and remove the use of parentheses in a
couple of places to make the reading flow a bit better.
* docs: update/add new README.md badges (#2708)
Replace existing badges with SVG counterparts and add a bunch of new ones.
* Update intro.md (#2702)
Add mention of censoring attack prevented by range proofs
* use sandbox folder for txhashset validation on state sync (#2685)
* use sandbox folder for txhashset validation on state sync
* rustfmt
* use temp directory as the sandbox instead actual db_root txhashset dir
* rustfmt
* move txhashset overwrite to the end of full validation
* fix travis-ci test
* rustfmt
* fix: hashset have 2 folders including txhashset and header
* rustfmt
*
(1)switch to rebuild_header_mmr instead of copy the sandbox header mmr
(2)lock txhashset when overwriting and opening and rebuild
* minor improve on sandbox_dir
* add Japanese edition of state.md (#2703)
* Attempt to fix broken TUI locale (#2713)
Can confirm that on the same machine 1.0.2 TUI looks great and is broken on
the current master. Bump of `cursive` version fixed it for me.
Fixes #2676
* clean the header folder in sandbox (#2716)
* forgot to clean the header folder in sandbox in #2685
* Reduce number of unwraps in servers crate (#2707)
It doesn't include stratum server which is sufficiently changed in 1.1
branch and adapters, which is big enough for a separate PR.
* rustfmt
* change version to beta
292 lines
14 KiB
Markdown
292 lines
14 KiB
Markdown
# Introduction to Switch Commitments
|
|
|
|
## General introduction
|
|
|
|
In cryptography a _Commitment_ (or _commitment scheme_) refers to a concept which can be imagined
|
|
like a box with a lock. You can put something into the box (for example a piece of a paper with a
|
|
secret number written on it), lock it and give it to another person (or the public).
|
|
|
|
The other person doesn't know yet what's the secret number in the box, but if you decide to publish
|
|
your secret number later in time and want to prove that this really is the secret which you came
|
|
up with in the first place (and not a different one) you can prove this simply by giving the
|
|
key of the box to the other person.
|
|
|
|
They can unlock the box, compare the secret within the box with the secret you just published
|
|
and can be sure that you didn't change your secret since you locked it. You "**committed**"
|
|
to the secret number beforehand, meaning you cannot change it between the time of
|
|
commitment and the time of revealing.
|
|
|
|
|
|
## Examples
|
|
|
|
### Hash Commitment
|
|
|
|
A simple commitment scheme can be realized with a cryptographic hash function. For example: Alice and Bob
|
|
want to play _"Guess my number"_ and Alice comes up with with her really secret number `29` which
|
|
Bob has to guess in the game, then before the game starts, Alice calculates:
|
|
|
|
hash( 29 + r )
|
|
|
|
and publishes the result to Bob. The `r` is a randomly chosen _Blinding Factor_ which is
|
|
needed because otherwise Bob could just try hashing all the possible numbers for the game and
|
|
compare the hashes.
|
|
|
|
When the game is finished, Alice simply needs to publish her secret number `29` and the
|
|
blinding factor `r` and Bob can calculate the hash himself and easily verify that Alice
|
|
did not change the secret number during the game.
|
|
|
|
|
|
### Pedersen Commitment
|
|
|
|
Other, more advanced commitment schemes can have additional properties. For example MimbleWimble
|
|
and Confidential Transactions (CT) make heavy use of
|
|
_[Pedersen Commitments](https://link.springer.com/content/pdf/10.1007/3-540-46766-1_9.pdf)_,
|
|
which are _homomorphic_ commitments. Homomorphic in this context means that (speaking in the
|
|
"box" metaphor from above) you can take two of these locked boxes (_box1_ and _box2_) and
|
|
somehow "_add_" them together, so that you
|
|
get a single box as result (which still is locked), and if you open this single box later
|
|
(like in the examples before) the secret it contains, is the sum of the secrets
|
|
from _box1_ and _box2_.
|
|
|
|
While this "box" metaphor no longer seems to be reasonable in the real-world this
|
|
is perfectly possible using the properties of operations on elliptic curves.
|
|
|
|
Look into [Introduction to MimbleWimble](intro.md) for further details on Pedersen Commitments
|
|
and how they are used in Grin.
|
|
|
|
|
|
## Properties of commitment schemes:
|
|
|
|
In general for any commitment scheme we can identify two important properties
|
|
which can be weaker or stronger, depending on the type of commitment scheme:
|
|
|
|
- **Hidingness (or Confidentiality):** How good is the commitment scheme protecting the secret
|
|
commitment. Or speaking in terms of our example from above: what would an attacker need to
|
|
open the box (and learn the secret number) without having the key to unlock it?
|
|
|
|
- **Bindingness:** Is it possible at all (or how hard would it be) for an attacker to somehow
|
|
find a different secret, which would produce the same commitment, so that the attacker could
|
|
later open the commitment to a different secret, thus breaking the _binding_ of the
|
|
commitment.
|
|
|
|
### Security of these properties:
|
|
|
|
For these two properties different security levels can be identified.
|
|
|
|
The two most important combinations of these are
|
|
|
|
- **perfectly binding** and **computationally hiding** commitment schemes and
|
|
- **computationally binding** and **perfectly hiding** commitment schemes
|
|
|
|
"_Computationally_" binding or hiding means that the property (bindingness/hidingness)
|
|
is secured by the fact that the underlying mathematical problem is too hard to be solved
|
|
with existing computing power in reasonable time (i.e. not breakable today as computational
|
|
resources are bound in the real world).
|
|
|
|
"_Perfectly_" binding or hiding means that even with infinite computing power
|
|
it would be impossible to break the property (bindingness/hidingness).
|
|
|
|
|
|
|
|
### Mutual exclusivity:
|
|
|
|
It is important to realize that it's **impossible** that any commitment scheme can be
|
|
_perfectly binding_ **and** _perfectly hiding_ at the same time. This can be easily shown
|
|
with a thought experiment: Imagine an attacker having infinite computing power, he could
|
|
simply generate a commitment for all possible values (and blinding factors) until finding a
|
|
pair that outputs the same commitment. If we further assume the commitment scheme is
|
|
_perfectly binding_ (meaning there cannot be two different values leading to the same
|
|
commitment) this uniquely would identify the value within the commitment, thus
|
|
breaking the hidingness.
|
|
|
|
The same is true the other way around. If a commitment scheme is _perfectly hiding_
|
|
there must exist several input values resulting in the same commitment (otherwise an
|
|
attacker with infinite computing power could just try all possible values as
|
|
described above). This concludes that the commitment scheme cannot be _perfectly
|
|
binding_.
|
|
|
|
#### Always a compromise
|
|
|
|
The key take-away point is this: it's **always a compromise**, you can never have both
|
|
properties (_hidingness_ and _bindingness_) with _perfect_ security. If one is _perfectly_
|
|
secure then the other can be at most _computationally_ secure
|
|
(and the other way around).
|
|
|
|
|
|
### Considerations for cryptocurrencies
|
|
|
|
Which roles do these properties play in the design of cryptocurrencies?
|
|
|
|
**Hidingness**:
|
|
In privacy oriented cryptocurrencies like Grin, commitment schemes are used to secure
|
|
the contents of transactions. The sender commits to an amount of coins he sends, but for
|
|
the general public the concrete amount should remain private (protected by the _hidingness_ property of the commitment scheme).
|
|
|
|
**Bindingness**:
|
|
At the same time no transaction creator should ever be able to change his commitment
|
|
to a different transaction amount later in time. If this would be possible, an attacker
|
|
could spend more coins than previously committed to in an UTXO (unspent transaction
|
|
output) and therefore inflate coins out of thin air. Even worse, as the amounts are
|
|
hidden, this could go undetected.
|
|
|
|
So there is a valid interest in having both of these properties always secured and
|
|
never be violated.
|
|
|
|
Even with the intent being that both of these properties will hold for the lifetime
|
|
of a cryptocurrency, still a choice has to be made about which commitment scheme to use.
|
|
|
|
|
|
#### A hard choice?
|
|
|
|
Which one of these two properties needs to be _perfectly_ safe
|
|
and for which one it would be sufficient to be _computationally_ safe?
|
|
Or in other words: in case of a disaster, if the commitment scheme unexpectedly
|
|
gets broken, which one of the two properties should be valued higher?
|
|
Economical soundness (no hidden inflation possible) or ensured privacy (privacy will
|
|
be preserved)?
|
|
|
|
This seems like a hard to choice to make.
|
|
|
|
|
|
If we look closer into this we realize that the commitment scheme only needs to be
|
|
_perfectly_ binding at the point in time when the scheme actually gets broken. Until
|
|
then it will be safe even if it's only _computationally_ binding.
|
|
|
|
At the same time a privacy-oriented cryptocurrency needs to ensure the _hidingness_
|
|
property **forever**. Unlike the _binding_ property, which only is important at the
|
|
time when a transaction is created and will not affect past transactions, the _hidingness_
|
|
property must be ensured at all times. Otherwise, in the unfortunate case should the
|
|
commitment scheme be broken, an attacker could go back in the chain and unblind
|
|
past transactions, thus break the privacy property retroactively.
|
|
|
|
|
|
## Properties of Pedersen Commitments
|
|
|
|
Pedersen Commitments are **computationally binding** and **perfectly hiding** as for a given
|
|
commitment to the value `v`: `v*H + r*G` there may exist a pair of different values `r1`
|
|
and `v1` such that the sum will be the same. Even if you have infinite computing power
|
|
and could try all possible values, you would not be able to tell which one is the original one
|
|
(thus _perfectly hiding_).
|
|
|
|
|
|
## Introducing Switch Commitments
|
|
|
|
So what can be done if the bindingness of the Pedersen Commitment unexpectedly gets broken?
|
|
|
|
In general a cryptocurrency confronted with a broken commitment scheme could choose to
|
|
change the scheme in use, but the problem with this approach would be that it requires to
|
|
create new transaction outputs using the new scheme to make funds secure again. This would
|
|
require every coin holder to move his coins into new transaction outputs.
|
|
If coins are not moved into new outputs, they will not profit from the
|
|
security of the new commitment scheme. Also, this has to happen **before** the scheme gets
|
|
actually broken in the wild, otherwise the existing UTXOs no longer can be assumed
|
|
to contain correct values.
|
|
|
|
In this situation [_Switch Commitments_](https://eprint.iacr.org/2017/237.pdf) offer a neat
|
|
solution. These type of commitments allow changing the properties of the commitments just
|
|
by changing the revealing / validating procedure without changing the way commitments
|
|
are created. (You "_switch_" to a new validation scheme which is backwards
|
|
compatible with commitments created long before the actual "_switch_").
|
|
|
|
|
|
### How does this work in detail
|
|
|
|
First let's introduce a new commitment scheme: The **ElGamal commitment** scheme is a commitment
|
|
scheme similiar to Pedersen Commitments and it's _perfectly binding_ (but only _computationally
|
|
hiding_ as we can never have both).
|
|
It looks very similar to a Pedersen Commitment, with the addition of a new
|
|
element, calculated by multiplying the blinding factor `r` with another generator point `J`:
|
|
|
|
v*H + r*G , r*J
|
|
|
|
So if we store the additional field `r*J` and ignore it for now, we can treat it like
|
|
Pedersen Commitments, until we decide to also validate the full ElGamal
|
|
commitment at some time in future. This is exactly what was implemented in an
|
|
[earlier version of Grin](https://github.com/mimblewimble/grin/blob/5a47a1710112153fb38e4406251c9874c366f1c0/core/src/core/transaction.rs#L812),
|
|
before mainnet was launched. In detail: the hashed value of `r*J`
|
|
(_switch\_commit\_hash_) was added to the transaction output, but this came with
|
|
the burden of increasing the size of each output by 32 bytes.
|
|
|
|
Fortunately, later on the Mimblewimble mailinglist Tim Ruffing came up with a really
|
|
[beautiful idea](https://lists.launchpad.net/mimblewimble/msg00479.html)
|
|
(initially suggested by Pieter Wuille), which offers the same advantages but doesn't
|
|
need this extra storage of an additional element per transaction output:
|
|
|
|
The idea is the following:
|
|
|
|
A normal Pedersen commitment looks like this:
|
|
|
|
v*H + r*G
|
|
|
|
(`v` is value of the input/output, `r` is a truly random blinding factor, and `H` and `G` are
|
|
two generator points on the elliptic curve).
|
|
|
|
If we adapt this by having `r` not being random itself, but using another random number `r'`
|
|
and create the Pedersen Commitment:
|
|
|
|
v*H + r*G
|
|
|
|
such that:
|
|
|
|
r = r' + hash( v*H + r'*G , r'*J )
|
|
|
|
(using the additional third generation point `J` on the curve) then `r` still is perfectly
|
|
valid as a blinding factor, as it's still randomly distributed, but now we see
|
|
that the part within the brackets of the hash function (`v*H + r'*G , r'*J`) is an
|
|
**ElGamal commitment**.
|
|
|
|
This neat idea lead to the removal of the switch commitment hash from the outputs in this
|
|
(and following) [pull requests](https://github.com/mimblewimble/grin/issues/998) as now it
|
|
could be easily included into the Pedersen Commitments.
|
|
|
|
|
|
This is how it is currently implemented in Grin. Pedersen commitments are
|
|
used for the Confidential Transaction but instead of choosing the blinding factor `r`
|
|
only by random, it is calculated by adding the hash of an ElGamal commitment to a random `r'`
|
|
(see here in [main_impl.h#L267](https://github.com/mimblewimble/secp256k1-zkp/blob/73617d0fcc4f51896cce4f9a1a6977a6958297f8/src/modules/commitment/main_impl.h#L267)).
|
|
|
|
|
|
In general switch commitments were first described in the paper
|
|
["Switch Commitments: A Safety Switch for Confidential Transactions"](https://eprint.iacr.org/2017/237.pdf)).
|
|
The **"switch"** in the name comes from the fact that you can virtually flip a "switch" in
|
|
the future and simply by changing the validation procedure you can change the strength of
|
|
the bindingness and hidingness property of your commitments and this even works in a
|
|
backwards compatible way with commitments created today.
|
|
|
|
|
|
|
|
## Conclusion
|
|
|
|
Grin uses Pedersen Commitments - like other privacy cryptocurrencies do as well - with
|
|
the only difference that the random blinding factor `r` is created using the ElGamal
|
|
commitment scheme.
|
|
|
|
This might not seem like a big change on a first look, but it provides an
|
|
important safety measure:
|
|
|
|
Pedersen Commitments are already _perfectly hiding_ so whatever happens, privacy will
|
|
never be at risk without requiring any action from users. But in case of a disaster if the
|
|
bindingness of the commitment scheme gets broken, then switch commitments can be enabled
|
|
(via a soft fork) requiring that all new transactions prove that their commitment is not
|
|
breaking the bindingness by validating the full ElGamal commitment.
|
|
|
|
But in this case users would still have a choice:
|
|
|
|
- they can decide to continue to create new transactions, even if this might compromise
|
|
their privacy (only on their **last** UTXOs) as the ElGamal commitment scheme is
|
|
only computationally hiding, but at least they would still have access to their coins
|
|
|
|
- or users can decide to just leave the money alone, walk away and make no more transactions
|
|
(but preserve their privacy, as their old transactions only validated the Pedersen commitment
|
|
which is perfectly hiding)
|
|
|
|
There are many cases where a privacy leak is much more dangerous to one's life than
|
|
some cryptocurrency might be worth. But this is a decision that should be left up to
|
|
the individual user and switch commitments enable this type of choice.
|
|
|
|
It should be made clear that this is a safety measure meant to be enabled in case of a
|
|
disaster. If advances in computing would put the hardness of the discrete log problem
|
|
in question, a lot of other cryptographic systems, including other cryptocurrencies,
|
|
will be in urgent need of updating their primitives to a future-proof system. The switch
|
|
commitments just provide an additional layer of security if the bindingness of Pedersen
|
|
commitments ever breaks unexpectedly.
|