Skip to content

Commit

Permalink
swapd: Add project skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
parazyd committed Dec 7, 2023
1 parent b2c4000 commit 5a526fe
Show file tree
Hide file tree
Showing 10 changed files with 315 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
/bin/lilith/lilith
/lilith

/bin/swapd/swapd
/swapd

/bin/tau/taud/taud
/taud

Expand Down
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ members = [
"bin/genev/genevd",
"bin/genev/genev-cli",
"bin/darkirc",
"bin/swapd",
"bin/tau/taud",
#"bin/tau/tau-cli",
"bin/vanityaddr",
Expand Down
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ BINS = \
genev \
genevd \
lilith \
swapd \
taud \
vanityaddr

Expand Down Expand Up @@ -87,6 +88,13 @@ lilith:
RUST_TARGET="$(RUST_TARGET)" \
RUSTFLAGS="$(RUSTFLAGS)"

swapd:
$(MAKE) -C bin/$@ \
PREFIX="$(PREFIX)" \
CARGO="$(CARGO)" \
RUST_TARGET="$(RUST_TARGET)" \
RUSTFLAGS="$(RUSTFLAGS)"

taud:
$(MAKE) -C bin/tau/$@ \
PREFIX="$(PREFIX)" \
Expand Down Expand Up @@ -142,6 +150,7 @@ clean:
$(MAKE) -C bin/genev/genev-cli clean
$(MAKE) -C bin/genev/genevd clean
$(MAKE) -C bin/lilith clean
$(MAKE) -C bin/swapd clean
$(MAKE) -C bin/tau/taud clean
$(MAKE) -C bin/vanityaddr clean
RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) clean --target=$(RUST_TARGET) --release
Expand Down
34 changes: 34 additions & 0 deletions bin/swapd/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[package]
name = "swapd"
version = "0.4.1"
homepage = "https://dark.fi"
description = "Atomic Swap Daemon"
authors = ["Dyne.org foundation <[email protected]>"]
repository = "https://github.com/darkrenaissance/darkfi"
license = "AGPL-3.0-only"
edition = "2021"

[dependencies]
darkfi = {path = "../../", features = ["async-daemonize", "async-serial", "system", "util", "net", "rpc", "sled"]}
darkfi-serial = {path = "../../src/serial", features = ["async"]}

# Misc
log = "0.4.20"

# Encoding
url = "2.5.0"

# Database
sled = "0.34.7"

# Daemon
easy-parallel = "3.3.1"
signal-hook-async-std = "0.2.2"
signal-hook = "0.3.17"
simplelog = "0.12.1"
smol = "1.3.0"

# Argument parsing
serde = {version = "1.0.193", features = ["derive"]}
structopt = "0.3.26"
structopt-toml = "0.5.1"
41 changes: 41 additions & 0 deletions bin/swapd/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.POSIX:

# Install prefix
PREFIX = $(HOME)/.cargo

# Cargo binary
CARGO = cargo +nightly

# Compile target
RUST_TARGET = $(shell rustc -Vv | grep '^host: ' | cut -d' ' -f2)
# Uncomment when doing musl static builds
#RUSTFLAGS = -C target-feature=+crt-static -C link-self-contained=yes

SRC = \
Cargo.toml \
../../Cargo.toml \
$(shell find src -type f -name '*.rs') \
$(shell find ../../src -type f -name '*.rs') \

BIN = $(shell grep '^name = ' Cargo.toml | cut -d' ' -f3 | tr -d '"')

all: $(BIN)

$(BIN): $(SRC)
RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) build --target=$(RUST_TARGET) --release --package $@
cp -f ../../target/$(RUST_TARGET)/release/$@ $@
cp -f ../../target/$(RUST_TARGET)/release/$@ ../../$@

clean:
RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) clean --target=$(RUST_TARGET) --release --package $(BIN)
rm -f $(BIN) ../../$(BIN)

install: all
mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin
chmod 755 $(DESTDIR)$(PREFIX)/bin/$(BIN)

uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN)

.PHONY: all clean install uninstall
Binary file added bin/swapd/darkfi-swapd
Binary file not shown.
127 changes: 127 additions & 0 deletions bin/swapd/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/* This file is part of DarkFi (https://dark.fi)
*
* Copyright (C) 2020-2023 Dyne.org foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use std::{collections::HashSet, sync::Arc};

use darkfi::{
async_daemonize, cli_desc,
rpc::server::{listen_and_serve, RequestHandler},
system::{StoppableTask, StoppableTaskPtr},
util::path::expand_path,
Error, Result,
};
use log::{error, info};
use serde::Deserialize;
use smol::{fs, lock::Mutex, stream::StreamExt, Executor};
use structopt::StructOpt;
use structopt_toml::StructOptToml;
use url::Url;

const CONFIG_FILE: &str = "swapd.toml";
const CONFIG_FILE_CONTENTS: &str = include_str!("../swapd.toml");

/// JSON-RPC server methods
mod rpc;

#[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
#[serde(default)]
#[structopt(name = "darkfi-mmproxy", about = cli_desc!())]
struct Args {
#[structopt(short, parse(from_occurrences))]
/// Increase verbosity (-vvv supported)
verbose: u8,

#[structopt(short, long)]
/// Configuration file to use
config: Option<String>,

#[structopt(long)]
/// Set log file output
log: Option<String>,

#[structopt(flatten)]
swapd: SwapdArgs,
}

#[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
#[structopt()]
struct SwapdArgs {
#[structopt(long, default_value = "tcp://127.0.0.1:52821")]
/// darkfi-swapd JSON-RPC listen URL
swapd_rpc: Url,

#[structopt(long, default_value = "~/.local/darkfi/swapd")]
/// Path to swapd's filesystem database
swapd_db: String,
}

/// Swapd daemon state
struct Swapd {
/// Main reference to the swapd filesystem databaase
_sled_db: sled::Db,
/// JSON-RPC connection tracker
rpc_connections: Mutex<HashSet<StoppableTaskPtr>>,
}

impl Swapd {
/// Instantiate `Swapd` state
async fn new(_swapd_args: &SwapdArgs, sled_db: sled::Db) -> Result<Self> {
Ok(Self { _sled_db: sled_db, rpc_connections: Mutex::new(HashSet::new()) })
}
}

async_daemonize!(realmain);
async fn realmain(args: Args, ex: Arc<Executor<'static>>) -> Result<()> {
info!("Starting DarkFi Atomic Swap Daemon...");

// Create datastore path if not there already.
let datastore = expand_path(&args.swapd.swapd_db)?;
fs::create_dir_all(&datastore).await?;
let sled_db = sled::open(datastore)?;

info!("Initializing daemon state");
let swapd = Arc::new(Swapd::new(&args.swapd, sled_db.clone()).await?);

info!("Starting JSON-RPC server on {}", args.swapd.swapd_rpc);
let swapd_ = Arc::clone(&swapd);
let rpc_task = StoppableTask::new();
rpc_task.clone().start(
listen_and_serve(args.swapd.swapd_rpc, swapd.clone(), None, ex.clone()),
|res| async move {
match res {
Ok(()) | Err(Error::RpcServerStopped) => swapd_.stop_connections().await,
Err(e) => error!("Failed stopping JSON-RPC server: {}", e),
}
},
Error::RpcServerStopped,
ex.clone(),
);

info!("Ready to operate");

// Signal handling for graceful termination.
let (signals_handler, signals_task) = SignalHandler::new(ex)?;
signals_handler.wait_termination(signals_task).await?;
info!("Caught termination signal, cleaning up and exiting");

info!("Flushing sled database");
sled_db.flush_async().await?;

info!("Shut down successfully");
Ok(())
}
67 changes: 67 additions & 0 deletions bin/swapd/src/rpc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* This file is part of DarkFi (https://dark.fi)
*
* Copyright (C) 2020-2023 Dyne.org foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use std::collections::HashSet;

use darkfi::{
rpc::{
jsonrpc::{ErrorCode, JsonError, JsonRequest, JsonResponse, JsonResult},
server::RequestHandler,
util::JsonValue,
},
system::StoppableTaskPtr,
};
use darkfi_serial::async_trait;
use smol::lock::MutexGuard;

use super::Swapd;

#[async_trait]
impl RequestHandler for Swapd {
async fn handle_request(&self, req: JsonRequest) -> JsonResult {
match req.method.as_str() {
"ping" => self.pong(req.id, req.params).await,
"hello" => self.hello(req.id, req.params).await,
_ => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
}
}

async fn connections_mut(&self) -> MutexGuard<'_, HashSet<StoppableTaskPtr>> {
self.rpc_connections.lock().await
}
}

impl Swapd {
// RPCAPI:
// Use this kind of comment in order to have the RPC spec automatically
// generated in the mdbook. You should be able to write any kind of
// markdown in here.
//
// At the bottom, you should have the reqrep in JSON:
//
// --> {"jsonrpc": "2.0", "method": "hello", "params": ["hello"], "id": 42}
// --> {"jsonrpc": "2.0", "result": "hello", "id": 42}
async fn hello(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
if params.len() != 1 || !params[0].is_string() {
return JsonError::new(ErrorCode::InvalidParams, None, id).into()
}

return JsonResponse::new(params[0].clone(), id).into()
}
}
14 changes: 14 additions & 0 deletions bin/swapd/swapd.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
## darkfi-swapd configuration file
##
## Please make sure you go through all the settings so you can configure
## your daemon properly.
##
## The default values are left commented. They can be overridden either by
## uncommenting, or by using the command-line.

#[swapd]
# darkfi-swapd JSON-RPC listen URL.
#swapd_rpc = "tcp://127.0.0.1:52821"

# Path to swapd's filesystem database
#swapd_db = "~/.local/darkfi/swapd"

0 comments on commit 5a526fe

Please sign in to comment.