Distributed Randomness from Weighted VRFs
* paper: https://eprint.iacr.org/2024/198
Science of Blockchain Conference
Wednesday, August 7th, 2024
Alin Tomescu
Aptos Labs�@alinush407
Benny Pinkas
Aptos Labs�@bennypinkas
Daniel Xiang
Aptos Labs�@XiangZhuolun
verifiable random functions
tl;dr
PoS randomness beacon, on Aptos
2
(1) Why might you care?
3
Academics:
Practitioners:
(PV, agg. & no complaints phase)
(2) Why might you care? Randomness is powerful 💪!
🔗 Dapps
🕸️ Consensus
🤐 Privacy
4
Outline
5
Outline
6
Randomness from VRFs
7
e.g., VRF(sk, m) = H(m)sk
r7 =
VRF(sk, 7)
block 7
block 1337
block 8
r8 =
VRF(sk, 8)
r1337 =
VRF(sk, 1337)
Q: Who knows sk?
Weighted distributed key generation (DKG)
8
∀ subset S with >66% stake,
sk = Reconstruct((ski)i∈S)
v1 = VRF(sk1, m)
v2 = VRF(sk2, m)
v3 = VRF(sk3, m)
v3 = VRF(sk4, m)
secret key share
DKG of sk
Weighted distributed key generation (DKG)
9
v1 = VRF(sk1, m)
v2 = VRF(sk2, m)
v3 = VRF(sk3, m)
v3 = VRF(sk4, m)
DKG of sk
Weighted verifiable random function (VRF)
10
v1 = VRF(sk1, m)
v2 = VRF(sk2, m)
v3 = VRF(sk3, m)
v3 = VRF(sk4, m)
rm = VRF(sk, m)
Weighted verifiable random function (VRF)
11
∀ subset S with >66% stake,
rm = Reconstruct((vi)i∈S)
v1 = VRF(sk1, m)
v2 = VRF(sk2, m)
v3 = VRF(sk3, m)
v4 = VRF(sk4, m)
VRF share
rm = VRF(sk, m)
The road so far
12
t-out-of-n "unweighted" PVSS of a secret s
PVSS.Deal(s, t, ek1, …, ekn) → trx ⋍ [ Enc(eki, si) ]i∈[n]
PVSS.Verify(trx, t, ek1, …, ekn) → {0, 1}
PVSS.Aggregate(trx1, trx2) → trx1,2
Public key infrastructure (PKI):
13
∀ subset S of size > t,
s = Reconstruct((si)i∈S)
trx1,2 "deals" s1 + s2
trx "deals" s
t-out-of-n "unweighted" DKG from PVSS
1. Every validator i:
2. Q = subset of >t validators who dealt correctly
3. trx = PVSS.Aggregate({ trxi }i ∈ Q)
⇒ trx deals sk = ∑i ∈ Q zi
14
1. No subset of ≤ t can reconstruct sk
2. Only subsets of > t can reconstruct sk
The road so far
15
Cryptographic preliminaries
Type-3 pairing:
Public parameters:
16
Our t-out-of-n "unweighted" PVSS
17
PVSS.Deal(a0, t, ek1, …, ekn) → trx
define deg-t polynomial s.t. p(0) = a0
commit to shares
encrypt shares
the shared secret is
* t = 548 out of n = 821, consistent with initial weighted deployment on Aptos
288 ms (↑1.65x)
154 KiB (↑1.34x) & aggregatable
Our t-out-of-n "unweighted" PVSS
18
4
2
3
PVSS.Verify(trx, t, ek1, …, ekn) → {0, 1}
1
[CD17]
[Grot21]
Our t-out-of-n "unweighted" PVSS
19
PVSS.Verify!(trx, t, ek1, …, ekn) → {0, 1}
1
3
* t = 548 out of n = 821, consistent with initial weighted deployment on Aptos
21.4 ms (↓11x)
2
Weighted PVSS via virtualization
20
Lagrange coefficients
∀ subset S of weight > t,
sk = Reconstruct((ski)i∈S)
threshold weight t,
total weight n = ∑i wi
(e.g., w = [ 3, 2, 1, 2 ], n = 8)
hp(1) | hp(2) | hp(3) | hp(4) | hp(5) | hp(6) | hp(7) | hp(8) |
sk1,0 | sk1,1 | sk1,2 | sk2,0 | sk2,1 | sk3,0 | sk4,0 | sk4,1 |
The road so far
21
Our weighted VRF
22
the final VRF
Our weighted VRF
23
the final VRF
post-DKG local keygen
O(1)-sized VRF share
Verifies against
📢 broadcast
Performance of our weighted VRF
N = 112 validators
threshold weight t = 548
total weight n = 821*
24
| Weighted BLS [BLS01] | Ours |
* initial weight distributions from Aptos mainnet
The average case
Performance of our weighted VRF
N = 112 validators
threshold weight t = 548
total weight n = 821*
25
| Weighted BLS [BLS01] | Ours |
Share signign time | 590 μs | 290 μs (↓2x) |
* initial weight distributions from Aptos mainnet
+ spreadsheet here
The average case
Performance of our weighted VRF
N = 112 validators
threshold weight t = 548
total weight n = 821*
26
| Weighted BLS [BLS01] | Ours |
Share signign time | 590 μs | 290 μs (↓2x) |
Share verification time | 1,760 μs | 870 μs (↓2x) |
* initial weight distributions from Aptos mainnet
+ spreadsheet here
The average case
Performance of our weighted VRF
N = 112 validators
threshold weight t = 548
total weight n = 821*
27
| Weighted BLS [BLS01] | Ours |
Share signign time | 590 μs | 290 μs (↓2x) |
Share verification time | 1,760 μs | 870 μs (↓2x) |
Share size | 352 bytes | 96 bytes(↓3.67x) |
* initial weight distributions from Aptos mainnet
+ spreadsheet here
The average case
Performance of our weighted VRF
N = 112 validators
threshold weight t = 548
total weight n = 821*
28
| Weighted BLS [BLS01] | Ours |
Share signign time | 590 μs | 290 μs (↓2x) |
Share verification time | 1,760 μs | 870 μs (↓2x) |
Share size | 352 bytes | 96 bytes(↓3.67x) |
Aggregation time | 4.6 ms | 43.5 ms (↓9.4x) |
* initial weight distributions from Aptos mainnet
+ spreadsheet here
The average case
Performance of our weighted VRF
N = 112 validators
threshold weight t = 548
total weight n = 821*
29
| Weighted BLS [BLS01] | Ours |
Share signign time | 590 μs | 290 μs (↓2x) |
Share verification time | 1,760 μs | 870 μs (↓2x) |
Share size | 352 bytes | 96 bytes(↓3.67x) |
Aggregation time | 4.6 ms | 43.5 ms (↓9.4x) |
End-to-end time | 137 ms | 108 ms (↓1.26x) |
The average case
* initial weight distributions from Aptos mainnet
+ spreadsheet here; screenshotted here
Dominates end-to-end time
The road so far
30
Randomness on Aptos mainnet 🚀
31
# of randomness TXNs | 520,141 |
Randomness on Aptos mainnet 🚀
32
# of randomness TXNs | 520,141 |
DKG duration | 20 sec |
Randomness on Aptos mainnet 🚀
33
# of randomness TXNs | 520,141 |
DKG duration | 20 sec |
Randomness latency | 160 ms |
↓6.4x to 25 ms since [DPTX24]
Conclusion: "What can switching to 𝔾 SKs do for you?"
34
🤲 PVSS for 𝔾 SKs
🚀 Aptos randomness
🎲 O(1) weighted VRFs
Open source
Deployed on mainnet
Fastest aggregatable PVSS to date
Theoretically-surprising & practically-useful
Acknowledgements
35
Did not get to discuss
36
Details
"More! More! is the cry of a mistaken soul.
Less than All cannot satisfy Man."
William Blake
37
References
[AIP41] Move APIs for public randomness generation, Alin Tomescu; 2023
[AIP61] Keyless accounts (AIP-61), Alin Tomescu; 2024
[AIP79] Implementation of instant on-chain randomness (AIP-79), Alin Tomescu, Zhuolun "Daniel" Xiang, Zhoujun Ma; 2024
[BLS01] Short Signatures from the Weil Pairing; by Boneh, Dan and Lynn, Ben and Shacham, Hovav; in ASIACRYPT'01
[BTW05] Characterizing Ideal Weighted Threshold Secret Sharing; by Beimel, Amos and Tassa, Tamir and Weinreb, Enav; in TCC'05
[CD17] SCRAPE: Scalable Randomness Attested by Public Entities; by Cascudo, Ignacio and David, Bernardo; in ACNS'17
[CD20] ALBATROSS: publicly AttestabLe BATched Randomness based On Secret Sharing; by Ignacio Cascudo and Bernardo David;
[DPTX24] Distributed Randomness using Weighted VRFs; by Sourav Das and Benny Pinkas and Alin Tomescu and Zhuolun Xiang;
[Elga85] A public key cryptosystem and a signature scheme based on discrete logarithms; by Elgamal, T.; in IEEE Transactions on Information Theory; 1985
[FLP85] Impossibility of distributed consensus with one faulty process; by Michael J. Fischer and Nancy A. Lynch and Michael S. Paterson; in JACM'85;
[FS01] One Round Threshold Discrete-Log Key Generation without Private Channels; by Fouque, Pierre-Alain and Stern, Jacques; in PKC'01
[Grot21] Non-interactive distributed key generation and key resharing; by Jens Groth
[GJM+21] Aggregatable Distributed Key Generation; by Gurkan, Kobi; Jovanovic, Philipp; Maller, Mary; Meiklejohn, Sarah; Stern, Gilad; Tomescu, Alin; EUROCRYPT'21
[GMR23] tlock: Practical Timelock Encryption from Threshold BLS; by Nicolas Gailly, Kelsey Melissaris & Yolan Romailler
[MRV99] Verifiable random functions; by S. Micali and M. Rabin and S. Vadhan; in FOCS'99�[Stad96] Publicly Verifiable Secret Sharing; by Stadler, Markus; in EUROCRYPT'96
[Tom24] How to use on-chain randomness on Aptos; by Alin Tomescu, 2024
[XDL+24] The Latency Price of Threshold Cryptosystem in Blockchains; by Zhuolun Xiang, Sourav Das, Zekun Li, Zhoujun Ma & Alexander Spiegelman;
38
Appendix
39
PVSS without V in G1
40
PVSS.Deal(a0, t, ek1, …, ekn) → trx
the shared secret is
validator i's
secret share of sk:
∀ set S of size > t,
sk = Reconstr((skj)j∈S)
PVSS without V in G1
41
PVSS.Verify(trx, ek1, …, ekn) → {0, 1}
1
2
3
✅trx is aggregatable
PVSS without V in G1
42
PVSS.Verify(trx, ek1, …, ekn) → {0, 1}
3
2
1
Extra PVSS benchmarks
43
Performance of PVSS w/o V in G1
t = 548, n = 821
44
| Unweighted PVSS w/o V in G1 |
PVSS.Deal time | 228 ms (↑1.3x) |
PVSS.Verify time | 17.9 ms (↓14x) |
trx size | same |
PVSS.Aggregate time | same |
Weighted PVSS with reusable EKs performance
w = 548, W = 821, n = 112*
45
| Weighted PVSS w/ reusable EKs |
PVSS.Deal time | 464 ms (↑2.65x) |
PVSS.Verify time | 149 ms (↓1.68x) |
trx size | 269 KiB (↑2.34x) |
PVSS.Aggregate time | 3.89 ms (↑2.74x) |
* weight distributions are from Aptos mainnet
Performance of our "unweighted" PVSS
t = 548 out of n = 821* PVSS
46
| SCRAPE [CD17] | Ours |
PVSS.Deal time | 175 ms | 288 ms (↑1.65x) |
PVSS.Verify time | 251 ms | 21.4 ms (↓11x) |
trx transcript size | 115 KiB | 154 KiB (↑1.34x) |
PVSS.Aggregate time | 1.71 ms | 2.18 ms (↑1.27x) |
* t and n consistent with initial weighted deployment on Aptos
+ spreadsheet with data
+ implementation: https://github.com/aptos-labs/aptos-core/tree/main/crates/aptos-dkg
Dominates DKG cost!
May be lowered to ↑1.3x via AGM proof
May be avoidable via AGM proof
47
4
2
3
PVSS.Verify(trx, t, ek1, …, ekn) → {0, 1}
1
Weighted PVSS (via virtualization)
48
weighted PVSS:
total weight n
threshold weight t,
validator i: weight wi
t-out-of-n PVSS
si is the starting index of validator i
Lagrange coefficients
∀ subset S of weight > t,
sk = Reconstr((ski)i∈S)
hp(1) | hp(2) | hp(3) | hp(4) | hp(5) | hp(6) | hp(7) | hp(8) |
sk1,0 | sk1,1 | sk1,2 | sk2,0 | sk2,1 | sk3,0 | sk4,0 | sk4,1 |
Weighted BLS versus our wVRF
49
Staking on Aptos (as of March 2024)
50
* slide borrowed from Benny Pinkas's presentation on Aptos randomness
The randomness Move module
module aptos_std::randomness {
use std::vector;
/// Generates `n` bytes uniformly at random.
public fun bytes(n: u64): vector<u8> { /* ... */ }
/// Generates a number uniformly at random.
public fun u64_integer(): u64 { /* ... */ }
public fun u256_integer(): u256 { /* ... */ }
/// Generates a number $n \in [min_incl, max_excl)$ uniformly at random.
public fun u64_range(min_incl: u64, max_excl: u64): u64 { /* ... */ }
public fun u256_range(min_incl: u256, max_excl: u256): u256 { /* ... */ }
/// Generate a permutation of `[0, 1, ..., n-1]` uniformly at random.
public fun permutation(n: u64): vector<u64> { /* ... */ }
#[test_only]
/// Test-only function to set the entropy in the RNG to a specific value.
public fun set_seed(seed: vector<u8>) { /* ... */ }
}
51
Repeated calls will resample a new random outcome
Our weighted VRF from the lens of functional encryptional*
52