@@ -16,14 +16,16 @@ import "./EntropyStructConverter.sol";
1616// Entropy implements a secure 2-party random number generation procedure. The protocol
1717// is an extension of a simple commit/reveal protocol. The original version has the following steps:
1818//
19- // 1. Two parties A and B each draw a random number x_{A,B}
20- // 2. A and B then share h_{A,B} = hash(x_{A,B})
21- // 3. A and B reveal x_{A,B}
22- // 4. Both parties verify that hash(x_{A, B}) == h_{A,B}
23- // 5. The random number r = hash(x_A, x_B)
19+ // 1. Two parties A and B each randomly sample a contribution x_{A,B} to the random number
20+ // 2. A commits to their number by sharing h_A = hash(x_A)
21+ // 3. B reveals x_B
22+ // 4. A reveals x_A
23+ // 5. B verifies that hash(x_{A}) == h_A
24+ // 6. The random number r = hash(x_A, x_B)
2425//
2526// This protocol has the property that the result is random as long as either A or B are honest.
26- // Thus, neither party needs to trust the other -- as long as they are themselves honest, they can
27+ // Honesty means that (1) they draw their value at random, and (2) for A, they keep x_A a secret until
28+ // step 4. Thus, neither party needs to trust the other -- as long as they are themselves honest, they can
2729// ensure that the result r is random.
2830//
2931// Entropy implements a version of this protocol that is optimized for on-chain usage. The
@@ -37,26 +39,19 @@ import "./EntropyStructConverter.sol";
3739// verified against the previous one in the sequence by hashing it, i.e., hash(x_i) == x_{i - 1}
3840//
3941// Request: To produce a random number, the following steps occur.
40- // 1. The user draws a random number x_U, and submits h_U = hash(x_U) to this contract
41- // 2. The contract remembers h_U and assigns it an incrementing sequence number i, representing which
42+ // 1. The user randomly samples their contribution x_U and submits it to the contract
43+ // 2. The contract remembers x_U and assigns it an incrementing sequence number i, representing which
4244// of the provider's random numbers the user will receive.
43- // 3. The user submits an off-chain request (e.g. via HTTP) to the provider to reveal the i'th random number.
44- // 4. The provider checks the on-chain sequence number and ensures it is > i. If it is not, the provider
45- // refuses to reveal the ith random number. The provider should wait for a sufficient number of block confirmations
46- // to ensure that the request does not get re-orged out of the blockchain.
47- // 5. The provider reveals x_i to the user.
48- // 6. The user submits both the provider's revealed number x_i and their own x_U to the contract.
49- // 7. The contract verifies hash(x_i) == x_{i-1} to prove that x_i is the i'th random number. The contract also checks that hash(x_U) == h_U.
45+ // 3. The provider submits a transaction to the contract revealing their contribution x_i to the contract.
46+ // 4. The contract verifies hash(x_i) == x_{i-1} to prove that x_i is the i'th random number.
5047// The contract stores x_i as the i'th random number to reuse for future verifications.
51- // 8. If both of the above conditions are satisfied, the random number r = hash(x_i, x_U).
52- // (Optional) as an added security mechanism, this step can further incorporate the blockhash of the block that the
53- // request transaction landed in: r = hash(x_i, x_U, blockhash).
48+ // 5. If the condition above is satisfied, the random number r = hash(x_i, x_U).
49+ // 6. The contract submits a callback to the calling contract with the random number `r`.
5450//
5551// This protocol has the same security properties as the 2-party randomness protocol above: as long as either
56- // the provider or user is honest, the number r is random. Honesty here means that the participant keeps their
57- // random number x a secret until the revelation phase (step 5) of the protocol. Note that providers need to
58- // be careful to ensure their off-chain service isn't compromised to reveal the random numbers -- if this occurs,
59- // then users will be able to influence the random number r.
52+ // the provider or user is honest, the number r is random. Note that this analysis assumes that
53+ // providers cannot frontrun user transactions -- a dishonest provider who frontruns user transaction can
54+ // manipulate the result.
6055//
6156// The Entropy implementation of the above protocol allows anyone to permissionlessly register to be a
6257// randomness provider. Users then choose which provider to request randomness from. Each provider can set
@@ -71,13 +66,6 @@ import "./EntropyStructConverter.sol";
7166// a compromised sequence. On rotation, any in-flight requests continue to use the pre-rotation commitment.
7267// Providers can use the sequence number of the request along with the event log of their registrations to determine
7368// which hash chain contains the requested random number.
74- //
75- // Warning to integrators:
76- // An important caveat of this protocol is that the user can compute the random number r before
77- // revealing their own number to the contract. This property means that the user can choose to halt the
78- // protocol prior to the random number being revealed (i.e., prior to step (6) above). Integrators should ensure that
79- // the user is always incentivized to reveal their random number, and that the protocol has an escape hatch for
80- // cases where the user chooses not to reveal.
8169abstract contract Entropy is IEntropy , EntropyState {
8270 using ExcessivelySafeCall for address ;
8371
@@ -357,24 +345,24 @@ abstract contract Entropy is IEntropy, EntropyState {
357345 // Note that excess value is *not* refunded to the caller.
358346 function requestWithCallback (
359347 address provider ,
360- bytes32 userRandomNumber
348+ bytes32 userContribution
361349 ) public payable override returns (uint64 ) {
362350 return
363351 requestV2 (
364352 provider,
365- userRandomNumber ,
353+ userContribution ,
366354 0 // Passing 0 will assign the request the provider's default gas limit
367355 );
368356 }
369357
370358 function requestV2 (
371359 address provider ,
372- bytes32 userRandomNumber ,
360+ bytes32 userContribution ,
373361 uint32 gasLimit
374362 ) public payable override returns (uint64 ) {
375363 EntropyStructsV2.Request storage req = requestHelper (
376364 provider,
377- constructUserCommitment (userRandomNumber ),
365+ constructUserCommitment (userContribution ),
378366 // If useBlockHash is set to true, it allows a scenario in which the provider and miner can collude.
379367 // If we remove the blockHash from this, the provider would have no choice but to provide its committed
380368 // random number. Hence, useBlockHash is set to false.
@@ -387,14 +375,14 @@ abstract contract Entropy is IEntropy, EntropyState {
387375 provider,
388376 req.requester,
389377 req.sequenceNumber,
390- userRandomNumber ,
378+ userContribution ,
391379 EntropyStructConverter.toV1Request (req)
392380 );
393381 emit EntropyEventsV2.Requested (
394382 provider,
395383 req.requester,
396384 req.sequenceNumber,
397- userRandomNumber ,
385+ userContribution ,
398386 uint32 (req.gasLimit10k) * TEN_THOUSAND,
399387 bytes ("" )
400388 );
@@ -406,14 +394,14 @@ abstract contract Entropy is IEntropy, EntropyState {
406394 // current commitment and returns the generated random number.
407395 function revealHelper (
408396 EntropyStructsV2.Request storage req ,
409- bytes32 userRevelation ,
410- bytes32 providerRevelation
397+ bytes32 userContribution ,
398+ bytes32 providerContribution
411399 ) internal returns (bytes32 randomNumber , bytes32 blockHash ) {
412400 bytes32 providerCommitment = constructProviderCommitment (
413401 req.numHashes,
414- providerRevelation
402+ providerContribution
415403 );
416- bytes32 userCommitment = constructUserCommitment (userRevelation );
404+ bytes32 userCommitment = constructUserCommitment (userContribution );
417405 if (
418406 keccak256 (bytes .concat (userCommitment, providerCommitment)) !=
419407 req.commitment
@@ -436,8 +424,8 @@ abstract contract Entropy is IEntropy, EntropyState {
436424 }
437425
438426 randomNumber = combineRandomValues (
439- userRevelation ,
440- providerRevelation ,
427+ userContribution ,
428+ providerContribution ,
441429 blockHash
442430 );
443431
@@ -446,7 +434,7 @@ abstract contract Entropy is IEntropy, EntropyState {
446434 ];
447435 if (providerInfo.currentCommitmentSequenceNumber < req.sequenceNumber) {
448436 providerInfo.currentCommitmentSequenceNumber = req.sequenceNumber;
449- providerInfo.currentCommitment = providerRevelation ;
437+ providerInfo.currentCommitment = providerContribution ;
450438 }
451439 }
452440
@@ -455,7 +443,7 @@ abstract contract Entropy is IEntropy, EntropyState {
455443 function advanceProviderCommitment (
456444 address provider ,
457445 uint64 advancedSequenceNumber ,
458- bytes32 providerRevelation
446+ bytes32 providerContribution
459447 ) public override {
460448 EntropyStructsV2.ProviderInfo storage providerInfo = _state.providers[
461449 provider
@@ -473,14 +461,14 @@ abstract contract Entropy is IEntropy, EntropyState {
473461 );
474462 bytes32 providerCommitment = constructProviderCommitment (
475463 numHashes,
476- providerRevelation
464+ providerContribution
477465 );
478466
479467 if (providerCommitment != providerInfo.currentCommitment)
480468 revert EntropyErrors.IncorrectRevelation ();
481469
482470 providerInfo.currentCommitmentSequenceNumber = advancedSequenceNumber;
483- providerInfo.currentCommitment = providerRevelation ;
471+ providerInfo.currentCommitment = providerContribution ;
484472 if (
485473 providerInfo.currentCommitmentSequenceNumber >=
486474 providerInfo.sequenceNumber
@@ -508,8 +496,8 @@ abstract contract Entropy is IEntropy, EntropyState {
508496 function reveal (
509497 address provider ,
510498 uint64 sequenceNumber ,
511- bytes32 userRevelation ,
512- bytes32 providerRevelation
499+ bytes32 userContribution ,
500+ bytes32 providerContribution
513501 ) public override returns (bytes32 randomNumber ) {
514502 EntropyStructsV2.Request storage req = findActiveRequest (
515503 provider,
@@ -528,13 +516,13 @@ abstract contract Entropy is IEntropy, EntropyState {
528516 bytes32 blockHash;
529517 (randomNumber, blockHash) = revealHelper (
530518 req,
531- userRevelation ,
532- providerRevelation
519+ userContribution ,
520+ providerContribution
533521 );
534522 emit Revealed (
535523 EntropyStructConverter.toV1Request (req),
536- userRevelation ,
537- providerRevelation ,
524+ userContribution ,
525+ providerContribution ,
538526 blockHash,
539527 randomNumber
540528 );
@@ -554,8 +542,8 @@ abstract contract Entropy is IEntropy, EntropyState {
554542 function revealWithCallback (
555543 address provider ,
556544 uint64 sequenceNumber ,
557- bytes32 userRandomNumber ,
558- bytes32 providerRevelation
545+ bytes32 userContribution ,
546+ bytes32 providerContribution
559547 ) public override {
560548 EntropyStructsV2.Request storage req = findActiveRequest (
561549 provider,
@@ -573,8 +561,8 @@ abstract contract Entropy is IEntropy, EntropyState {
573561 bytes32 randomNumber;
574562 (randomNumber, ) = revealHelper (
575563 req,
576- userRandomNumber ,
577- providerRevelation
564+ userContribution ,
565+ providerContribution
578566 );
579567
580568 // If the request has an explicit gas limit, then run the new callback failure state flow.
@@ -613,15 +601,17 @@ abstract contract Entropy is IEntropy, EntropyState {
613601 if (success) {
614602 emit RevealedWithCallback (
615603 EntropyStructConverter.toV1Request (req),
616- userRandomNumber ,
617- providerRevelation ,
604+ userContribution ,
605+ providerContribution ,
618606 randomNumber
619607 );
620608 emit EntropyEventsV2.Revealed (
621609 provider,
622610 req.requester,
623611 req.sequenceNumber,
624612 randomNumber,
613+ userContribution,
614+ providerContribution,
625615 false ,
626616 ret,
627617 SafeCast.toUint32 (gasUsed),
@@ -642,8 +632,8 @@ abstract contract Entropy is IEntropy, EntropyState {
642632 provider,
643633 req.requester,
644634 sequenceNumber,
645- userRandomNumber ,
646- providerRevelation ,
635+ userContribution ,
636+ providerContribution ,
647637 randomNumber,
648638 ret
649639 );
@@ -652,6 +642,8 @@ abstract contract Entropy is IEntropy, EntropyState {
652642 req.requester,
653643 sequenceNumber,
654644 randomNumber,
645+ userContribution,
646+ providerContribution,
655647 true ,
656648 ret,
657649 SafeCast.toUint32 (gasUsed),
@@ -692,15 +684,17 @@ abstract contract Entropy is IEntropy, EntropyState {
692684
693685 emit RevealedWithCallback (
694686 reqV1,
695- userRandomNumber ,
696- providerRevelation ,
687+ userContribution ,
688+ providerContribution ,
697689 randomNumber
698690 );
699691 emit EntropyEventsV2.Revealed (
700692 provider,
701693 callAddress,
702694 sequenceNumber,
703695 randomNumber,
696+ userContribution,
697+ providerContribution,
704698 false ,
705699 bytes ("" ),
706700 gasUsed,
0 commit comments