diff --git a/docs/alpha/randomness_generation.rst b/docs/alpha/randomness_generation.rst index 090b263bc82b23410db163c748cad1f8c918e7b2..80f9f9ab37513bf2ee84edf108ce71d73841598b 100644 --- a/docs/alpha/randomness_generation.rst +++ b/docs/alpha/randomness_generation.rst @@ -148,13 +148,13 @@ Randomness generation parameters * - ``BLOCKS_PER_COMMITMENT`` - 64 blocks * - ``NONCE_REVELATION_THRESHOLD`` - - 32 blocks + - 256 blocks * - ``MAX_ANON_OPS_PER_BLOCK`` - 132 revelations * - ``SEED_NONCE_REVELATION_TIP`` - 1/8 ꜩ * - ``VDF_DIFFICULTY`` - - 1,000,000,000 + - 8,000,000,000 The variables ``BLOCKS_PER_CYCLE`` and ``PRESERVED_CYCLES`` are already defined in the :doc:`proof of stake ` page. diff --git a/docs/kathmandu/randomness_generation.rst b/docs/kathmandu/randomness_generation.rst index 3677e53d9aadeddb0f00787174cf1e0da7493399..4d686bbd521ef98bd01b33e6f4f8f93bc3341c21 100644 --- a/docs/kathmandu/randomness_generation.rst +++ b/docs/kathmandu/randomness_generation.rst @@ -36,10 +36,10 @@ is discarded, otherwise it is accepted. Once the revelation phase is finished, nonces are combined to generate the seed. More precisely, the nonces are hashed together in the same order as the commitment publication. In the case of a rolling RANDAO, the previous seed may -be used to initilialise the hash. +be used to initialize the hash. We make the assumption that at least one participant is honest, that is, it -has indeed chosen a random value and this values was revealed. This is a +has indeed chosen a random value and this value was revealed. This is a necessary condition for the seed to be random. The randomness could however be biased as this protocol suffers from the following low-impact weakness: if a malicious participant can make sure she is the last revealer, then she @@ -49,9 +49,9 @@ two different predetermined seeds. Verifiable Delay Function ^^^^^^^^^^^^^^^^^^^^^^^^^ -Verifiable Delay Functions, also called VDF, are a recent cryptographic -primitive formalised in 2018. They can be seen as a trapdoor-less timelock: -the goal of VDF is making sure a party cannot compute a value before a +Verifiable Delay Functions, also called VDFs, are a recent cryptographic +primitive formalized in 2018. They can be seen as a trapdoor-less timelock: +the goal of a VDF is making sure a party cannot compute a value before a specific time. This new cryptographic building block is based on modular squaring in a group @@ -59,13 +59,13 @@ of unknown order (e.g. class groups or MPC-generated RSA groups) that is believed to be expensive and hard to parallelize. More precisely, the goal of a VDF is for a user to compute a certain value -h = g^2^T mod N ∈ G and a proof of correctness π_h by recursive modular -squarings of h. The variables g, h and T are respectively called the challenge, -solution, and difficulfy parameter. The main difference between VDF and -timelocks is that the latter offers a backdoor to efficiently generate the -challenge from the solution. +``h = g^2^T mod N ∈ G`` and a proof of correctness ``π_h`` by recursive modular +squarings of ``h``. The variables ``g``, ``h``, ``T`` and ``N`` are respectively the *challenge*, +*solution* (or *output*), the *difficulty parameter* and the -unknown- *group order*. The main +difference between VDF and timelocks is that the latter offers a backdoor to +efficiently generate the challenge from the solution. -To this day, two main schemes exist for generating the VDF proofs: +To this day, two main schemes exist for generating VDF proofs: `Wesolowski `_ and `Pietrzak `_. The former presents shorter proofs and is based on a stronger security @@ -78,9 +78,10 @@ Protocol Randomness generation overview ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The randomness generation can be summed up as follows. We first use RANDAO to +The randomness generation uses both RANDAO and VDF, based on class groups and +using Wesolowski proofs. It can be summed up as follows. We first use RANDAO to produce biasable entropy which is used as a VDF challenge to generate an -unbiasable seed (given the adversary cannot compute the VDF before the reveal +unbiasable seed (given the adversary cannot compute the VDF solution before the reveal time ends). To ensure liveness, we fallback to RANDAO entropy if no VDF output was published and verified on-chain. @@ -114,11 +115,20 @@ with transactions for block space. Up to ``MAX_ANON_OPS_PER_BLOCK`` revelations, wallet activations and denunciations can be contained in any given block. During the rest of the cycle, informally called the VDF revelation period, any -party can query the protocol for the *seed computation status* to compute the -VDF solution and publish it on-chain together with a proof of randomness. -If the verification of the solution and proof succeeds, the seed for cycle -``n`` is then updated with the solution: its value is set to be the hash of -the RANDAO output and the solution. +party can query the protocol for the *seed computation status*, which can be +one of the following:(1) the VDF revelation period has not yet started, i.e. +the nonce revelation phase is still ongoing, (2) a VDF solution has already +been successfully submitted, and (3) no VDF solution has been submitted. In +this latter case, the status also provides the information needed to compute +the VDF solution: hash seeds for computing the VDF discriminant (a prime +number defining the class group) and the VDF challenge; more precisely the +random seed of cycle ``n-1`` for the VDF discriminant and the current RANDAO +output for the VDF challenge. Any party can compute a VDF solution and publish +it on-chain together with a proof of correctness. If the verification of the +solution and proof succeeds, the seed for cycle ``n`` is then updated with the +solution: its value is set to be the hash of the RANDAO output and the VDF +solution. + A *VDF revelation* is an operation. A reward ``SEED_NONCE_REVELATION_TIP`` is given for the first correct VDF revelation, subsequent VDF revelation @@ -138,13 +148,13 @@ Randomness generation parameters * - ``BLOCKS_PER_COMMITMENT`` - 64 blocks * - ``NONCE_REVELATION_THRESHOLD`` - - 64 blocks + - 256 blocks * - ``MAX_ANON_OPS_PER_BLOCK`` - 132 revelations * - ``SEED_NONCE_REVELATION_TIP`` - 1/8 ꜩ * - ``VDF_DIFFICULTY`` - - 1,000,000,000 + - 8,000,000,000 The variables ``BLOCKS_PER_CYCLE`` and ``PRESERVED_CYCLES`` are already defined in the :doc:`proof of stake ` page. diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml index 458df999709af3bd11428a1579868c2e078cb78d..af4b89778c34f47e4f426ca47b097f974f112866 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -89,7 +89,7 @@ let constants_mainnet = Constants.Parametric.preserved_cycles = 5; blocks_per_cycle = 8192l; blocks_per_commitment = 64l; - nonce_revelation_threshold = 32l; + nonce_revelation_threshold = 256l; blocks_per_stake_snapshot = 512l; cycles_per_voting_period = 5l; hard_gas_limit_per_operation = Gas.Arith.(integral_of_int_exn 1_040_000); @@ -97,13 +97,13 @@ let constants_mainnet = proof_of_work_threshold = Int64.(sub (shift_left 1L 46) 1L); tokens_per_roll = Tez.(mul_exn one 6_000); (* VDF's difficulty must be a multiple of `nonce_revelation_threshold` times - the block time. At the moment it is equal to 1B = 1000 * 5 * .2M with - - 1000 ~= 32 * 30 that is nonce_revelation_threshold * block time + the block time. At the moment it is equal to 8B = 8000 * 5 * .2M with + - 8000 ~= 256 * 30 that is nonce_revelation_threshold * block time - .2M ~= number of modular squaring per second on benchmark machine with 2.8GHz CPU - 5: security factor (strictly higher than the ratio between highest CPU clock rate and benchmark machine that is 8.43/2.8 ~= 3 *) - vdf_difficulty = 1_000_000_000L; + vdf_difficulty = 8_000_000_000L; seed_nonce_revelation_tip = (match Tez.(one /? 8L) with Ok c -> c | Error _ -> assert false); origination_size = 257; diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index 28af84754b98d8a202203a5a273bda68755ca7f4..a34b0145576cbea7c545515a79ace8e55dadbc1c 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -909,8 +909,8 @@ let prepare_first_block ~level ~timestamp ctxt = blocks_per_cycle = c.blocks_per_cycle; blocks_per_commitment = c.blocks_per_commitment; nonce_revelation_threshold = - (if Compare.Int32.(32l < c.blocks_per_commitment) then 32l - else c.blocks_per_commitment); + (if Compare.Int32.(256l < c.blocks_per_cycle) then 256l + else (* not on mainnet *) Int32.div c.blocks_per_cycle 2l); blocks_per_stake_snapshot = c.blocks_per_stake_snapshot; cycles_per_voting_period = c.cycles_per_voting_period; hard_gas_limit_per_operation = c.hard_gas_limit_per_operation; @@ -918,9 +918,8 @@ let prepare_first_block ~level ~timestamp ctxt = proof_of_work_threshold = c.proof_of_work_threshold; tokens_per_roll = c.tokens_per_roll; vdf_difficulty = - (if Compare.Int32.(32l < c.blocks_per_commitment) then - 1_000_000_000L - else 50_000L); + (if Compare.Int32.(256l < c.blocks_per_cycle) then 8_000_000_000L + else (* not on mainnet *) 50_000L); seed_nonce_revelation_tip = c.seed_nonce_revelation_tip; origination_size = c.origination_size; max_operations_time_to_live = c.max_operations_time_to_live;