Skip to content

Commit 2488c60

Browse files
committed
add register threshold-enc-key functionality
1 parent 0277089 commit 2488c60

File tree

9 files changed

+122
-49
lines changed

9 files changed

+122
-49
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

justfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ test-dyn-comm: build_release_until build-test-utils
215215
--stamp-dir /tmp \
216216
--output test-configs/c1" \
217217
--run "7:target/release/register \
218-
-i 0 \
219218
-u http://localhost:8545 \
220219
-k 0x2bbf15bc655c4cc157b769cfcb1ea9924b9e1a35 \
221220
-c test-configs/c1/committee.toml" \

timeboost-contract/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ bincode = { workspace = true }
2020
clap = { workspace = true }
2121
futures = { workspace = true }
2222
rand = { workspace = true }
23+
reqwest = { workspace = true }
2324
serde = { workspace = true }
2425
timeboost-config = { path = "../timeboost-config" }
26+
timeboost-crypto = { path = "../timeboost-crypto" }
2527
timeboost-types = { path = "../timeboost-types" }
2628
timeboost-utils = { path = "../timeboost-utils" }
2729
tokio = { workspace = true }
@@ -30,4 +32,4 @@ tracing = { workspace = true }
3032
url = { workspace = true }
3133

3234
[build-dependencies]
33-
alloy = { workspace = true }
35+
alloy = { workspace = true }

timeboost-contract/src/binaries/register.rs

Lines changed: 96 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@ use alloy::{
44
primitives::Address,
55
providers::{Provider, WalletProvider},
66
};
7-
use anyhow::{Context, Result, bail};
8-
use clap::Parser;
7+
use anyhow::{Context, Result, anyhow, bail};
8+
use clap::{Parser, ValueEnum};
9+
use reqwest::Client;
910
use std::path::PathBuf;
11+
use std::time::Duration;
1012
use timeboost_config::CommitteeConfig;
1113
use timeboost_contract::{CommitteeMemberSol, KeyManager, provider::build_provider};
14+
use timeboost_crypto::prelude::ThresholdEncKey;
15+
use timeboost_utils::enc_key::ThresholdEncKeyCellAccumulator;
1216
use timeboost_utils::types::logging;
13-
use tracing::info;
17+
use tracing::{info, warn};
1418
use url::Url;
1519

1620
#[derive(Clone, Debug, Parser)]
@@ -22,7 +26,7 @@ struct Args {
2226
)]
2327
mnemonic: String,
2428

25-
#[clap(short, long)]
29+
#[clap(short, long, default_value_t = 0)]
2630
index: u32,
2731

2832
#[clap(short, long)]
@@ -35,6 +39,20 @@ struct Args {
3539
/// Path to the committee.toml config for the next committee
3640
#[clap(short, long)]
3741
config: PathBuf,
42+
43+
/// What to register (new committee or threshold enc key?)
44+
#[clap(long, short, default_value = "new-committee")]
45+
action: Action,
46+
}
47+
48+
/// Specific register action
49+
#[derive(Clone, Copy, Debug, Default, ValueEnum)]
50+
enum Action {
51+
/// register the next committee
52+
#[default]
53+
NewCommittee,
54+
/// register the threshold encryption key (when ready)
55+
ThresholdEncKey,
3856
}
3957

4058
#[tokio::main]
@@ -46,8 +64,6 @@ async fn main() -> Result<()> {
4664
.await
4765
.context(format!("Failed to read config file: {:?}", &args.config))?;
4866

49-
info!("Start committee registration");
50-
5167
let provider = build_provider(args.mnemonic.clone(), args.index, args.url.clone())?;
5268
let addr = args.key_manager_addr;
5369
if provider
@@ -63,40 +79,79 @@ async fn main() -> Result<()> {
6379

6480
let contract = KeyManager::new(addr, provider);
6581

66-
// prepare input argument from config file
67-
let members = config
68-
.members
69-
.iter()
70-
.map(|m| {
71-
Ok::<_, anyhow::Error>(CommitteeMemberSol {
72-
sigKey: m.signing_key.to_bytes().into(),
73-
dhKey: m.dh_key.as_bytes().into(),
74-
dkgKey: m.dkg_enc_key.to_bytes()?.into(),
75-
networkAddress: m.public_address.to_string(),
76-
})
77-
})
78-
.collect::<Result<Vec<_>, _>>()?;
79-
80-
let timestamp: u64 = config
81-
.effective_timestamp
82-
.as_second()
83-
.try_into()
84-
.with_context(|| {
85-
format!(
86-
"failed to convert timestamp {} to u64",
87-
config.effective_timestamp
88-
)
89-
})?;
90-
91-
// send tx and invoke the contract
92-
let _tx_receipt = contract
93-
.setNextCommittee(timestamp, members)
94-
.send()
95-
.await?
96-
.get_receipt()
97-
.await?;
98-
99-
let registered_cid = contract.nextCommitteeId().call().await? - 1;
100-
info!("Registered new committee with id: {registered_cid}");
82+
match args.action {
83+
Action::NewCommittee => {
84+
info!("Start committee registration");
85+
// prepare input argument from config file
86+
let members = config
87+
.members
88+
.iter()
89+
.map(|m| {
90+
Ok::<_, anyhow::Error>(CommitteeMemberSol {
91+
sigKey: m.signing_key.to_bytes().into(),
92+
dhKey: m.dh_key.as_bytes().into(),
93+
dkgKey: m.dkg_enc_key.to_bytes()?.into(),
94+
networkAddress: m.public_address.to_string(),
95+
})
96+
})
97+
.collect::<Result<Vec<_>, _>>()?;
98+
99+
let timestamp: u64 = config
100+
.effective_timestamp
101+
.as_second()
102+
.try_into()
103+
.with_context(|| {
104+
format!(
105+
"failed to convert timestamp {} to u64",
106+
config.effective_timestamp
107+
)
108+
})?;
109+
110+
// send tx and invoke the contract
111+
let _tx_receipt = contract
112+
.setNextCommittee(timestamp, members)
113+
.send()
114+
.await?
115+
.get_receipt()
116+
.await?;
117+
118+
let registered_cid = contract.nextCommitteeId().call().await? - 1;
119+
info!("Registered new committee with id: {registered_cid}");
120+
}
121+
Action::ThresholdEncKey => {
122+
info!("Start threshold encryption key registration");
123+
let client = Client::builder().timeout(Duration::from_secs(1)).build()?;
124+
let urls = config
125+
.members
126+
.iter()
127+
.map(|m| {
128+
let addr = m.http_api.clone();
129+
Url::parse(&format!("http://{addr}/v1/encryption-key"))
130+
.with_context(|| format!("parsing {addr} into a url"))
131+
})
132+
.collect::<Result<Vec<_>, _>>()?;
133+
134+
let mut acc = ThresholdEncKeyCellAccumulator::new(client, urls.into_iter());
135+
let Some(key) = acc.enc_key().await else {
136+
warn!("encryption key not available yet");
137+
return Err(anyhow!(
138+
"threshold enc key not available on enough nodes, try later"
139+
));
140+
};
141+
142+
let _tx_receipt = contract
143+
.setThresholdEncryptionKey(key.to_owned().to_bytes()?.into())
144+
.send()
145+
.await?
146+
.get_receipt()
147+
.await?;
148+
assert_eq!(
149+
&ThresholdEncKey::from_bytes(&contract.thresholdEncryptionKey().call().await?.0)?,
150+
key
151+
);
152+
153+
info!("Registered threshold encryption key");
154+
}
155+
}
101156
Ok(())
102157
}

timeboost-crypto/src/sg_encryption.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use anyhow::anyhow;
55
use ark_ec::{AffineRepr, CurveGroup, hashing::HashToCurve};
66
use ark_ff::{PrimeField, UniformRand};
77
use ark_poly::{DenseUVPolynomial, Polynomial, polynomial::univariate::DensePolynomial};
8+
use ark_serialize::SerializationError;
89
use ark_std::rand::Rng;
910
use ark_std::rand::rngs::OsRng;
1011
use derive_more::From;
@@ -342,6 +343,19 @@ pub struct PublicKey<C: CurveGroup> {
342343
key: C,
343344
}
344345

346+
impl<C: CurveGroup> PublicKey<C> {
347+
pub fn to_bytes(&self) -> Result<Vec<u8>, SerializationError> {
348+
let mut v = Vec::new();
349+
self.key.serialize_compressed(&mut v)?;
350+
Ok(v)
351+
}
352+
353+
pub fn from_bytes(value: &[u8]) -> Result<Self, SerializationError> {
354+
let key = C::deserialize_compressed(value)?;
355+
Ok(Self { key })
356+
}
357+
}
358+
345359
#[serde_as]
346360
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize, ZeroizeOnDrop, From)]
347361
pub struct KeyShare<C: CurveGroup> {

yapper/src/enc_key.rs renamed to timeboost-utils/src/enc_key.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use reqwest::{Client, Url};
22
use std::collections::HashMap;
3-
use timeboost::crypto::prelude::ThresholdEncKey;
3+
use timeboost_crypto::prelude::ThresholdEncKey;
44

55
use tracing::warn;
66

@@ -28,7 +28,7 @@ async fn fetch_encryption_key(client: &Client, enckey_url: &Url) -> Option<Thres
2828
}
2929

3030
/// helper struct to keep track of sufficient quorum of DKG keys
31-
pub(crate) struct ThresholdEncKeyCellAccumulator {
31+
pub struct ThresholdEncKeyCellAccumulator {
3232
client: Client,
3333
// DKG results on individual node
3434
results: HashMap<Url, Option<ThresholdEncKey>>,
@@ -40,7 +40,7 @@ pub(crate) struct ThresholdEncKeyCellAccumulator {
4040

4141
impl ThresholdEncKeyCellAccumulator {
4242
/// give a list of TimeboostApi's endpoint to query `/enckey` status
43-
pub(crate) fn new(client: Client, urls: impl Iterator<Item = Url>) -> Self {
43+
pub fn new(client: Client, urls: impl Iterator<Item = Url>) -> Self {
4444
let results: HashMap<Url, Option<ThresholdEncKey>> = urls.map(|url| (url, None)).collect();
4545
let threshold = results.len().div_ceil(3);
4646
Self {
@@ -53,7 +53,7 @@ impl ThresholdEncKeyCellAccumulator {
5353

5454
/// try to get the threshold encryption key, only available after a threshold of nodes
5555
/// finish their DKG processes.
56-
pub(crate) async fn enc_key(&mut self) -> Option<&ThresholdEncKey> {
56+
pub async fn enc_key(&mut self) -> Option<&ThresholdEncKey> {
5757
// if result is already available, directly return
5858
if self.output.is_some() {
5959
self.output.as_ref()

timeboost-utils/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod enc_key;
12
pub mod load_generation;
23
pub mod types;
34
pub mod until;

yapper/src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use crate::config::YapperConfig;
2323
use crate::yapper::Yapper;
2424

2525
mod config;
26-
mod enc_key;
2726
mod yapper;
2827

2928
#[derive(Parser, Debug)]

yapper/src/yapper.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ use anyhow::{Context, Result};
1111
use futures::future::join_all;
1212
use reqwest::{Client, Url};
1313
use timeboost::types::BundleVariant;
14+
use timeboost_utils::enc_key::ThresholdEncKeyCellAccumulator;
1415
use timeboost_utils::load_generation::{TxInfo, make_bundle, make_dev_acct_bundle, tps_to_millis};
1516
use tokio::time::interval;
1617
use tracing::warn;
1718

18-
use crate::{config::YapperConfig, enc_key::ThresholdEncKeyCellAccumulator};
19+
use crate::config::YapperConfig;
1920

2021
/// This is the address of the prefunded dev account for nitro chain
2122
/// https://docs.arbitrum.io/run-arbitrum-node/run-local-full-chain-simulation#default-endpoints-and-addresses

0 commit comments

Comments
 (0)