Skip to content

Commit 448ecde

Browse files
authored
feat: Dockerise the code and create Github CI (#2)
Dockerises the code for the drand-rs Adds a CI for github for easy deployments
1 parent 234bdb7 commit 448ecde

29 files changed

+1010
-1200
lines changed

Diff for: .dockerignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.env

Diff for: .gitattributes

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
src/protobuf/* linguist-generated=true

Diff for: .github/workflows/prod.yml

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Drand
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
11+
env:
12+
CARGO_TERM_COLOR: always
13+
14+
jobs:
15+
build-arkworks:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v2
19+
- name: Install protobuf-compiler
20+
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
21+
- name: Install Rust
22+
uses: actions-rs/toolchain@v1
23+
with:
24+
profile: minimal
25+
toolchain: stable
26+
override: true
27+
components: rustfmt, clippy
28+
- name: Build with arkworks
29+
run: cargo build --release --verbose --features arkworks
30+
- name: Test with arkworks
31+
run: cargo test --release --verbose --features arkworks
32+
- name: Lint with arkworks
33+
run: cargo clippy --release --features arkworks
34+
- name: Build Docker image with arkworks
35+
run: docker build --build-arg FEATURES=arkworks -t drand:arkworks .
36+
37+
build-blstrs:
38+
runs-on: ubuntu-latest
39+
steps:
40+
- uses: actions/checkout@v2
41+
- name: Install protobuf-compiler
42+
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
43+
- name: Install Rust
44+
uses: actions-rs/toolchain@v1
45+
with:
46+
profile: minimal
47+
toolchain: stable
48+
override: true
49+
components: rustfmt, clippy
50+
- name: Build with blstrs
51+
run: cargo build --release --verbose --features blstrs
52+
- name: Test with blstrs
53+
run: cargo test --release --verbose --features blstrs
54+
- name: Lint with blstrs
55+
run: cargo clippy --release --features blstrs
56+
- name: Build Docker image with blstrs
57+
run: docker build --build-arg FEATURES=blstrs -t drand:blstrs .

Diff for: Dockerfile

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Use the official Rust image as the base image
2+
FROM rust:latest AS builder
3+
4+
# Set the working directory
5+
WORKDIR /app
6+
7+
# Install protobuf compiler
8+
RUN apt-get update && apt-get install -y protobuf-compiler
9+
10+
# Copy the current directory contents into the container at /app
11+
COPY . .
12+
13+
#default build is arkworks if not specified otherwise
14+
ARG FEATURES=arkworks
15+
16+
# Build the application
17+
RUN cargo build --release --features ${FEATURES}
18+
19+
# Use the official Golang image to download the binary
20+
FROM golang:latest AS golang_builder
21+
22+
# Set the working directory inside the container
23+
WORKDIR /app
24+
25+
# Download the golang binary (needed when we run from latest releases)
26+
# RUN wget https://github.com/drand/drand/releases/download/v1.5.8/drand_1.5.8_linux_amd64.tar.gz && \
27+
# tar -xzf drand_1.5.8_linux_amd64.tar.gz && \
28+
# mkdir -p /app/make_demo && \
29+
# mv drand /app/make_demo/drand_go
30+
31+
# Use Ubuntu as the final base image
32+
FROM ubuntu:22.04
33+
34+
# Set the working directory
35+
WORKDIR /app/make_demo
36+
37+
# Copy the compiled Rust binary from the builder stage
38+
COPY --from=builder /app/target/release/drand /app/make_demo/drand_rs
39+
40+
# Copy the Golang binary from the golang_builder stage
41+
# COPY --from=golang_builder /app/make_demo/drand_go /app/make_demo/drand_go
42+
43+
# Copy only the necessary files from make_demo
44+
COPY make_demo/drand_go .
45+
COPY make_demo/stop .
46+
COPY make_demo/run .
47+
48+
# Install any necessary runtime dependencies
49+
RUN apt-get update && apt-get install -y libssl-dev ca-certificates && rm -rf /var/lib/apt/lists/*
50+
51+
# Make the run script executable
52+
RUN chmod +x run
53+
54+
# Set the entrypoint to the run script
55+
ENTRYPOINT ["./run"]

Diff for: README.md

+26
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Notice
2+
3+
Main branch currently support the drand-go 1.5.8 binary . To check for versions greater than this , look into the other branches
4+
15
# drand-rs
26

37
**This project is currently at the prototype stage and does not contain full functionality. Codebase uploaded only for demonstration purpose and does not reflect the final quiality. For production usage, please visit [Drand Golang implementation](https://github.com/drand/drand)**
@@ -55,3 +59,25 @@ Number of nodes can be modified for various scenaries, for example:
5559
```
5660
[video: 4-7-10 nodes group](https://drive.google.com/file/d/191rzucL5gX529J6PMfG5YfpZej6GoWQV/view?usp=drive_link)
5761

62+
## How to run Docker image
63+
64+
Build the image
65+
66+
```
67+
docker build -t drand-rs .
68+
```
69+
70+
Check if the image is created
71+
72+
```
73+
docker images
74+
```
75+
76+
Run the docker image
77+
78+
```
79+
docker run --rm -it drand-rs
80+
#or
81+
docker compose up
82+
```
83+

Diff for: docker-compose.yml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
version: '3.8'
2+
3+
services:
4+
drand:
5+
build:
6+
context: .
7+
dockerfile: Dockerfile
8+
volumes:
9+
- ./make_demo:/app/make_demo
10+
working_dir: /app/make_demo
11+
entrypoint: ["./run"]

Diff for: rustfmt.toml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
use_small_heuristics = "Max"
2+

Diff for: src/cli.rs

+6-25
Original file line numberDiff line numberDiff line change
@@ -146,47 +146,28 @@ impl Cli {
146146
pub async fn run(self) -> anyhow::Result<()> {
147147
init_log(self.verbose)?;
148148
match self.commands {
149-
Commands::GenerateKeypair {
150-
folder,
151-
id,
152-
scheme,
153-
address,
154-
tls_disable,
155-
} => {
149+
Commands::GenerateKeypair { folder, id, scheme, address, tls_disable } => {
156150
// - Default boolean value is true, omitting '--tls_disable' leads to tls_disable:true
157151
// - We want to keep CLI in sync with golang implementation
158152
// - From here tls:true means tls enabled, this can probably be done more elegantly
159153
let tls = !tls_disable;
160154
crate::core::schemes::gen_keypair(scheme, &folder, tls, id, address)?
161155
}
162-
Commands::Start {
163-
folder,
164-
id,
165-
private_listen,
166-
control,
167-
} => control::start(&folder, id, &control, private_listen).await?,
156+
Commands::Start { folder, id, private_listen, control } => {
157+
control::start(&folder, id, &control, private_listen).await?
158+
}
168159

169160
Commands::Stop { control, id } => control::stop(&control, id.as_ref()).await?,
170161

171162
Commands::Show(show) => match show {
172163
Show::Public { control, id } => control::public_key_request(&control, id).await?,
173164
},
174165
Commands::Util(util) => match util {
175-
Util::Check {
176-
tls_disable,
177-
id,
178-
addresses,
179-
} => todo!(),
166+
Util::Check { tls_disable, id, addresses } => todo!(),
180167
Util::ListSchemes { control } => control::list_schemes(&control).await?,
181168
Util::PoolInfo { control } => control::pool_info(&control).await?,
182169
},
183-
Commands::Share {
184-
control,
185-
leader,
186-
id,
187-
tls_disable,
188-
connect,
189-
} => {
170+
Commands::Share { control, leader, id, tls_disable, connect } => {
190171
// - Default boolean value is true, omitting '--tls_disable' leads to tls_disable:true
191172
// - We want to keep CLI in sync with golang implementation
192173
// - From here tls:true means tls enabled, this can probably be done more elegantly

Diff for: src/core/beacon.rs

+5-23
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,7 @@ impl<S: Scheme> Beacon<S> {
125125
) -> Self {
126126
let span = info_span!("", id = format!("{private_listen}.{id}"));
127127

128-
Self(Arc::new(InnerNode {
129-
beacon_id: id.clone(),
130-
fs,
131-
keypair,
132-
pool,
133-
span,
134-
}))
128+
Self(Arc::new(InnerNode { beacon_id: id.clone(), fs, keypair, pool, span }))
135129
}
136130

137131
pub fn start(self, mut rx: Receiver<BeaconCmd>) {
@@ -299,18 +293,11 @@ impl<S: Scheme> Beacon<S> {
299293
secret: &[u8],
300294
) -> Result<DkgConfig<S>> {
301295
if secret != p.secret_proof {
302-
bail!(
303-
"secret_proof is not valid, beacon_id: {}",
304-
self.beacon_id.as_str()
305-
);
296+
bail!("secret_proof is not valid, beacon_id: {}", self.beacon_id.as_str());
306297
}
307298

308299
if p.new_group.scheme_id != S::ID {
309-
bail!(
310-
"invalid scheme, expected: {}, received: {}",
311-
S::ID,
312-
p.new_group.scheme_id,
313-
);
300+
bail!("invalid scheme, expected: {}, received: {}", S::ID, p.new_group.scheme_id,);
314301
}
315302
let leader_key = Affine::deserialize(leader_key)?;
316303

@@ -321,10 +308,7 @@ impl<S: Scheme> Beacon<S> {
321308
}
322309
let group: Group<S> = p.new_group.try_into()?;
323310
let Some(dkg_index) = group.find_index(self.keypair.public()) else {
324-
bail!(
325-
"local node {} is not found in group_file",
326-
self.keypair.public().address()
327-
)
311+
bail!("local node {} is not found in group_file", self.keypair.public().address())
328312
};
329313

330314
Ok(DkgConfig::new(leader_key, group, p.dkg_timeout, dkg_index))
@@ -333,9 +317,7 @@ impl<S: Scheme> Beacon<S> {
333317

334318
impl From<String> for BeaconID {
335319
fn from(value: String) -> Self {
336-
Self {
337-
inner: value.into(),
338-
}
320+
Self { inner: value.into() }
339321
}
340322
}
341323

Diff for: src/core/chain.rs

+3-15
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,7 @@ impl<S: Scheme> ChainHandler<S> {
118118

119119
async fn add_partial(&mut self, p: PartialBeaconPacket) -> Result<()> {
120120
let sig_sh = SigShare::deserialize(&p.partial_sig)?;
121-
if self
122-
.sigs_buf
123-
.iter()
124-
.any(|stored| stored.index() == sig_sh.index())
125-
{
121+
if self.sigs_buf.iter().any(|stored| stored.index() == sig_sh.index()) {
126122
debug!(parent: self.node.span(), "ignoring dublicated partial, index: {}, round: {}", sig_sh.index(), p.round);
127123
return Ok(());
128124
}
@@ -135,11 +131,7 @@ impl<S: Scheme> ChainHandler<S> {
135131
let msg = S::Beacon::digest(&p.previous_signature, p.round);
136132
let key = &self.share.public().eval(sig_sh.index()).v;
137133
if S::bls_verify(key, sig_sh.value(), &msg).is_err() {
138-
bail!(
139-
"invalid bls signarure, index: {}, round: {}",
140-
sig_sh.index(),
141-
p.round
142-
);
134+
bail!("invalid bls signarure, index: {}, round: {}", sig_sh.index(), p.round);
143135
}
144136

145137
debug!(parent: self.node.span(), "Added valid partial, index: {}, round: {}, last_stored.round: {}", sig_sh.index(), p.round, self.last_stored.round);
@@ -183,11 +175,7 @@ impl<S: Scheme> ChainHandler<S> {
183175
metadata: From::from(&self.node.beacon_id),
184176
};
185177

186-
if !self
187-
.sigs_buf
188-
.iter()
189-
.any(|stored| stored.index() == our_partial.index())
190-
{
178+
if !self.sigs_buf.iter().any(|stored| stored.index() == our_partial.index()) {
191179
self.try_recover(our_partial, &msg);
192180
}
193181
let _ = self.node.pool.send(PoolCmd::Partial(packet)).await;

Diff for: src/core/daemon.rs

+4-17
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,7 @@ impl Daemon {
5454
let pool = Pool::start(false, logger.register_pool());
5555
let beacons = MultiBeacon::new(beacon_id, base_folder, &private_listen, pool.clone())?;
5656
let (stop_daemon, _) = tokio::sync::broadcast::channel::<()>(1);
57-
let daemon = Self {
58-
beacons,
59-
stop_daemon,
60-
logger,
61-
private_listen,
62-
pool,
63-
};
57+
let daemon = Self { beacons, stop_daemon, logger, private_listen, pool };
6458

6559
Ok(Arc::new(daemon))
6660
}
@@ -127,9 +121,7 @@ impl Daemon {
127121
.await
128122
.map_err(|e| Status::invalid_argument(e.to_string()))?;
129123

130-
callback
131-
.await
132-
.map_or_else(|_| Err(Status::internal(INTERNAL_ERR)), Ok)
124+
callback.await.map_or_else(|_| Err(Status::internal(INTERNAL_ERR)), Ok)
133125
}
134126

135127
pub async fn broadcast_dkg_bundle(&self, bundle: Bundle, id: &str) -> Result<(), Status> {
@@ -166,14 +158,9 @@ impl Daemon {
166158

167159
pub async fn pool_status(&self) -> Result<String, Status> {
168160
let (sender, callback) = oneshot::channel();
169-
self.pool
170-
.send(PoolCmd::Status(sender))
171-
.await
172-
.map_err(|e| Status::from_error(e.into()))?;
161+
self.pool.send(PoolCmd::Status(sender)).await.map_err(|e| Status::from_error(e.into()))?;
173162

174-
callback
175-
.await
176-
.map_or_else(|_| Err(Status::internal(INTERNAL_ERR)), Ok)
163+
callback.await.map_or_else(|_| Err(Status::internal(INTERNAL_ERR)), Ok)
177164
}
178165
}
179166

0 commit comments

Comments
 (0)