Skip to content

Commit 1200a2f

Browse files
authored
Feature/service persistence (#171)
* validator: adding Diesel ORM * validator: making sure Iron::status is always avaialable * ibid * validator: presence-announcement REST API * validator: adding Diesel setup * Removing Diesel stuff from root of monorepo * validator: adding Diesel migrations and setup * validator: documenting how PresenceAnnouncement is different from presence. * validator: added Chrono crate for datetime conversions into sql * validator: restructured the presence module * validator: removed presence announcements from persistence * validator: commenting topology * Adding staking to the mixmining service * Start of mixmining + stake service * validator: added a bit about mixmining to README * validator: added Iron's params crate * validator: reorganized mixmining service and db code * validator: no need for this .env warning * validator: removing params parser, it's now unused * validator: adding json body parser library for Iron * validator: adding spelling exceptions * validator: adding bodyparser deps * validator: ability to (de)serialize Mixnode struct * validator: further announcement HTTP progress * validator: simplified announcement route * validator: injecting database and service into handler * validator: renaming service and db variables * validator: using camelCase json * validator: using base Iron handler rather than middleware handler * validator: better error message on unexpected json parsing * validator: adding 'location' to presence::Announcement * comments on mixmining::Db * validator: commenting out unused mixmining::Service methods for the moment * validator: noting that we don't yet know how to measure capacity * validator: comments * validator: starting to add correct serializers in rest API * validator: renaming a mixnode announcements * validator: extracted route creation * validator: going lower-case for node in "Mixnode" * validator: removing the "announcement" model * validator: renamed annoucements handlers * validator: temporarily removed Chrono, remove it fully if it's not needed. * validator: added all the needed Mixnode fields to the service model * validator: moved models into their own file. * validator: conversions to/from api vs service models * validator: doing type conversions from rest to service models * validator: unused import cleanup * validator: rewrote mixmining service comments in light of recent thinking * validator: some notes on type conversion tests * wip * validator: getting capacity from db works * wip * validator: eliminating borrows so we can have something pure to mutex out on * validator: a working mutex on the mixmining service * validator: renaming mixmining db get_capacity to capacity * validator: making mixmining db capacity field private, using accessor * validator: local capacity updates working * validator: starting REST API for staking * validator: fixing clippy warning * validator: minor naming fixes on mixmining service * validator: service mixnode and rest mixnode + topology conversions + tests * validator: renaming mix_nodes to mixnodes for consistency * validator: test fixtures for mixnode * validator: moved service models into their own file * validator: a properly-structured toplogy route * validator: topology retrieval * validator: killed test fixture warning * validator: getting set for topology equality checks (testing purposes) * validator: otherway conversions for topology and mixnode types * validator: initial topology retrieval working * validator: ditching go-ish variable name :) * ibid * validator: added a StakeUpdate struct to get around cargo fmt failing * validator: commenting out struct so kill warning * Ignoring validator vscode settings * ibid * ibid
1 parent 9ab2517 commit 1200a2f

File tree

21 files changed

+741
-27
lines changed

21 files changed

+741
-27
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
target
77
.env
88
/.vscode/settings.json
9+
validator/.vscode
910
sample-configs/validator-config.toml

Cargo.lock

+57
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

validator/Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ edition = "2018"
99

1010
[dependencies]
1111
abci = "0.6.4"
12+
bodyparser = "0.8.0"
1213
byteorder = "1.3.2"
1314
clap = "2.33.0"
15+
# chrono = { version = "0.4.11", features = ["serde"] } TODO: remove this if I don't start using it again soon
16+
diesel = { version = "1.4.3", features = ["sqlite"] }
1417
dirs = "2.0.2"
15-
# Read notes https://crates.io/crates/dotenv - tl;dr: don't use in production, set environmental variables properly.
1618
dotenv = "0.15.0"
1719
futures = "0.3.1"
1820
iron = "0.6.1"

validator/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ Nym Validator
44
The Nym Validator has several jobs:
55

66
* use Tendermint (v0.33.0) to maintain a total global ordering of incoming transactions
7-
* track quality of service for mixnet nodes (mixmining)
7+
* rewards + stake slashing based quality of service measurements for mixnet nodes (aka "mixmining")
88
* generate Coconut credentials and ensure they're not double spent
99
* maintain a decentralized directory of all Nym nodes that have staked into the system
10-
10+
1111
Some of these functions may be moved away to their own node types in the future, for example to increase scalability or performance. At the moment, we'd like to keep deployments simple, so they're all in the validator node.
1212

1313
Running the validator on your local machine

validator/diesel.toml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# For documentation on how to configure this file,
2+
# see diesel.rs/guides/configuring-diesel-cli
3+
4+
[print_schema]
5+
file = "src/schema.rs"

validator/migrations/.gitkeep

Whitespace-only changes.
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
use super::*;
4+
use bodyparser::Struct;
5+
use iron::mime::Mime;
6+
use iron::status;
7+
use iron::Handler;
8+
9+
/// Holds data for a capacity update (json)
10+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
11+
#[serde(rename_all = "camelCase")]
12+
pub struct Capacity {
13+
value: usize,
14+
}
15+
16+
pub struct Update {
17+
service: Arc<Mutex<mixmining::Service>>,
18+
}
19+
20+
impl Update {
21+
pub fn new(service: Arc<Mutex<mixmining::Service>>) -> Update {
22+
Update { service }
23+
}
24+
}
25+
26+
impl Handler for Update {
27+
fn handle(&self, req: &mut Request) -> IronResult<Response> {
28+
let json_parse = req.get::<Struct<Capacity>>();
29+
30+
if json_parse.is_ok() {
31+
let capacity = json_parse
32+
.unwrap()
33+
.expect("Unexpected JSON parsing problem")
34+
.value;
35+
self.service.lock().unwrap().set_capacity(capacity);
36+
Ok(Response::with(status::Created))
37+
} else {
38+
let error = json_parse.unwrap_err();
39+
Ok(Response::with((status::BadRequest, error.detail)))
40+
}
41+
}
42+
}
43+
44+
pub struct Get {
45+
service: Arc<Mutex<mixmining::Service>>,
46+
}
47+
48+
impl Get {
49+
pub fn new(service: Arc<Mutex<mixmining::Service>>) -> Get {
50+
Get { service }
51+
}
52+
}
53+
54+
impl Handler for Get {
55+
fn handle(&self, _: &mut Request) -> IronResult<Response> {
56+
let content_type = "application/json".parse::<Mime>().unwrap();
57+
let value = self.service.lock().unwrap().capacity();
58+
let c = Capacity { value };
59+
let json = serde_json::to_string(&c).unwrap();
60+
Ok(Response::with((content_type, status::Ok, json)))
61+
}
62+
}

validator/src/network/rest/mod.rs

+43-14
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,62 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14-
14+
use crate::services::mixmining;
1515
use iron::prelude::*;
16+
use presence::mixnode;
17+
use presence::topology;
1618
use router::Router;
19+
use std::sync::{Arc, Mutex};
1720

18-
mod models;
19-
mod routes;
21+
mod capacity;
22+
mod presence;
23+
mod staking;
2024

21-
pub struct Api {}
25+
pub struct Api {
26+
mixmining_service: Arc<Mutex<mixmining::Service>>,
27+
}
2228

2329
impl Api {
24-
pub fn new() -> Api {
25-
Api {}
30+
pub fn new(mixmining_service: mixmining::Service) -> Api {
31+
let service = Arc::new(Mutex::new(mixmining_service));
32+
Api {
33+
mixmining_service: service,
34+
}
2635
}
2736

37+
/// Run the REST API.
2838
pub async fn run(self) {
29-
let port = 3000;
30-
println!("* starting REST API on localhost:{}", port);
39+
let port = 3000; // TODO: make this configurable
40+
let address = format!("localhost:{}", port);
41+
println!("* starting REST API on http://{}", address);
42+
43+
let router = self.setup_router();
3144

32-
let router = self.setup_routes();
33-
Iron::new(router)
34-
.http(format!("localhost:{}", port))
35-
.unwrap();
45+
Iron::new(router).http(address).unwrap();
3646
}
3747

38-
pub fn setup_routes(&self) -> Router {
48+
/// Tie together URL route paths with handler functions.
49+
fn setup_router(self) -> Router {
50+
// define a Router to hold our routes
3951
let mut router = Router::new();
40-
router.get("/topology", routes::topology::get, "topology_get");
52+
53+
// set up handlers
54+
let capacity_update = capacity::Update::new(Arc::clone(&self.mixmining_service));
55+
let capacity_get = capacity::Get::new(Arc::clone(&self.mixmining_service));
56+
let presence_mixnode_create =
57+
mixnode::CreatePresence::new(Arc::clone(&self.mixmining_service));
58+
let topology_get = topology::GetTopology::new(Arc::clone(&self.mixmining_service));
59+
60+
// tie routes to handlers
61+
router.get("/capacity", capacity_get, "capacity_get");
62+
router.post("/capacity", capacity_update, "capacity_update");
63+
router.get("/topology", topology_get, "topology_get");
64+
router.post(
65+
"/presence/mixnodes",
66+
presence_mixnode_create,
67+
"presence_mixnodes_post",
68+
);
69+
4170
router
4271
}
4372
}

0 commit comments

Comments
 (0)