Skip to content

Commit e8b9b28

Browse files
zjmadanielxiangzl
andauthored
randomness #2: real dkg from randomnet (aptos-labs#12127)
* types update from randomnet * update * lint * real dkg and rounding * rounding --------- Co-authored-by: danielxiangzl <[email protected]>
1 parent 3721bd0 commit e8b9b28

File tree

9 files changed

+885
-64
lines changed

9 files changed

+885
-64
lines changed

dkg/src/dkg_manager/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use aptos_validator_transaction_pool::{TxnGuard, VTxnPoolState};
1616
use futures_channel::oneshot;
1717
use futures_util::{future::AbortHandle, FutureExt, StreamExt};
1818
use move_core_types::account_address::AccountAddress;
19-
use rand::thread_rng;
19+
use rand::{prelude::StdRng, thread_rng, SeedableRng};
2020
use std::sync::Arc;
2121

2222
#[allow(dead_code)]
@@ -207,12 +207,12 @@ impl<DKG: DKGTrait> DKGManager<DKG> {
207207
self.state = match &self.state {
208208
InnerState::NotStarted => {
209209
let public_params = DKG::new_public_params(dkg_session_metadata);
210-
let mut rng = thread_rng();
211-
let input_secret = if cfg!(feature = "smoke-test") {
212-
DKG::generate_predictable_input_secret_for_testing(self.dealer_sk.as_ref())
210+
let mut rng = if cfg!(feature = "smoke-test") {
211+
StdRng::from_seed(self.my_addr.into_bytes())
213212
} else {
214-
DKG::InputSecret::generate(&mut rng)
213+
StdRng::from_rng(thread_rng()).unwrap()
215214
};
215+
let input_secret = DKG::InputSecret::generate(&mut rng);
216216

217217
let trx = DKG::generate_transcript(
218218
&mut rng,

dkg/src/transcript_aggregation/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ impl<S: DKGTrait> BroadcastStatus<DKGMessage> for Arc<TranscriptAggregationState
7676
// All checks passed. Aggregating.
7777
trx_aggregator.contributors.insert(metadata.author);
7878
if let Some(agg_trx) = trx_aggregator.trx.as_mut() {
79-
let acc = std::mem::take(agg_trx);
80-
*agg_trx = S::aggregate_transcripts(&self.dkg_pub_params, vec![acc, transcript]);
79+
S::aggregate_transcripts(&self.dkg_pub_params, agg_trx, transcript);
8180
} else {
8281
trx_aggregator.trx = Some(transcript);
8382
}

state-sync/inter-component/event-notifications/src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ fn count_event_notifications_and_ensure_ordering(listener: &mut EventNotificatio
436436
notification_count += 1;
437437
assert_lt!(
438438
last_version_received,
439-
event_notification.version.try_into().unwrap()
439+
std::convert::TryInto::<i64>::try_into(event_notification.version).unwrap()
440440
);
441441
last_version_received = event_notification.version.try_into().unwrap();
442442
} else {

types/src/dkg/dummy_dkg/mod.rs

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub struct DummyDKG {}
1414

1515
impl DKGTrait for DummyDKG {
1616
type DealerPrivateKey = bls12381::PrivateKey;
17+
type DealtPubKeyShare = ();
1718
type DealtSecret = DummySecret;
1819
type DealtSecretShare = DummySecret;
1920
type InputSecret = DummySecret;
@@ -29,11 +30,14 @@ impl DKGTrait for DummyDKG {
2930
DummySecret::aggregate(secrets)
3031
}
3132

32-
fn dealt_secret_from_input(input: &Self::InputSecret) -> Self::DealtSecret {
33+
fn dealt_secret_from_input(
34+
_pub_params: &Self::PublicParams,
35+
input: &Self::InputSecret,
36+
) -> Self::DealtSecret {
3337
*input
3438
}
3539

36-
fn generate_transcript<R: CryptoRng>(
40+
fn generate_transcript<R: CryptoRng + RngCore>(
3741
_rng: &mut R,
3842
_params: &Self::PublicParams,
3943
input_secret: &Self::InputSecret,
@@ -63,31 +67,27 @@ impl DKGTrait for DummyDKG {
6367

6468
fn aggregate_transcripts(
6569
_params: &Self::PublicParams,
66-
transcripts: Vec<DummyDKGTranscript>,
67-
) -> DummyDKGTranscript {
68-
let mut all_secrets = vec![];
69-
let mut agg_contributions_by_dealer = BTreeMap::new();
70-
for transcript in transcripts {
71-
let DummyDKGTranscript {
72-
secret,
73-
contributions_by_dealer,
74-
} = transcript;
75-
all_secrets.push(secret);
76-
agg_contributions_by_dealer.extend(contributions_by_dealer);
77-
}
78-
DummyDKGTranscript {
79-
secret: DummySecret::aggregate(all_secrets),
80-
contributions_by_dealer: agg_contributions_by_dealer,
81-
}
70+
accumulator: &mut Self::Transcript,
71+
element: Self::Transcript,
72+
) {
73+
let DummyDKGTranscript {
74+
secret,
75+
contributions_by_dealer,
76+
} = element;
77+
accumulator
78+
.contributions_by_dealer
79+
.extend(contributions_by_dealer);
80+
accumulator.secret =
81+
DummySecret::aggregate(vec![std::mem::take(&mut accumulator.secret), secret]);
8282
}
8383

8484
fn decrypt_secret_share_from_transcript(
8585
_pub_params: &Self::PublicParams,
8686
transcript: &DummyDKGTranscript,
8787
_player_idx: u64,
8888
_dk: &Self::NewValidatorDecryptKey,
89-
) -> anyhow::Result<DummySecret> {
90-
Ok(transcript.secret)
89+
) -> anyhow::Result<(DummySecret, ())> {
90+
Ok((transcript.secret, ()))
9191
}
9292

9393
fn reconstruct_secret_from_shares(
@@ -108,15 +108,6 @@ impl DKGTrait for DummyDKG {
108108
fn get_dealers(transcript: &DummyDKGTranscript) -> BTreeSet<u64> {
109109
transcript.contributions_by_dealer.keys().copied().collect()
110110
}
111-
112-
fn generate_predictable_input_secret_for_testing(
113-
dealer_sk: &bls12381::PrivateKey,
114-
) -> DummySecret {
115-
let bytes_8: [u8; 8] = dealer_sk.to_bytes()[0..8].try_into().unwrap();
116-
DummySecret {
117-
val: u64::from_be_bytes(bytes_8),
118-
}
119-
}
120111
}
121112

122113
#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize, Deserialize)]

types/src/dkg/dummy_dkg/tests.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,11 @@ fn test_dummy_dkg_correctness() {
118118
.iter()
119119
.map(|state| state.transcript.clone().unwrap())
120120
.collect();
121-
let agg_transcript = DummyDKG::aggregate_transcripts(&pub_params, all_transcripts);
121+
let mut agg_transcript = DummyDKGTranscript::default();
122+
all_transcripts.into_iter().for_each(|trx| {
123+
DummyDKG::aggregate_transcripts(&pub_params, &mut agg_transcript, trx);
124+
});
125+
122126
assert!(DummyDKG::verify_transcript(&pub_params, &agg_transcript).is_ok());
123127

124128
// Optional check: bad transcript should be rejected.
@@ -128,13 +132,14 @@ fn test_dummy_dkg_correctness() {
128132

129133
// Every new validator decrypt their own secret share.
130134
for (idx, nvi) in new_validator_states.iter_mut().enumerate() {
131-
nvi.secret_share = DummyDKG::decrypt_secret_share_from_transcript(
135+
let (secret, _pub_key) = DummyDKG::decrypt_secret_share_from_transcript(
132136
&pub_params,
133137
&agg_transcript,
134138
idx as u64,
135139
&nvi.sk,
136140
)
137-
.ok()
141+
.unwrap();
142+
nvi.secret_share = Some(secret);
138143
}
139144

140145
// The dealt secret should be reconstructable.
@@ -147,7 +152,9 @@ fn test_dummy_dkg_correctness() {
147152
DummyDKG::reconstruct_secret_from_shares(&pub_params, player_share_pairs).unwrap();
148153

149154
let all_input_secrets = dealer_states.iter().map(|ds| ds.input_secret).collect();
150-
let dealt_secret_from_input =
151-
DummyDKG::dealt_secret_from_input(&DummyDKG::aggregate_input_secret(all_input_secrets));
155+
let dealt_secret_from_input = DummyDKG::dealt_secret_from_input(
156+
&pub_params,
157+
&DummyDKG::aggregate_input_secret(all_input_secrets),
158+
);
152159
assert_eq!(dealt_secret_from_reconstruct, dealt_secret_from_input);
153160
}

types/src/dkg/mod.rs

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// Copyright © Aptos Foundation
22

33
use crate::{
4-
dkg::dummy_dkg::DummyDKG, on_chain_config::OnChainConfig,
5-
validator_verifier::ValidatorConsensusInfoMoveStruct,
4+
dkg::real_dkg::RealDKG,
5+
on_chain_config::OnChainConfig,
6+
validator_verifier::{ValidatorConsensusInfo, ValidatorConsensusInfoMoveStruct},
67
};
78
use anyhow::Result;
89
use aptos_crypto::Uniform;
@@ -12,9 +13,12 @@ use move_core_types::{
1213
move_resource::MoveStructType,
1314
};
1415
use once_cell::sync::Lazy;
15-
use rand::CryptoRng;
16+
use rand::{CryptoRng, RngCore};
1617
use serde::{Deserialize, Serialize};
17-
use std::{collections::BTreeSet, fmt::Debug};
18+
use std::{
19+
collections::BTreeSet,
20+
fmt::{Debug, Formatter},
21+
};
1822

1923
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, CryptoHasher, BCSCryptoHash)]
2024
pub struct DKGTranscriptMetadata {
@@ -37,13 +41,22 @@ pub static DKG_START_EVENT_MOVE_TYPE_TAG: Lazy<TypeTag> =
3741
Lazy::new(|| TypeTag::Struct(Box::new(DKGStartEvent::struct_tag())));
3842

3943
/// DKG transcript and its metadata.
40-
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
44+
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
4145
pub struct DKGTranscript {
4246
pub metadata: DKGTranscriptMetadata,
4347
#[serde(with = "serde_bytes")]
4448
pub transcript_bytes: Vec<u8>,
4549
}
4650

51+
impl Debug for DKGTranscript {
52+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
53+
f.debug_struct("DKGTranscript")
54+
.field("metadata", &self.metadata)
55+
.field("transcript_bytes_len", &self.transcript_bytes.len())
56+
.finish()
57+
}
58+
}
59+
4760
impl DKGTranscript {
4861
pub fn new(epoch: u64, author: AccountAddress, transcript_bytes: Vec<u8>) -> Self {
4962
Self {
@@ -63,52 +76,88 @@ impl DKGTranscript {
6376
}
6477
}
6578

66-
// The input of DKG.
79+
/// Reflection of `0x1::dkg::DKGSessionMetadata` in rust.
6780
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
6881
pub struct DKGSessionMetadata {
6982
pub dealer_epoch: u64,
7083
pub dealer_validator_set: Vec<ValidatorConsensusInfoMoveStruct>,
7184
pub target_validator_set: Vec<ValidatorConsensusInfoMoveStruct>,
7285
}
7386

74-
// The input and the run state of DKG.
87+
impl DKGSessionMetadata {
88+
pub fn target_validator_consensus_infos_cloned(&self) -> Vec<ValidatorConsensusInfo> {
89+
self.target_validator_set
90+
.clone()
91+
.into_iter()
92+
.map(|obj| obj.try_into().unwrap())
93+
.collect()
94+
}
95+
96+
pub fn dealer_consensus_infos_cloned(&self) -> Vec<ValidatorConsensusInfo> {
97+
self.dealer_validator_set
98+
.clone()
99+
.into_iter()
100+
.map(|obj| obj.try_into().unwrap())
101+
.collect()
102+
}
103+
}
104+
75105
/// Reflection of Move type `0x1::dkg::DKGSessionState`.
76106
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
77107
pub struct DKGSessionState {
78108
pub metadata: DKGSessionMetadata,
79109
pub start_time_us: u64,
80-
pub result: Vec<u8>,
81-
pub deadline_microseconds: u64,
110+
pub transcript: Vec<u8>,
82111
}
83112

113+
impl DKGSessionState {
114+
pub fn target_epoch(&self) -> u64 {
115+
self.metadata.dealer_epoch + 1
116+
}
117+
}
84118
/// Reflection of Move type `0x1::dkg::DKGState`.
85119
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
86120
pub struct DKGState {
87-
pub last_complete: Option<DKGSessionState>,
121+
pub last_completed: Option<DKGSessionState>,
88122
pub in_progress: Option<DKGSessionState>,
89123
}
90124

125+
impl DKGState {
126+
pub fn maybe_last_complete(&self, epoch: u64) -> Option<&DKGSessionState> {
127+
match &self.last_completed {
128+
Some(session) if session.target_epoch() == epoch => Some(session),
129+
_ => None,
130+
}
131+
}
132+
133+
pub fn last_complete(&self) -> &DKGSessionState {
134+
self.last_completed.as_ref().unwrap()
135+
}
136+
}
137+
91138
impl OnChainConfig for DKGState {
92139
const MODULE_IDENTIFIER: &'static str = "dkg";
93140
const TYPE_IDENTIFIER: &'static str = "DKGState";
94141
}
95142

143+
/// NOTE: this is a subset of the full scheme. Some data items/algorithms are not used in DKG and are omitted.
96144
pub trait DKGTrait: Debug {
97145
type DealerPrivateKey;
98146
type PublicParams: Clone + Debug + Send + Sync;
99-
type Transcript: Clone + Default + Send + Sync + Serialize + for<'a> Deserialize<'a>;
147+
type Transcript: Clone + Send + Sync + Serialize + for<'a> Deserialize<'a>;
100148
type InputSecret: Uniform;
101149
type DealtSecret;
102150
type DealtSecretShare;
103-
type NewValidatorDecryptKey;
151+
type DealtPubKeyShare;
152+
type NewValidatorDecryptKey: Uniform;
104153

105154
fn new_public_params(dkg_session_metadata: &DKGSessionMetadata) -> Self::PublicParams;
106-
fn generate_predictable_input_secret_for_testing(
107-
dealer_sk: &Self::DealerPrivateKey,
108-
) -> Self::InputSecret;
109155
fn aggregate_input_secret(secrets: Vec<Self::InputSecret>) -> Self::InputSecret;
110-
fn dealt_secret_from_input(input: &Self::InputSecret) -> Self::DealtSecret;
111-
fn generate_transcript<R: CryptoRng>(
156+
fn dealt_secret_from_input(
157+
pub_params: &Self::PublicParams,
158+
input: &Self::InputSecret,
159+
) -> Self::DealtSecret;
160+
fn generate_transcript<R: CryptoRng + RngCore>(
112161
rng: &mut R,
113162
params: &Self::PublicParams,
114163
input_secret: &Self::InputSecret,
@@ -120,14 +169,15 @@ pub trait DKGTrait: Debug {
120169

121170
fn aggregate_transcripts(
122171
params: &Self::PublicParams,
123-
transcripts: Vec<Self::Transcript>,
124-
) -> Self::Transcript;
172+
accumulator: &mut Self::Transcript,
173+
element: Self::Transcript,
174+
);
125175
fn decrypt_secret_share_from_transcript(
126176
pub_params: &Self::PublicParams,
127177
trx: &Self::Transcript,
128178
player_idx: u64,
129179
dk: &Self::NewValidatorDecryptKey,
130-
) -> Result<Self::DealtSecretShare>;
180+
) -> Result<(Self::DealtSecretShare, Self::DealtPubKeyShare)>;
131181
fn reconstruct_secret_from_shares(
132182
pub_params: &Self::PublicParams,
133183
player_share_pairs: Vec<(u64, Self::DealtSecretShare)>,
@@ -136,6 +186,6 @@ pub trait DKGTrait: Debug {
136186
}
137187

138188
pub mod dummy_dkg;
189+
pub mod real_dkg;
139190

140-
// TODO: replace with RealDKG.
141-
pub type DefaultDKG = DummyDKG;
191+
pub type DefaultDKG = RealDKG;

0 commit comments

Comments
 (0)