Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/service persistence #171

Merged
merged 80 commits into from
Apr 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
5ac7454
validator: adding Diesel ORM
futurechimp Mar 17, 2020
e30f3f7
validator: making sure Iron::status is always avaialable
futurechimp Mar 17, 2020
516a32a
ibid
futurechimp Mar 17, 2020
b398c5c
validator: presence-announcement REST API
futurechimp Mar 17, 2020
6dbc755
validator: adding Diesel setup
futurechimp Mar 17, 2020
fd103cd
Removing Diesel stuff from root of monorepo
futurechimp Mar 17, 2020
a0993b4
validator: adding Diesel migrations and setup
futurechimp Mar 17, 2020
6d8f443
validator: documenting how PresenceAnnouncement is different from pre…
futurechimp Mar 17, 2020
03f37f6
validator: added Chrono crate for datetime conversions into sql
futurechimp Mar 17, 2020
53665e3
validator: restructured the presence module
futurechimp Mar 17, 2020
6609439
validator: removed presence announcements from persistence
futurechimp Mar 17, 2020
342bef8
validator: commenting topology
futurechimp Mar 17, 2020
e7cef03
Adding staking to the mixmining service
futurechimp Mar 17, 2020
8c0fca5
Start of mixmining + stake service
futurechimp Mar 17, 2020
73a05ec
validator: added a bit about mixmining to README
futurechimp Mar 17, 2020
97b6a0e
validator: added Iron's params crate
futurechimp Mar 17, 2020
0d17414
validator: reorganized mixmining service and db code
futurechimp Mar 17, 2020
e7730c3
Merge branch 'develop' into feature/diesel-persistence
futurechimp Mar 25, 2020
0d0bc33
validator: no need for this .env warning
futurechimp Mar 25, 2020
7bd7ede
validator: removing params parser, it's now unused
futurechimp Mar 25, 2020
d5eed7e
validator: adding json body parser library for Iron
futurechimp Mar 25, 2020
656f79a
validator: adding spelling exceptions
futurechimp Mar 25, 2020
1a4a43f
validator: adding bodyparser deps
futurechimp Mar 25, 2020
397853c
validator: ability to (de)serialize Mixnode struct
futurechimp Mar 25, 2020
1343af0
validator: further announcement HTTP progress
futurechimp Mar 25, 2020
cb349aa
validator: simplified announcement route
futurechimp Mar 25, 2020
8235ccc
validator: injecting database and service into handler
futurechimp Mar 25, 2020
85397d4
validator: renaming service and db variables
futurechimp Mar 25, 2020
9ff3420
validator: using camelCase json
futurechimp Mar 25, 2020
131e976
validator: using base Iron handler rather than middleware handler
futurechimp Mar 25, 2020
9a96713
validator: better error message on unexpected json parsing
futurechimp Mar 25, 2020
2543516
validator: adding 'location' to presence::Announcement
futurechimp Mar 25, 2020
21bd0e8
comments on mixmining::Db
futurechimp Mar 25, 2020
614b60a
validator: commenting out unused mixmining::Service methods for the m…
futurechimp Mar 25, 2020
9bfa746
validator: noting that we don't yet know how to measure capacity
futurechimp Mar 25, 2020
11d606a
validator: comments
futurechimp Mar 25, 2020
1cbb6f2
validator: starting to add correct serializers in rest API
futurechimp Mar 25, 2020
bdcfe81
validator: renaming a mixnode announcements
futurechimp Mar 25, 2020
a341f52
validator: extracted route creation
futurechimp Mar 26, 2020
b260879
validator: going lower-case for node in "Mixnode"
futurechimp Mar 26, 2020
44a49d1
validator: removing the "announcement" model
futurechimp Mar 26, 2020
c45e85d
validator: renamed annoucements handlers
futurechimp Mar 26, 2020
1d82585
validator: temporarily removed Chrono, remove it fully if it's not ne…
futurechimp Mar 26, 2020
9b9fed7
validator: added all the needed Mixnode fields to the service model
futurechimp Mar 26, 2020
bcac889
validator: moved models into their own file.
futurechimp Mar 26, 2020
1dd7460
validator: conversions to/from api vs service models
futurechimp Mar 26, 2020
348260c
validator: doing type conversions from rest to service models
futurechimp Mar 26, 2020
e7c11d5
validator: unused import cleanup
futurechimp Mar 26, 2020
24f9152
validator: rewrote mixmining service comments in light of recent thin…
futurechimp Mar 26, 2020
ab993d7
validator: some notes on type conversion tests
futurechimp Mar 26, 2020
a65d6b4
wip
futurechimp Mar 27, 2020
98cc48f
validator: getting capacity from db works
futurechimp Mar 31, 2020
9eecac4
wip
futurechimp Mar 31, 2020
d5dea8e
validator: eliminating borrows so we can have something pure to mutex…
futurechimp Apr 2, 2020
522ac8b
validator: a working mutex on the mixmining service
futurechimp Apr 2, 2020
76d7c6d
validator: renaming mixmining db get_capacity to capacity
futurechimp Apr 2, 2020
58c7f52
validator: making mixmining db capacity field private, using accessor
futurechimp Apr 2, 2020
6d7fb2a
validator: local capacity updates working
futurechimp Apr 2, 2020
eba02a0
validator: starting REST API for staking
futurechimp Apr 2, 2020
04d2ac0
validator: fixing clippy warning
futurechimp Apr 2, 2020
dd854d3
validator: minor naming fixes on mixmining service
futurechimp Apr 2, 2020
e43b950
validator: service mixnode and rest mixnode + topology conversions + …
futurechimp Apr 3, 2020
c0231ab
validator: renaming mix_nodes to mixnodes for consistency
futurechimp Apr 3, 2020
afa624c
validator: test fixtures for mixnode
futurechimp Apr 3, 2020
5997556
validator: moved service models into their own file
futurechimp Apr 3, 2020
f81441e
validator: a properly-structured toplogy route
futurechimp Apr 3, 2020
4d4ecb9
validator: topology retrieval
futurechimp Apr 3, 2020
cf5e7bb
validator: killed test fixture warning
futurechimp Apr 3, 2020
b685903
validator: getting set for topology equality checks (testing purposes)
futurechimp Apr 3, 2020
324a6c4
validator: otherway conversions for topology and mixnode types
futurechimp Apr 3, 2020
66bda28
validator: initial topology retrieval working
futurechimp Apr 3, 2020
535ae4a
validator: ditching go-ish variable name :)
futurechimp Apr 3, 2020
d7be512
ibid
futurechimp Apr 3, 2020
36fdbb5
Merge branch 'develop' into feature/service-persistence
futurechimp Apr 3, 2020
36d4f04
validator: added a StakeUpdate struct to get around cargo fmt failing
futurechimp Apr 3, 2020
8737a0e
validator: commenting out struct so kill warning
futurechimp Apr 3, 2020
1986839
Ignoring validator vscode settings
futurechimp Apr 6, 2020
c547751
ibid
futurechimp Apr 6, 2020
2da3a8b
ibid
futurechimp Apr 6, 2020
a4ec792
Merge branch 'develop' into feature/service-persistence
futurechimp Apr 17, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
target
.env
/.vscode/settings.json
validator/.vscode
sample-configs/validator-config.toml
61 changes: 59 additions & 2 deletions Cargo.lock

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

4 changes: 3 additions & 1 deletion validator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ edition = "2018"

[dependencies]
abci = "0.6.4"
bodyparser = "0.8.0"
byteorder = "1.3.2"
clap = "2.33.0"
# chrono = { version = "0.4.11", features = ["serde"] } TODO: remove this if I don't start using it again soon
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will be using this very soon for better time units in config files : )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. I had it in my validator implementation for a little bit, then it came out. I was planning to either delete or uncomment when it become totally clear if I'd really need it.

diesel = { version = "1.4.3", features = ["sqlite"] }
dirs = "2.0.2"
# Read notes https://crates.io/crates/dotenv - tl;dr: don't use in production, set environmental variables properly.
dotenv = "0.15.0"
futures = "0.3.1"
iron = "0.6.1"
Expand Down
4 changes: 2 additions & 2 deletions validator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ Nym Validator
The Nym Validator has several jobs:

* use Tendermint (v0.33.0) to maintain a total global ordering of incoming transactions
* track quality of service for mixnet nodes (mixmining)
* rewards + stake slashing based quality of service measurements for mixnet nodes (aka "mixmining")
* generate Coconut credentials and ensure they're not double spent
* maintain a decentralized directory of all Nym nodes that have staked into the system

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.

Running the validator on your local machine
Expand Down
5 changes: 5 additions & 0 deletions validator/diesel.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# For documentation on how to configure this file,
# see diesel.rs/guides/configuring-diesel-cli

[print_schema]
file = "src/schema.rs"
Empty file added validator/migrations/.gitkeep
Empty file.
62 changes: 62 additions & 0 deletions validator/src/network/rest/capacity/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use serde::{Deserialize, Serialize};

use super::*;
use bodyparser::Struct;
use iron::mime::Mime;
use iron::status;
use iron::Handler;

/// Holds data for a capacity update (json)
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Capacity {
value: usize,
}

pub struct Update {
service: Arc<Mutex<mixmining::Service>>,
}

impl Update {
pub fn new(service: Arc<Mutex<mixmining::Service>>) -> Update {
Update { service }
}
}

impl Handler for Update {
fn handle(&self, req: &mut Request) -> IronResult<Response> {
let json_parse = req.get::<Struct<Capacity>>();

if json_parse.is_ok() {
let capacity = json_parse
.unwrap()
.expect("Unexpected JSON parsing problem")
.value;
self.service.lock().unwrap().set_capacity(capacity);
Ok(Response::with(status::Created))
} else {
let error = json_parse.unwrap_err();
Ok(Response::with((status::BadRequest, error.detail)))
}
}
}

pub struct Get {
service: Arc<Mutex<mixmining::Service>>,
}

impl Get {
pub fn new(service: Arc<Mutex<mixmining::Service>>) -> Get {
Get { service }
}
}

impl Handler for Get {
fn handle(&self, _: &mut Request) -> IronResult<Response> {
let content_type = "application/json".parse::<Mime>().unwrap();
let value = self.service.lock().unwrap().capacity();
let c = Capacity { value };
let json = serde_json::to_string(&c).unwrap();
Ok(Response::with((content_type, status::Ok, json)))
}
}
57 changes: 43 additions & 14 deletions validator/src/network/rest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,62 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::services::mixmining;
use iron::prelude::*;
use presence::mixnode;
use presence::topology;
use router::Router;
use std::sync::{Arc, Mutex};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be entirely wrong about this, but this is based on some random comments on the internet I've read (so the most reliable source there is), but I think in an async setup, like we have here, i.e. tokio runtime, we want to be using this mutex: https://docs.rs/futures/0.3.4/futures/lock/struct.Mutex.html . As from what I understand, waiting for std::sync::Mutex blocks more stuff than necessary, while futures::lock::Mutex affects only this particular [tokio] task.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am blocking way more than I need to anyway - I'm planning to move the mutex from the Service (where it is now) to the level of each individual datastore (when those exist), because right now every request is basically going to hit the mutex for every other request. I'll switch mutexes when I do that next bit of work (right now I only have 1 datastore so it doesn't really make much difference) - if you happen to have the source on the futures vs std mutex please shoot it to me in Keybase, I'm interested to see!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be totally wrong about this, however, based on some comments I've read on the internet (so the most reliable source on the planet), you want to be using this mutex: https://docs.rs/futures/0.3.4/futures/lock/struct.Mutex.html . As from what I understand, std::sync::Mutex would block the whole thread what could lead to blocking async executor hence causing a deadlock. Meanwhile futures::lock::Mutex would simply return Poll::Pending and cause the Future (or tokio task) to be polled again at later time.


mod models;
mod routes;
mod capacity;
mod presence;
mod staking;

pub struct Api {}
pub struct Api {
mixmining_service: Arc<Mutex<mixmining::Service>>,
}

impl Api {
pub fn new() -> Api {
Api {}
pub fn new(mixmining_service: mixmining::Service) -> Api {
let service = Arc::new(Mutex::new(mixmining_service));
Api {
mixmining_service: service,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at how many places are using Arc<Mutex<mixmining_service>> perhaps we could make it into a type alias?

}
}

/// Run the REST API.
pub async fn run(self) {
let port = 3000;
println!("* starting REST API on localhost:{}", port);
let port = 3000; // TODO: make this configurable
let address = format!("localhost:{}", port);
println!("* starting REST API on http://{}", address);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we be consistent and use log for those messages? : )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a difference between log messages (which I think are mostly for developers) and output messages (which should always exist and not be configurable by log level). There is no situation in which I ever want the startup messages about components to not print out (e.g. if somebody knocked log level down).

I think maybe we need to argue this one out a bit more, but I'd say the reverse: some of the things that are currently configured as log messages actually are not - they're important messages from the running system to the user. Things like major subsystems starting, progress messages etc are not things that I think should be configurable as log messages.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we be consistent and use log for those messages? : )


let router = self.setup_router();

let router = self.setup_routes();
Iron::new(router)
.http(format!("localhost:{}", port))
.unwrap();
Iron::new(router).http(address).unwrap();
}

pub fn setup_routes(&self) -> Router {
/// Tie together URL route paths with handler functions.
fn setup_router(self) -> Router {
// define a Router to hold our routes
let mut router = Router::new();
router.get("/topology", routes::topology::get, "topology_get");

// set up handlers
let capacity_update = capacity::Update::new(Arc::clone(&self.mixmining_service));
let capacity_get = capacity::Get::new(Arc::clone(&self.mixmining_service));
let presence_mixnode_create =
mixnode::CreatePresence::new(Arc::clone(&self.mixmining_service));
let topology_get = topology::GetTopology::new(Arc::clone(&self.mixmining_service));

// tie routes to handlers
router.get("/capacity", capacity_get, "capacity_get");
router.post("/capacity", capacity_update, "capacity_update");
router.get("/topology", topology_get, "topology_get");
router.post(
"/presence/mixnodes",
presence_mixnode_create,
"presence_mixnodes_post",
);

router
}
}
Loading