From b6ca182e1c48ea00c9499afc1cb508a3687372cb Mon Sep 17 00:00:00 2001 From: tomossomot Date: Thu, 31 Oct 2019 16:29:22 +0000 Subject: [PATCH 01/40] script descriptions --- examples/demo.rs | 7 ++++++- scripts/create_request.sh | 9 +++++++++ scripts/demo.sh | 5 +++++ scripts/report.py | 10 +++++++++- 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/examples/demo.rs b/examples/demo.rs index e941f2b..923f602 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -1,4 +1,9 @@ //! Simple demo of coordinator with mock guard node +//! +//! Demo Coordinator connects to demo client chain (can be built by running +//! ./scripts/demo.sh) and sends challenges to mock guardnodes that made bids. +//! When guardnode responses are received by coordinator they are verified and +//! can be stored ready for fee payments to be made. #[macro_use] extern crate log; @@ -68,7 +73,7 @@ fn main() { for bid in client_rpc.get_request_bids(&request_txid).unwrap().unwrap().bids { if bid.fee_pub_key.to_string() == guardnode_pubkey { guardnode_txid = bid.txid; - println!("guardnode bid txid: {}", guardnode_txid); + println!("Guardnode bid txid: {}", guardnode_txid); break; } } diff --git a/scripts/create_request.sh b/scripts/create_request.sh index 72000b5..6fca816 100755 --- a/scripts/create_request.sh +++ b/scripts/create_request.sh @@ -1,3 +1,12 @@ +# Script builds, signs and sends a request transaction on service chain whose +# connectivity information is specified in $RPC_USER, RPC_PASS, RPC_CONNECT, +# and RPC_PORT env variables from the local ocean wallet. +# +# Several checks are made for validity of given arguments. If all is well then an +# unspent permission asset output is found (or provided in argument 9 and 10) and +# used as input to a raw request tx. The request is broadcast and its spending script +# address imported to the wallet to allow for automatic renewal of the request. + #!/bin/bash shopt -s expand_aliases alias ocl="$HOME/jsonrpc-cli/jsonrpc-cli --user=$RPC_USER --pass=$RPC_PASS --format=jsonpretty --resultonly=on --highlight=off http://$RPC_CONNECT:$RPC_PORT/" diff --git a/scripts/demo.sh b/scripts/demo.sh index 525b3e7..bb56203 100755 --- a/scripts/demo.sh +++ b/scripts/demo.sh @@ -1,3 +1,8 @@ +# Script spins up new chain with datadir=~/co-client-dir/ and creates a new +# demo request transaction along with 2 bids. This can be used to initialise +# exmples/demo.rs to perform coordinator functionality on a mock client and service +# chain. + #!/bin/bash shopt -s expand_aliases diff --git a/scripts/report.py b/scripts/report.py index b4dc02b..849ed6b 100755 --- a/scripts/report.py +++ b/scripts/report.py @@ -1,3 +1,11 @@ +# Script to generate report of responses from guardnodes using +# coordinator RPC API interface. +# +# First connection to a local Ocean node is made, the request data for a +# txid is found via getrequest RPC and fee size is calculated. +# Then getrequestresponses RPC is called to get challenge responses which can be +# used to determine rewards for guardnodes. + #!/usr/bin/env python3 import requests import json @@ -135,4 +143,4 @@ def calculate_fees(rpc, start_height, end_height): performance = resps[bid] print("Bid {0}\npubkey: {1}\naddress: {2}\nperformance: {3:.2f}%\nreward: {4}\n".\ format(bid, key, key_to_p2pkh(key, addr_prefix), 100*performance, fee_per_guard*performance)) -print("End") \ No newline at end of file +print("End") From 650205481fb6f465680e8393df5a3e4427dcd56c Mon Sep 17 00:00:00 2001 From: tomossomot <55086152+tomossomot@users.noreply.github.com> Date: Mon, 11 Nov 2019 10:29:50 +0000 Subject: [PATCH 02/40] Enhancements (#46) * move doc format util into own file * issue 45 * tests and fmt * explicit db indexes - issue 44 * only set end_blockheight once * fmt * Add clientchain height fields to Request model, other PR changes * PR improvements * staorage tests and move into storage.rs * check for request already in db before storing * fmt * remove storage test, correct comments --- src/api.rs | 6 +- src/challenger.rs | 41 +++++++- src/clientchain.rs | 6 ++ src/coordinator.rs | 17 +++- src/lib.rs | 1 + src/request.rs | 6 ++ src/storage.rs | 208 ++++++++--------------------------------- src/util/doc_format.rs | 184 ++++++++++++++++++++++++++++++++++++ src/util/testing.rs | 42 +++++++-- 9 files changed, 324 insertions(+), 187 deletions(-) create mode 100644 src/util/doc_format.rs diff --git a/src/api.rs b/src/api.rs index 1b7581e..2b6d094 100644 --- a/src/api.rs +++ b/src/api.rs @@ -185,7 +185,7 @@ mod tests { let resp = get_request(params, storage.clone()); assert_eq!( format!( - r#"{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}}"#, + r#"{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}}"#, dummy_hash.to_string() ), resp.wait().unwrap() @@ -207,7 +207,7 @@ mod tests { let resp = get_requests(storage.clone()); assert_eq!( format!( - r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}}]}}"#, + r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}}]}}"#, dummy_hash.to_string() ), resp.wait().unwrap() @@ -219,7 +219,7 @@ mod tests { let resp = get_requests(storage.clone()); assert_eq!( format!( - r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}},{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}}]}}"#, + r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}},{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}}]}}"#, dummy_hash.to_string(), dummy_hash2.to_string() ), diff --git a/src/challenger.rs b/src/challenger.rs index 5deab01..88162b7 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -95,13 +95,15 @@ pub fn run_challenge_request( challenge_frequency: u64, refresh_delay: time::Duration, ) -> Result<()> { - let request = challenge_state.lock().unwrap().request.clone(); // clone as const and drop mutex - info! {"Running challenge request: {:?}", request}; + let mut request = challenge_state.lock().unwrap().request.clone(); // clone as const and drop mutex + info! {"Running challenge request: {:?}", request.txid}; let mut prev_challenge_height: u64 = 0; loop { let challenge_height = service.get_blockheight()?; info! {"service chain height: {}", challenge_height} if (request.end_blockheight as u64) < challenge_height { + request.end_blockheight_clientchain = clientchain.get_block_count()?; + storage.update_request(request)?; break; } else if (challenge_height - prev_challenge_height) < challenge_frequency { info! {"Sleeping for {} sec...",time::Duration::as_secs(&refresh_delay)} @@ -360,17 +362,18 @@ mod tests { let dummy_hash = gen_dummy_hash(0); let dummy_other_hash = gen_dummy_hash(9); - let dummy_request = service.get_request(&dummy_hash).unwrap().unwrap(); + let mut dummy_request = service.get_request(&dummy_hash).unwrap().unwrap(); // test normal operation of run_challenge_request by adding some responses for // the first challenge let _ = service.height.replace(dummy_request.start_blockheight as u64); // set height for fetch_next to succeed - let challenge_state = fetch_next(&service, &dummy_hash).unwrap().unwrap(); + + let mut challenge_state = fetch_next(&service, &dummy_hash).unwrap().unwrap(); storage.save_challenge_state(&challenge_state).unwrap(); let (vtx, vrx): (Sender, Receiver) = channel(); - let _ = clientchain.height.replace((dummy_request.start_blockheight as u64) + 1); // set height +1 for challenge hash response + let _ = clientchain.height.replace((dummy_request.start_blockheight) + 1); // set height +1 for challenge hash response let dummy_challenge_hash = clientchain.send_challenge().unwrap(); let dummy_bid = challenge_state.bids.iter().next().unwrap().clone(); vtx.send(ChallengeResponse(dummy_challenge_hash, dummy_bid.clone())) @@ -390,6 +393,7 @@ mod tests { 3, time::Duration::from_millis(10), ); + match res { Ok(_) => { let resps = storage.get_responses(dummy_request.txid).unwrap(); @@ -398,6 +402,8 @@ mod tests { assert_eq!(challenge_state.bids, bids); let requests = storage.get_requests().unwrap(); assert_eq!(1, requests.len()); + // manually set to allow for comparison of all unchanged fields + challenge_state.request.end_blockheight_clientchain = 3; assert_eq!(&challenge_state.request, &requests[0]); assert_eq!( challenge_state.request, @@ -423,6 +429,7 @@ mod tests { 1, time::Duration::from_millis(10), ); + match res { Ok(_) => { let resps = storage.get_responses(dummy_request.txid).unwrap(); @@ -444,6 +451,30 @@ mod tests { Err(_) => assert!(false, "should not return error"), } + // test end_blockheight_clientchain set correctly in request + vtx.send(ChallengeResponse(dummy_challenge_hash, dummy_bid.clone())) + .unwrap(); // send again + let _ = service.height.replace(dummy_request.start_blockheight as u64); // set height back to starting height + let res = run_challenge_request( + &service, + &clientchain, + Arc::new(Mutex::new(challenge_state.clone())), + &vrx, + storage.clone(), + time::Duration::from_millis(10), + time::Duration::from_millis(10), + 1, + time::Duration::from_millis(10), + ); + match res { + Ok(_) => { + // manual set of end_blockheight_clientchain for comparison + dummy_request.end_blockheight_clientchain = *clientchain.height.borrow(); + assert_eq!(storage.get_requests().unwrap()[0], dummy_request); + } + Err(_) => assert!(false, "should not return error"), + }; + // test client chain failure let _ = service.height.replace(dummy_request.start_blockheight as u64); // set height for fetch_next to succeed let challenge_state = fetch_next(&service, &dummy_hash).unwrap().unwrap(); diff --git a/src/clientchain.rs b/src/clientchain.rs index 912ae5a..cfb2d62 100644 --- a/src/clientchain.rs +++ b/src/clientchain.rs @@ -33,6 +33,8 @@ pub trait ClientChain { fn send_challenge(&self) -> Result; /// Verify challenge transaction has been included in the chain fn verify_challenge(&self, txid: &sha256d::Hash) -> Result; + /// Get height of client chain + fn get_block_count(&self) -> Result; } /// Rpc implementation of Service using an underlying ocean rpc connection @@ -124,4 +126,8 @@ impl<'a> ClientChain for RpcClientChain<'a> { } Ok(false) } + /// Return block count of chain + fn get_block_count(&self) -> Result { + Ok(self.client.get_block_count()? as u32) + } } diff --git a/src/coordinator.rs b/src/coordinator.rs index f494506..069da8d 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -52,10 +52,21 @@ pub fn run_request( genesis_hash: sha256d::Hash, ) -> Result> { match ::challenger::fetch_next(service, &genesis_hash)? { - Some(challenge) => { - // first attempt to store the challenge state information + Some(mut challenge) => { + // First attempt to store the challenge state information // on requests and winning bids and exit if that fails - storage.save_challenge_state(&challenge)?; + // Check if request already stored. If so set challenge request to + // request in table (catcher for coordinator failure after storing + // request but before request service period over) + match storage.get_request(challenge.request.txid)? { + Some(req) => challenge.request = req, + None => { + // Set request's start_blockheight_clientchain + challenge.request.start_blockheight_clientchain = clientchain.get_block_count()?; + // Store Challenge Request + storage.save_challenge_state(&challenge)?; + } + } // create a challenge state mutex to share between challenger and listener let shared_challenge = Arc::new(Mutex::new(challenge)); diff --git a/src/lib.rs b/src/lib.rs index d6812fa..12dec6c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,5 +47,6 @@ pub mod storage; /// utilities pub mod util { pub mod checks; + pub mod doc_format; pub mod testing; } diff --git a/src/request.rs b/src/request.rs index 316900a..a790878 100644 --- a/src/request.rs +++ b/src/request.rs @@ -25,6 +25,10 @@ pub struct Request { pub fee_percentage: u32, /// Num of Guardnode tickets set by client pub num_tickets: u32, + /// Request client chain start block height + pub start_blockheight_clientchain: u32, + /// Request client chain end block height + pub end_blockheight_clientchain: u32, } impl Request { @@ -37,6 +41,8 @@ impl Request { genesis_blockhash: res.genesis_block, fee_percentage: res.fee_percentage, num_tickets: res.num_tickets, + start_blockheight_clientchain: 0, + end_blockheight_clientchain: 0, } } } diff --git a/src/storage.rs b/src/storage.rs index 88fe94e..0b38609 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -3,25 +3,25 @@ //! Storage interface and implementations use std::mem::drop; -use std::str::FromStr; use std::sync::{Mutex, MutexGuard}; -use bitcoin_hashes::{hex::FromHex, sha256d}; +use bitcoin_hashes::sha256d; use mongodb::db::{Database, ThreadedDatabase}; -use mongodb::ordered::OrderedDocument; -use mongodb::{coll::options::FindOptions, Bson, Client, ThreadedClient}; -use secp256k1::key::PublicKey; +use mongodb::{coll::options::FindOptions, Client, ThreadedClient}; +use util::doc_format::*; use crate::challenger::{ChallengeResponseIds, ChallengeState}; use crate::config::StorageConfig; -use crate::error::Result; -use crate::request::{Bid, BidSet, Request}; +use crate::error::{Error::MongoDb, Result}; +use crate::request::{BidSet, Request}; /// Storage trait defining required functionality for objects that store request /// and challenge information pub trait Storage { /// Store the state of a challenge request fn save_challenge_state(&self, challenge: &ChallengeState) -> Result<()>; + /// Update request in storage + fn update_request(&self, request: Request) -> Result<()>; /// Store responses for a specific challenge request fn save_response(&self, request_hash: sha256d::Hash, ids: &ChallengeResponseIds) -> Result<()>; /// Get all challenge responses for a specific request @@ -53,6 +53,17 @@ impl MongoStorage { } } + // Specify collections Indexes + if let Err(e) = db.collection("Request").create_index(doc! ("txid":1), None) { + return Err(MongoDb(e)); + } + if let Err(e) = db.collection("Bid").create_index(doc! ("request_id":1), None) { + return Err(MongoDb(e)); + } + if let Err(e) = db.collection("Response").create_index(doc! ("request_id":1), None) { + return Err(MongoDb(e)); + } + Ok(MongoStorage { db: Mutex::new(db), config: storage_config, @@ -84,11 +95,16 @@ impl Storage for MongoStorage { let request_id; let coll = db_locked.collection("Request"); - let doc = request_to_doc(&challenge.request); - match coll.find_one(Some(doc.clone()), None)? { - Some(res) => request_id = res.get("_id").unwrap().clone(), + let filter = doc! {"txid"=>challenge.request.txid.to_string()}; + match coll.find_one(Some(filter), None)? { + Some(res) => { + request_id = res.get("_id").unwrap().clone(); + } None => { - request_id = coll.insert_one(doc, None)?.inserted_id.unwrap(); + request_id = coll + .insert_one(request_to_doc(&challenge.request), None)? + .inserted_id + .unwrap(); } } @@ -105,6 +121,17 @@ impl Storage for MongoStorage { Ok(()) } + /// Update entry in Request collection with given Request model + fn update_request(&self, request: Request) -> Result<()> { + let db_locked = self.db.lock().unwrap(); + self.auth(&db_locked)?; + let coll = db_locked.collection("Request"); + let filter = doc! {"txid"=>&request.txid.clone().to_string()}; + let update = doc! {"$set" => request_to_doc(&request)}; + let _ = coll.update_one(filter, update, None)?; + Ok(()) + } + /// Store responses for a specific challenge request fn save_response(&self, request_hash: sha256d::Hash, ids: &ChallengeResponseIds) -> Result<()> { let db_locked = self.db.lock().unwrap(); @@ -234,162 +261,3 @@ impl Storage for MongoStorage { } } } - -/// Util method that generates a Request document from a request -pub fn request_to_doc(request: &Request) -> OrderedDocument { - doc! { - "txid": request.txid.to_string(), - "start_blockheight": request.start_blockheight, - "end_blockheight": request.end_blockheight, - "genesis_blockhash": request.genesis_blockhash.to_string(), - "fee_percentage": request.fee_percentage, - "num_tickets": request.num_tickets - } -} - -/// Util method that generates a request from a Request document -pub fn doc_to_request(doc: &OrderedDocument) -> Request { - Request { - txid: sha256d::Hash::from_hex(doc.get("txid").unwrap().as_str().unwrap()).unwrap(), - start_blockheight: doc.get("start_blockheight").unwrap().as_i32().unwrap() as u32, - end_blockheight: doc.get("end_blockheight").unwrap().as_i32().unwrap() as u32, - genesis_blockhash: sha256d::Hash::from_hex(doc.get("genesis_blockhash").unwrap().as_str().unwrap()).unwrap(), - fee_percentage: doc.get("fee_percentage").unwrap().as_i32().unwrap() as u32, - num_tickets: doc.get("num_tickets").unwrap().as_i32().unwrap() as u32, - } -} - -/// Util method that generates a Bid document from a request bid -pub fn bid_to_doc(request_id: &Bson, bid: &Bid) -> OrderedDocument { - doc! { - "request_id": request_id.clone(), - "txid": bid.txid.to_string(), - "pubkey": bid.pubkey.to_string() - } -} - -/// Util method that generates a request bid from a Bid document -pub fn doc_to_bid(doc: &OrderedDocument) -> Bid { - Bid { - txid: sha256d::Hash::from_hex(doc.get("txid").unwrap().as_str().unwrap()).unwrap(), - pubkey: PublicKey::from_str(doc.get("pubkey").unwrap().as_str().unwrap()).unwrap(), - } -} - -/// Util method that generates a Response document from challenge responses -pub fn challenge_responses_to_doc(request_id: &Bson, responses: &ChallengeResponseIds) -> OrderedDocument { - let bids = responses - .iter() - .map(|x| Bson::String(x.to_string())) - .collect::>(); - doc! { - "request_id": request_id.clone(), - "bid_txids": bids - } -} - -/// Util method that generates challenge responses from a Response document -pub fn doc_to_challenge_responses(doc: &OrderedDocument) -> ChallengeResponseIds { - doc.get_array("bid_txids") - .unwrap() - .iter() - .map(|x| sha256d::Hash::from_hex(x.as_str().unwrap()).unwrap()) - .collect() -} - -#[cfg(test)] -mod tests { - use super::*; - - use mongodb::oid::ObjectId; - - use crate::util::testing::gen_dummy_hash; - - #[test] - fn request_doc_test() { - let request_hash = gen_dummy_hash(9); - let genesis_hash = "1100000000000000000000000000000000000000000000000000000000000022"; - let request = Request { - txid: request_hash, - start_blockheight: 2, - end_blockheight: 5, - genesis_blockhash: sha256d::Hash::from_hex(genesis_hash).unwrap(), - fee_percentage: 5, - num_tickets: 10, - }; - - let doc = request_to_doc(&request); - assert_eq!( - doc! { - "txid": request_hash.to_string(), - "start_blockheight": 2, - "end_blockheight": 5, - "genesis_blockhash": genesis_hash, - "fee_percentage": 5, - "num_tickets": 10 - }, - doc - ); - assert_eq!(request, doc_to_request(&doc)); - } - - #[test] - fn bid_doc_test() { - let id = ObjectId::new().unwrap(); - let pubkey_hex = "026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"; - let hash = gen_dummy_hash(1); - let bid = Bid { - txid: hash, - pubkey: PublicKey::from_str(pubkey_hex).unwrap(), - }; - - let doc = bid_to_doc(&Bson::ObjectId(id.clone()), &bid); - assert_eq!( - doc! { - "request_id": id.clone(), - "txid": hash.to_string(), - "pubkey": pubkey_hex - }, - doc - ); - assert_eq!(bid, doc_to_bid(&doc)); - } - - #[test] - fn challenge_responses_doc_test() { - let id = ObjectId::new().unwrap(); - let mut ids = ChallengeResponseIds::new(); - - let doc = challenge_responses_to_doc(&Bson::ObjectId(id.clone()), &ids); - assert_eq!( - doc! { - "request_id": id.clone(), - "bid_txids": [] - }, - doc - ); - assert_eq!(ids, doc_to_challenge_responses(&doc)); - - let _ = ids.insert(gen_dummy_hash(0)); - let doc = challenge_responses_to_doc(&Bson::ObjectId(id.clone()), &ids); - assert_eq!( - doc! { - "request_id": id.clone(), - "bid_txids": [gen_dummy_hash(0).to_string()] - }, - doc - ); - assert_eq!(ids, doc_to_challenge_responses(&doc)); - - let _ = ids.insert(gen_dummy_hash(1)); - let _ = ids.insert(gen_dummy_hash(2)); - let _ = ids.insert(gen_dummy_hash(3)); - let doc = challenge_responses_to_doc(&Bson::ObjectId(id.clone()), &ids); - assert_eq!(&id, doc.get("request_id").unwrap().as_object_id().unwrap()); - for id in doc.get_array("bid_txids").unwrap().iter() { - assert!(ids.contains(&sha256d::Hash::from_hex(id.as_str().unwrap()).unwrap())); - } - assert_eq!(4, doc.get_array("bid_txids").unwrap().len()); - assert_eq!(ids, doc_to_challenge_responses(&doc)); - } -} diff --git a/src/util/doc_format.rs b/src/util/doc_format.rs new file mode 100644 index 0000000..15343ed --- /dev/null +++ b/src/util/doc_format.rs @@ -0,0 +1,184 @@ +//! doc_format +//! +//! doc format is used to store items in the db. +//! File contains methods to convert to/from document format. + +use bitcoin_hashes::{hex::FromHex, sha256d}; +use mongodb::{ordered::OrderedDocument, Bson}; +use secp256k1::key::PublicKey; +use std::str::FromStr; + +use crate::challenger::ChallengeResponseIds; +use crate::request::{Bid, Request}; + +/// Util method that generates a Request document from a request +pub fn request_to_doc(request: &Request) -> OrderedDocument { + doc! { + "txid": request.txid.to_string(), + "start_blockheight": request.start_blockheight, + "end_blockheight": request.end_blockheight, + "genesis_blockhash": request.genesis_blockhash.to_string(), + "fee_percentage": request.fee_percentage, + "num_tickets": request.num_tickets, + "start_blockheight_clientchain": request.start_blockheight_clientchain, + "end_blockheight_clientchain": request.end_blockheight_clientchain, + } +} + +/// Util method that generates a request from a Request document +pub fn doc_to_request(doc: &OrderedDocument) -> Request { + Request { + txid: sha256d::Hash::from_hex(doc.get("txid").unwrap().as_str().unwrap()).unwrap(), + start_blockheight: doc.get("start_blockheight").unwrap().as_i32().unwrap() as u32, + end_blockheight: doc.get("end_blockheight").unwrap().as_i32().unwrap() as u32, + genesis_blockhash: sha256d::Hash::from_hex(doc.get("genesis_blockhash").unwrap().as_str().unwrap()).unwrap(), + fee_percentage: doc.get("fee_percentage").unwrap().as_i32().unwrap() as u32, + num_tickets: doc.get("num_tickets").unwrap().as_i32().unwrap() as u32, + start_blockheight_clientchain: doc.get("start_blockheight_clientchain").unwrap().as_i32().unwrap() as u32, + end_blockheight_clientchain: doc.get("end_blockheight_clientchain").unwrap().as_i32().unwrap() as u32, + } +} + +/// Util method that generates a Bid document from a request bid +pub fn bid_to_doc(request_id: &Bson, bid: &Bid) -> OrderedDocument { + doc! { + "request_id": request_id.clone(), + "txid": bid.txid.to_string(), + "pubkey": bid.pubkey.to_string() + } +} + +/// Util method that generates a request bid from a Bid document +pub fn doc_to_bid(doc: &OrderedDocument) -> Bid { + Bid { + txid: sha256d::Hash::from_hex(doc.get("txid").unwrap().as_str().unwrap()).unwrap(), + pubkey: PublicKey::from_str(doc.get("pubkey").unwrap().as_str().unwrap()).unwrap(), + } +} + +/// Util method that generates a Response document from challenge responses +pub fn challenge_responses_to_doc(request_id: &Bson, responses: &ChallengeResponseIds) -> OrderedDocument { + let bids = responses + .iter() + .map(|x| Bson::String(x.to_string())) + .collect::>(); + doc! { + "request_id": request_id.clone(), + "bid_txids": bids + } +} + +/// Util method that generates challenge responses from a Response document +pub fn doc_to_challenge_responses(doc: &OrderedDocument) -> ChallengeResponseIds { + doc.get_array("bid_txids") + .unwrap() + .iter() + .map(|x| sha256d::Hash::from_hex(x.as_str().unwrap()).unwrap()) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + use bitcoin_hashes::hex::FromHex; + use mongodb::oid::ObjectId; + use mongodb::Bson; + use secp256k1::key::PublicKey; + use std::str::FromStr; + + use crate::request::Bid; + use crate::util::testing::gen_dummy_hash; + + #[test] + fn request_doc_test() { + let request_hash = gen_dummy_hash(9); + let genesis_hash = "1100000000000000000000000000000000000000000000000000000000000022"; + let request = Request { + txid: request_hash, + start_blockheight: 2, + end_blockheight: 5, + genesis_blockhash: sha256d::Hash::from_hex(genesis_hash).unwrap(), + fee_percentage: 5, + num_tickets: 10, + start_blockheight_clientchain: 0, + end_blockheight_clientchain: 0, + }; + + let doc = request_to_doc(&request); + assert_eq!( + doc! { + "txid": request_hash.to_string(), + "start_blockheight": 2, + "end_blockheight": 5, + "genesis_blockhash": genesis_hash, + "fee_percentage": 5, + "num_tickets": 10, + "start_blockheight_clientchain":0, + "end_blockheight_clientchain":0 + }, + doc + ); + assert_eq!(request, doc_to_request(&doc)); + } + + #[test] + fn bid_doc_test() { + let id = ObjectId::new().unwrap(); + let pubkey_hex = "026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"; + let hash = gen_dummy_hash(1); + let bid = Bid { + txid: hash, + pubkey: PublicKey::from_str(pubkey_hex).unwrap(), + }; + + let doc = bid_to_doc(&Bson::ObjectId(id.clone()), &bid); + assert_eq!( + doc! { + "request_id": id.clone(), + "txid": hash.to_string(), + "pubkey": pubkey_hex + }, + doc + ); + assert_eq!(bid, doc_to_bid(&doc)); + } + + #[test] + fn challenge_responses_doc_test() { + let id = ObjectId::new().unwrap(); + let mut ids = ChallengeResponseIds::new(); + + let doc = challenge_responses_to_doc(&Bson::ObjectId(id.clone()), &ids); + assert_eq!( + doc! { + "request_id": id.clone(), + "bid_txids": [] + }, + doc + ); + assert_eq!(ids, doc_to_challenge_responses(&doc)); + + let _ = ids.insert(gen_dummy_hash(0)); + let doc = challenge_responses_to_doc(&Bson::ObjectId(id.clone()), &ids); + assert_eq!( + doc! { + "request_id": id.clone(), + "bid_txids": [gen_dummy_hash(0).to_string()] + }, + doc + ); + assert_eq!(ids, doc_to_challenge_responses(&doc)); + + let _ = ids.insert(gen_dummy_hash(1)); + let _ = ids.insert(gen_dummy_hash(2)); + let _ = ids.insert(gen_dummy_hash(3)); + let doc = challenge_responses_to_doc(&Bson::ObjectId(id.clone()), &ids); + assert_eq!(&id, doc.get("request_id").unwrap().as_object_id().unwrap()); + for id in doc.get_array("bid_txids").unwrap().iter() { + assert!(ids.contains(&sha256d::Hash::from_hex(id.as_str().unwrap()).unwrap())); + } + assert_eq!(4, doc.get_array("bid_txids").unwrap().len()); + assert_eq!(ids, doc_to_challenge_responses(&doc)); + } +} diff --git a/src/util/testing.rs b/src/util/testing.rs index 9597a80..e576d5b 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -8,6 +8,7 @@ use mongodb::Bson; use secp256k1::PublicKey; use std::cell::RefCell; use std::str::FromStr; +use util::doc_format::*; use crate::challenger::{ChallengeResponseIds, ChallengeState}; use crate::clientchain::ClientChain; @@ -31,6 +32,8 @@ pub fn gen_challenge_state(request_hash: &sha256d::Hash) -> ChallengeState { genesis_blockhash: gen_dummy_hash(0), fee_percentage: 5, num_tickets: 10, + start_blockheight_clientchain: 0, + end_blockheight_clientchain: 0, }; let mut bids = BidSet::new(); let _ = bids.insert(Bid { @@ -56,6 +59,8 @@ pub fn gen_challenge_state_with_challenge( genesis_blockhash: *request_hash, fee_percentage: 5, num_tickets: 10, + start_blockheight_clientchain: 0, + end_blockheight_clientchain: 0, }; let mut bids = BidSet::new(); let _ = bids.insert(Bid { @@ -79,7 +84,7 @@ pub struct MockClientChain { /// bool pub return_false: bool, /// Mock client chain blockheight - pub height: RefCell, + pub height: RefCell, } impl MockClientChain { @@ -113,6 +118,11 @@ impl ClientChain for MockClientChain { } Ok(true) } + + /// Get block count dummy + fn get_block_count(&self) -> Result { + Ok(self.height.clone().into_inner()) + } } /// Mock implementation of Service using some mock logic for testing @@ -124,7 +134,7 @@ pub struct MockService { /// Option pub return_none: bool, /// Current active request - pub request: ServiceRequest, + pub request: RefCell, /// Mock service chain blockheight - incremented by default on /// get_blockheight pub height: RefCell, @@ -143,12 +153,14 @@ impl MockService { .unwrap(), fee_percentage: 5, num_tickets: 10, + start_blockheight_clientchain: 0, + end_blockheight_clientchain: 0, }; MockService { return_err: false, return_none: false, - request, + request: RefCell::new(request), height: RefCell::new(0), } } @@ -169,9 +181,9 @@ impl Service for MockService { return Err(Error::from(CError::Generic("get_request failed".to_owned()))); } - let mut dummy_req = self.request.clone(); + let mut dummy_req = self.request.borrow_mut(); dummy_req.genesis_blockhash = *hash; - Ok(Some(dummy_req)) + Ok(Some(dummy_req.clone())) } /// Try get active request bids, by transaction hash, from service chain @@ -245,7 +257,15 @@ impl Storage for MockStorage { if self.return_err { return Err(Error::from(CError::Generic("save_challenge_state failed".to_owned()))); } - self.requests.borrow_mut().push(request_to_doc(&challenge.request)); + // do not add request if already exists + if !self + .requests + .borrow_mut() + .iter() + .any(|request| request.get("txid").unwrap().as_str().unwrap() == &challenge.request.txid.to_string()) + { + self.requests.borrow_mut().push(request_to_doc(&challenge.request)); + } for bid in challenge.bids.iter() { self.bids .borrow_mut() @@ -254,6 +274,16 @@ impl Storage for MockStorage { Ok(()) } + /// update request in mock storage + fn update_request(&self, request_update: ServiceRequest) -> Result<()> { + for request in self.requests.borrow_mut().iter_mut() { + if request.get("txid").unwrap().as_str().unwrap() == &request_update.txid.to_string() { + *request = request_to_doc(&request_update); + } + } + Ok(()) + } + /// Store responses for a specific challenge request fn save_response(&self, request_hash: sha256d::Hash, ids: &ChallengeResponseIds) -> Result<()> { if self.return_err { From bf65c8786e961e470e79d930c8b4ea37162de164 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Wed, 6 Nov 2019 17:32:14 +0000 Subject: [PATCH 03/40] cargo update --- Cargo.lock | 115 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 863d691..430b2c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,7 +81,7 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "strason 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -96,8 +96,8 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_test 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_test 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -105,7 +105,7 @@ name = "bitcoin-amount" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -130,7 +130,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -160,7 +160,7 @@ dependencies = [ "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "md5 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -236,7 +236,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde-hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -265,7 +265,7 @@ dependencies = [ "ocean-rpc 0.3.0 (git+https://github.com/commerceblock/rust-ocean-rpc)", "rust-ocean 0.6.0 (git+https://github.com/commerceblock/rust-ocean)", "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -287,7 +287,7 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -387,7 +387,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -427,6 +427,14 @@ dependencies = [ "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hermit-abi" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hex" version = "0.3.2" @@ -494,7 +502,7 @@ dependencies = [ "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -568,8 +576,8 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -580,8 +588,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -608,7 +616,7 @@ dependencies = [ "jsonrpc-core 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -686,6 +694,11 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "md-5" version = "0.7.0" @@ -708,7 +721,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memoffset" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -816,7 +829,7 @@ dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -846,9 +859,10 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -867,7 +881,7 @@ dependencies = [ "ocean-rpc-json 0.3.0 (git+https://github.com/commerceblock/rust-ocean-rpc)", "rust-ocean 0.6.0 (git+https://github.com/commerceblock/rust-ocean)", "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -882,8 +896,8 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -907,7 +921,7 @@ dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1184,7 +1198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1220,10 +1234,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1240,12 +1254,12 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1256,7 +1270,7 @@ dependencies = [ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1269,10 +1283,10 @@ dependencies = [ [[package]] name = "serde_test" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1304,15 +1318,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.10" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "strason" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1325,7 +1342,7 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1350,8 +1367,8 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1380,7 +1397,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1463,7 +1480,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1504,7 +1521,7 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1556,7 +1573,7 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1618,7 +1635,7 @@ name = "unicode-normalization" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1777,6 +1794,7 @@ dependencies = [ "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" @@ -1805,10 +1823,11 @@ dependencies = [ "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" "checksum md-5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9402eaae33a9e144ce18ef488a0e4ca19869673c7bcdbbfe2030fdc3f84211cd" "checksum md5 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "79c56d6a0b07f9e19282511c83fc5b086364cbae4ba8c7d5f190c3d9b0425a48" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" +"checksum memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a85c1a8c329f11437034d7313dca647c79096523533a1c79e86f1d0f657c7cc" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" @@ -1821,7 +1840,7 @@ dependencies = [ "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" +"checksum num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155394f924cdddf08149da25bfb932d226b4a593ca7468b08191ff6335941af5" "checksum ocean-rpc 0.3.0 (git+https://github.com/commerceblock/rust-ocean-rpc)" = "" "checksum ocean-rpc-json 0.3.0 (git+https://github.com/commerceblock/rust-ocean-rpc)" = "" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" @@ -1863,19 +1882,19 @@ dependencies = [ "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum separator 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7acc4d818f952ed02e7911df5da8098c8b00a3c5ba2832e035a750b56e8fc32b" "checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" -"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +"checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0" "checksum serde-hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0b833c5ad67d52ced5f5938b2980f32a9c1c5ef047f0b4fb3127e7a423c76153" -"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" +"checksum serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "ca13fc1a832f793322228923fbb3aba9f3f44444898f835d31ad1b74fa0a2bf8" "checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum serde_test 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5" -"checksum serde_test 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4aaf891d32257c9f65259b841af6e0b35d2ee22e41f1becbead01f0217f3e000" +"checksum serde_test 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "00d9d9443b1a25de2526ad21a2efc89267df5387c36035fe3902fbda8a79d83c" "checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded" "checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" +"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" "checksum strason 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dcd1098ae32c583b8d538072380c340a01e46fbca379d6248ff77721373e2cef" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textnonce 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dafb35214e317d6c0a72b16d1aa667bbc0fea57e302798e7bc520e0f39988006" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" From 9eedcd37eea480047332e1cc23821358e734a4b7 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Wed, 6 Nov 2019 17:32:41 +0000 Subject: [PATCH 04/40] Config duration changes --- config/default.toml | 7 ++----- examples/demo.rs | 4 ++-- src/config.rs | 3 --- src/coordinator.rs | 10 +++++----- src/ocean.rs | 8 ++++---- src/service.rs | 3 +++ 6 files changed, 16 insertions(+), 19 deletions(-) diff --git a/config/default.toml b/config/default.toml index 719d1b1..34945d7 100644 --- a/config/default.toml +++ b/config/default.toml @@ -7,9 +7,6 @@ challenge_duration = 60 # Frequency of creating new challenges, in number of blocks challenge_frequency = 2 -# Duration that we attempt to verify a challenge transaction before skipping, in seconds -verify_duration = 150 - # Host address that the listener binds to and receives guardnode requests listener_host = "127.0.0.1:9999" @@ -34,5 +31,5 @@ asset_key = "cScSHCQp9AEwzZoucRpX9bMRkLCJ4LoQWBNFTZuD6tPX9qwNMWfQ" [storage] host = "localhost:27017" name = "coordinator" -user = "user" -pass = "pass" +#user = "user" +#pass = "pass" diff --git a/examples/demo.rs b/examples/demo.rs index 923f602..69ac3c8 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -30,6 +30,7 @@ use secp256k1::{Message, Secp256k1, SecretKey}; use coordinator::clientchain::get_first_unspent; use coordinator::coordinator as coordinator_main; use coordinator::ocean::OceanClient; +use coordinator::service::SERVICE_BLOCK_TIME; /// Demo coordinator with listener and challenge service running /// mock implementation for service chain interface and ocean @@ -38,7 +39,6 @@ use coordinator::ocean::OceanClient; fn main() { let mut config = coordinator::config::Config::new().unwrap(); config.challenge_duration = 5; - config.verify_duration = 30; env::set_var("RUST_LOG", &config.log_level); env::set_var("RUST_BACKTRACE", "1"); @@ -56,7 +56,7 @@ fn main() { // auto client chain block generation let client_rpc_clone = client_rpc.clone(); thread::spawn(move || loop { - thread::sleep(time::Duration::from_secs(5)); + thread::sleep(time::Duration::from_secs(SERVICE_BLOCK_TIME)); if let Err(e) = client_rpc_clone.clone().client.generate(1) { error!("{}", e); } diff --git a/src/config.rs b/src/config.rs index f4312a8..a053995 100644 --- a/src/config.rs +++ b/src/config.rs @@ -115,8 +115,6 @@ pub struct Config { pub challenge_duration: u64, /// Challenge frequency in number of blocks pub challenge_frequency: u64, - /// Verify duration in seconds - pub verify_duration: u64, /// Listener host address pub listener_host: String, /// Api configuration @@ -135,7 +133,6 @@ impl Default for Config { log_level: String::from("coordinator"), challenge_duration: 60, challenge_frequency: 1, - verify_duration: 150, listener_host: String::from("localhost:80"), api: ApiConfig::default(), service: ServiceConfig::default(), diff --git a/src/coordinator.rs b/src/coordinator.rs index 069da8d..02315c6 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -13,7 +13,7 @@ use crate::challenger::ChallengeResponse; use crate::clientchain::{ClientChain, RpcClientChain}; use crate::config::Config; use crate::error::Result; -use crate::service::{RpcService, Service}; +use crate::service::{RpcService, Service, SERVICE_BLOCK_TIME}; use crate::storage::{MongoStorage, Storage}; /// Run coordinator main method @@ -36,8 +36,8 @@ pub fn run(config: Config) -> Result<()> { let resp = storage.get_responses(request_id).unwrap(); println! {"{}", serde_json::to_string_pretty(&resp).unwrap()}; } - info! {"Sleeping for 10 sec..."} - thread::sleep(time::Duration::from_secs(10)) + info! {"Sleeping for {} sec...", SERVICE_BLOCK_TIME} + thread::sleep(time::Duration::from_secs(SERVICE_BLOCK_TIME)) } } @@ -85,10 +85,10 @@ pub fn run_request( shared_challenge.clone(), &verify_rx, storage.clone(), - time::Duration::from_secs(config.verify_duration), + time::Duration::from_secs(5 * SERVICE_BLOCK_TIME), time::Duration::from_secs(config.challenge_duration), config.challenge_frequency, - time::Duration::from_secs(10), + time::Duration::from_secs(SERVICE_BLOCK_TIME / 2), )?; // stop listener service diff --git a/src/ocean.rs b/src/ocean.rs index fad8aae..1d305de 100644 --- a/src/ocean.rs +++ b/src/ocean.rs @@ -22,10 +22,10 @@ impl OceanClient { } /// Interval between retry attempts of rpc client -pub const CLIENT_INTERVAL: u64 = 10; +pub const OCEAN_CLIENT_INTERVAL: u64 = 10; /// Number of retry attemps for rpc client calls -pub const CLIENT_RETRY_ATTEMPTS: u8 = 5; +pub const OCEAN_CLIENT_RETRY_ATTEMPTS: u8 = 5; impl RpcApi for OceanClient { fn call serde::de::Deserialize<'b>>( @@ -33,12 +33,12 @@ impl RpcApi for OceanClient { cmd: &str, args: &[serde_json::Value], ) -> ocean_rpc::Result { - for _ in 0..CLIENT_RETRY_ATTEMPTS { + for _ in 0..OCEAN_CLIENT_RETRY_ATTEMPTS { match self.client.call(cmd, args) { Ok(ret) => return Ok(ret), Err(ocean_rpc::Error::JsonRpc(e)) => { warn!("rpc error: {}, retrying...", e); - ::std::thread::sleep(::std::time::Duration::from_millis(CLIENT_INTERVAL)); + ::std::thread::sleep(::std::time::Duration::from_millis(OCEAN_CLIENT_INTERVAL)); continue; } Err(e) => return Err(e), diff --git a/src/service.rs b/src/service.rs index bb31319..5aa5f74 100644 --- a/src/service.rs +++ b/src/service.rs @@ -10,6 +10,9 @@ use crate::error::Result; use crate::ocean::OceanClient; use crate::request::{Bid, BidSet, Request}; +/// Service chain block time in seconds +pub const SERVICE_BLOCK_TIME: u64 = 60; + /// Service trait defining functionality for interfacing with service chain pub trait Service { /// Get all active requests, if any, from service chain From dfc6ae090944a11fd65565fd7a29eb90b0e4e91b Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Wed, 6 Nov 2019 18:44:50 +0000 Subject: [PATCH 05/40] Challenge verify now throws an error if verify period ends --- config/default.toml | 4 ++-- src/challenger.rs | 58 ++++++++++++++++++++++++++------------------- src/error.rs | 3 +++ src/ocean.rs | 4 ++-- 4 files changed, 41 insertions(+), 28 deletions(-) diff --git a/config/default.toml b/config/default.toml index 34945d7..f0b251f 100644 --- a/config/default.toml +++ b/config/default.toml @@ -31,5 +31,5 @@ asset_key = "cScSHCQp9AEwzZoucRpX9bMRkLCJ4LoQWBNFTZuD6tPX9qwNMWfQ" [storage] host = "localhost:27017" name = "coordinator" -#user = "user" -#pass = "pass" +user = "user" +pass = "pass" diff --git a/src/challenger.rs b/src/challenger.rs index 88162b7..2016548 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -15,32 +15,34 @@ use crate::request::{Bid, BidSet, Request}; use crate::service::Service; use crate::storage::Storage; -/// Number of verify attempts for challenge transaction -pub const CHALLENGER_VERIFY_ATTEMPTS: u32 = 5; +/// Verify attempt interval to client in ms +pub const CHALLENGER_VERIFY_INTERVAL: u64 = 100; /// Attempts to verify that a challenge has been included in the client chain -/// Method tries a fixed number of attempts CHALLENGER_VERIFY_ATTEMPTS for a -/// variable delay time to allow easy configuration +/// This makes attempts every CHALLENGER_VERIFY_INTERVAL ms and for the verify +/// duration specified, which is variable in order to allow easy configuration fn verify_challenge( hash: &sha256d::Hash, clientchain: &K, - attempt_delay: time::Duration, -) -> Result { + verify_duration: time::Duration, +) -> Result<()> { info! {"verifying challenge hash: {}", hash} - for i in 0..CHALLENGER_VERIFY_ATTEMPTS { - // fixed number of attempts? - if clientchain.verify_challenge(&hash)? { - info! {"challenge verified"} - return Ok(true); - } - warn! {"attempt {} failed", i+1} - if i + 1 == CHALLENGER_VERIFY_ATTEMPTS { + let start_time = time::Instant::now(); + loop { + let now = time::Instant::now(); + if start_time + verify_duration > now { + if clientchain.verify_challenge(&hash)? { + info! {"challenge verified"} + return Ok(()); + } + } else { break; } - info! {"sleeping for {:?}...", attempt_delay/CHALLENGER_VERIFY_ATTEMPTS} - thread::sleep(attempt_delay / CHALLENGER_VERIFY_ATTEMPTS) + // This will potentially be replaced by subscribing to the ocean node + // for transaction updates but this is good enough for now + thread::sleep(std::time::Duration::from_millis(CHALLENGER_VERIFY_INTERVAL)) } - Ok(false) + Err(Error::from(CError::UnverifiedChallenge)) } /// Get responses to the challenge by reading data from the channel receiver @@ -115,9 +117,9 @@ pub fn run_challenge_request( let challenge_hash = clientchain.send_challenge()?; challenge_state.lock().unwrap().latest_challenge = Some(challenge_hash); - if !verify_challenge(&challenge_hash, clientchain, verify_duration)? { + if let Err(e) = verify_challenge(&challenge_hash, clientchain, verify_duration) { challenge_state.lock().unwrap().latest_challenge = None; // stop receiving responses - continue; + return Err(e); } info! {"fetching responses..."} @@ -218,15 +220,21 @@ mod tests { let mut clientchain = MockClientChain::new(); let dummy_hash = gen_dummy_hash(5); - assert!(verify_challenge(&dummy_hash, &clientchain, time::Duration::from_nanos(1)).unwrap() == true); + // duration doesn't matter here + assert!(verify_challenge(&dummy_hash, &clientchain, time::Duration::from_millis(10)).unwrap() == ()); clientchain.return_false = true; - assert!(verify_challenge(&dummy_hash, &clientchain, time::Duration::from_nanos(1)).unwrap() == false); + let res = verify_challenge(&dummy_hash, &clientchain, time::Duration::from_millis(10)); + match res { + Ok(_) => assert!(false, "should not return Ok"), + Err(Error::Coordinator(e)) => assert_eq!(CError::UnverifiedChallenge.to_string(), e.to_string()), + Err(_) => assert!(false, "should not return any error"), + } clientchain.return_false = false; clientchain.return_err = true; assert!( - verify_challenge(&dummy_hash, &clientchain, time::Duration::from_nanos(1)).is_err(), + verify_challenge(&dummy_hash, &clientchain, time::Duration::from_millis(10)).is_err(), "verify_challenge failed" ) } @@ -553,10 +561,12 @@ mod tests { time::Duration::from_millis(10), ); match res { - Ok(_) => { + Ok(_) => assert!(false, "should not return Ok"), + Err(Error::Coordinator(e)) => { assert_eq!(0, storage.challenge_responses.borrow().len()); + assert_eq!(CError::UnverifiedChallenge.to_string(), e.to_string()); } - Err(_) => assert!(false, "should not return error"), + Err(_) => assert!(false, "should not return any error"), } clientchain.return_false = false; diff --git a/src/error.rs b/src/error.rs index ba7b19a..dd25fa8 100644 --- a/src/error.rs +++ b/src/error.rs @@ -20,6 +20,8 @@ pub type Result = result::Result; pub enum CError { /// Missing bids for a specific request error MissingBids, + /// Challenge was not successfully verified + UnverifiedChallenge, /// Listener receiver disconnected error ReceiverDisconnected, /// Missing unspent for challenge asset. Takes parameters asset label and @@ -77,6 +79,7 @@ impl error::Error for CError { match *self { CError::Generic(_) => "Generic error", CError::MissingBids => "No bids found", + CError::UnverifiedChallenge => "Challenge not successfully verified", CError::ReceiverDisconnected => "Challenge response receiver disconnected", CError::MissingUnspent(_, _) => "No unspent found for asset", CError::InputError(_, _) => "Input parameter error", diff --git a/src/ocean.rs b/src/ocean.rs index 1d305de..4576471 100644 --- a/src/ocean.rs +++ b/src/ocean.rs @@ -22,7 +22,7 @@ impl OceanClient { } /// Interval between retry attempts of rpc client -pub const OCEAN_CLIENT_INTERVAL: u64 = 10; +pub const OCEAN_CLIENT_RETRY_INTERVAL: u64 = 10; /// Number of retry attemps for rpc client calls pub const OCEAN_CLIENT_RETRY_ATTEMPTS: u8 = 5; @@ -38,7 +38,7 @@ impl RpcApi for OceanClient { Ok(ret) => return Ok(ret), Err(ocean_rpc::Error::JsonRpc(e)) => { warn!("rpc error: {}, retrying...", e); - ::std::thread::sleep(::std::time::Duration::from_millis(OCEAN_CLIENT_INTERVAL)); + ::std::thread::sleep(::std::time::Duration::from_millis(OCEAN_CLIENT_RETRY_INTERVAL)); continue; } Err(e) => return Err(e), From 78bc33371e0d912229c4d9714ee3951d64e119e2 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Thu, 7 Nov 2019 12:29:19 +0000 Subject: [PATCH 06/40] Service block time configurable --- config/default.toml | 8 +++----- examples/demo.rs | 7 ++++--- src/config.rs | 12 ++++++++++-- src/coordinator.rs | 10 +++++----- src/service.rs | 3 --- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/config/default.toml b/config/default.toml index f0b251f..758ec6f 100644 --- a/config/default.toml +++ b/config/default.toml @@ -1,11 +1,11 @@ # Log level option used to set RUST_LOG for the rust env logger -log_level = "coordinator,demo" +# log_level = "coordinator,demo" # Duration that we wait for challenge responses from guardnodes, in seconds -challenge_duration = 60 +# challenge_duration = 60 # Frequency of creating new challenges, in number of blocks -challenge_frequency = 2 +# challenge_frequency = 2 # Host address that the listener binds to and receives guardnode requests listener_host = "127.0.0.1:9999" @@ -31,5 +31,3 @@ asset_key = "cScSHCQp9AEwzZoucRpX9bMRkLCJ4LoQWBNFTZuD6tPX9qwNMWfQ" [storage] host = "localhost:27017" name = "coordinator" -user = "user" -pass = "pass" diff --git a/examples/demo.rs b/examples/demo.rs index 69ac3c8..3538ffc 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -30,7 +30,6 @@ use secp256k1::{Message, Secp256k1, SecretKey}; use coordinator::clientchain::get_first_unspent; use coordinator::coordinator as coordinator_main; use coordinator::ocean::OceanClient; -use coordinator::service::SERVICE_BLOCK_TIME; /// Demo coordinator with listener and challenge service running /// mock implementation for service chain interface and ocean @@ -39,8 +38,10 @@ use coordinator::service::SERVICE_BLOCK_TIME; fn main() { let mut config = coordinator::config::Config::new().unwrap(); config.challenge_duration = 5; + config.challenge_frequency = 2; + config.block_time = 10; - env::set_var("RUST_LOG", &config.log_level); + env::set_var("RUST_LOG", "coordinator,demo"); env::set_var("RUST_BACKTRACE", "1"); env_logger::init(); @@ -56,7 +57,7 @@ fn main() { // auto client chain block generation let client_rpc_clone = client_rpc.clone(); thread::spawn(move || loop { - thread::sleep(time::Duration::from_secs(SERVICE_BLOCK_TIME)); + thread::sleep(time::Duration::from_secs(10)); if let Err(e) = client_rpc_clone.clone().client.generate(1) { error!("{}", e); } diff --git a/src/config.rs b/src/config.rs index a053995..4f983d9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -115,6 +115,8 @@ pub struct Config { pub challenge_duration: u64, /// Challenge frequency in number of blocks pub challenge_frequency: u64, + /// Block time in seconds + pub block_time: u64, /// Listener host address pub listener_host: String, /// Api configuration @@ -127,12 +129,18 @@ pub struct Config { pub storage: StorageConfig, } +/// Config default variable definitons +const CONFIG_CHALLENGE_DURATION_DEFAULT: u64 = 60; +const CONFIG_CHALLENGE_FREQUENCY_DEFAULT: u64 = 1; +const CONFIG_BLOCK_TIME_DEFAULT: u64 = 60; + impl Default for Config { fn default() -> Config { Config { log_level: String::from("coordinator"), - challenge_duration: 60, - challenge_frequency: 1, + challenge_duration: CONFIG_CHALLENGE_DURATION_DEFAULT, + challenge_frequency: CONFIG_CHALLENGE_FREQUENCY_DEFAULT, + block_time: CONFIG_BLOCK_TIME_DEFAULT, listener_host: String::from("localhost:80"), api: ApiConfig::default(), service: ServiceConfig::default(), diff --git a/src/coordinator.rs b/src/coordinator.rs index 02315c6..b46d6fd 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -13,7 +13,7 @@ use crate::challenger::ChallengeResponse; use crate::clientchain::{ClientChain, RpcClientChain}; use crate::config::Config; use crate::error::Result; -use crate::service::{RpcService, Service, SERVICE_BLOCK_TIME}; +use crate::service::{RpcService, Service}; use crate::storage::{MongoStorage, Storage}; /// Run coordinator main method @@ -36,8 +36,8 @@ pub fn run(config: Config) -> Result<()> { let resp = storage.get_responses(request_id).unwrap(); println! {"{}", serde_json::to_string_pretty(&resp).unwrap()}; } - info! {"Sleeping for {} sec...", SERVICE_BLOCK_TIME} - thread::sleep(time::Duration::from_secs(SERVICE_BLOCK_TIME)) + info! {"Sleeping for {} sec...", config.block_time} + thread::sleep(time::Duration::from_secs(config.block_time)) } } @@ -85,10 +85,10 @@ pub fn run_request( shared_challenge.clone(), &verify_rx, storage.clone(), - time::Duration::from_secs(5 * SERVICE_BLOCK_TIME), + time::Duration::from_secs(5 * config.block_time), time::Duration::from_secs(config.challenge_duration), config.challenge_frequency, - time::Duration::from_secs(SERVICE_BLOCK_TIME / 2), + time::Duration::from_secs(config.block_time / 2), )?; // stop listener service diff --git a/src/service.rs b/src/service.rs index 5aa5f74..bb31319 100644 --- a/src/service.rs +++ b/src/service.rs @@ -10,9 +10,6 @@ use crate::error::Result; use crate::ocean::OceanClient; use crate::request::{Bid, BidSet, Request}; -/// Service chain block time in seconds -pub const SERVICE_BLOCK_TIME: u64 = 60; - /// Service trait defining functionality for interfacing with service chain pub trait Service { /// Get all active requests, if any, from service chain From dcf42d8fd30d674a8305dc6864d244c04b7b18d5 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Mon, 11 Nov 2019 10:32:28 +0000 Subject: [PATCH 07/40] cargo update --- Cargo.lock | 68 +++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 430b2c9..e749ba2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,14 +21,6 @@ name = "arrayref" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "atty" version = "0.2.13" @@ -271,23 +263,23 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -308,6 +300,16 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-utils" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crypto-mac" version = "0.6.2" @@ -546,7 +548,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -721,7 +723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memoffset" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -807,11 +809,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "nom" version = "4.2.3" @@ -869,7 +866,7 @@ dependencies = [ [[package]] name = "ocean-rpc" version = "0.3.0" -source = "git+https://github.com/commerceblock/rust-ocean-rpc#a8ffb9e94751a608eeb8c5d8a4e082266658184f" +source = "git+https://github.com/commerceblock/rust-ocean-rpc#4281e8656729470be5a1b6083a0337a34bc4454e" dependencies = [ "bitcoin 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", "bitcoin-amount 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -888,7 +885,7 @@ dependencies = [ [[package]] name = "ocean-rpc-json" version = "0.3.0" -source = "git+https://github.com/commerceblock/rust-ocean-rpc#a8ffb9e94751a608eeb8c5d8a4e082266658184f" +source = "git+https://github.com/commerceblock/rust-ocean-rpc#4281e8656729470be5a1b6083a0337a34bc4454e" dependencies = [ "bitcoin 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", "bitcoin-amount 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1152,7 +1149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rust-ocean" version = "0.6.0" -source = "git+https://github.com/commerceblock/rust-ocean#b3728b67611c52f1bd408e588cf396562ffb4c7a" +source = "git+https://github.com/commerceblock/rust-ocean#82329da46e80d367ab62b8be8b8c2573dc90c79c" dependencies = [ "bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitcoin 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1259,7 +1256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1342,7 +1339,7 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1515,7 +1512,7 @@ name = "tokio-threadpool" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1632,7 +1629,7 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1748,7 +1745,6 @@ dependencies = [ "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" @@ -1775,10 +1771,11 @@ dependencies = [ "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum config 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9107d78ed62b3fa5a86e7d18e647abed48cfd8f8fab6c72f4cdb982d196f7e6" "checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" -"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" +"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" +"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" "checksum crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7afa06d05a046c7a47c3a849907ec303504608c927f4e85f7bfff22b7180d971" "checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97" "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" @@ -1827,14 +1824,13 @@ dependencies = [ "checksum md-5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9402eaae33a9e144ce18ef488a0e4ca19869673c7bcdbbfe2030fdc3f84211cd" "checksum md5 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "79c56d6a0b07f9e19282511c83fc5b086364cbae4ba8c7d5f190c3d9b0425a48" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a85c1a8c329f11437034d7313dca647c79096523533a1c79e86f1d0f657c7cc" +"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum mongodb 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "d558c8c1ee6140954f82b53558135bb9ecb7b258e10dbd7206d985d134d388e0" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" "checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" @@ -1894,7 +1890,7 @@ dependencies = [ "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" "checksum strason 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dcd1098ae32c583b8d538072380c340a01e46fbca379d6248ff77721373e2cef" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c" +"checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textnonce 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dafb35214e317d6c0a72b16d1aa667bbc0fea57e302798e7bc520e0f39988006" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" @@ -1923,7 +1919,7 @@ dependencies = [ "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" +"checksum unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" From a63d048ec771a4862a7ef21dd9bf94ccb107a747 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Mon, 11 Nov 2019 11:43:41 +0000 Subject: [PATCH 08/40] Storage get_responses -> get_response --- src/api.rs | 2 +- src/challenger.rs | 4 ++-- src/coordinator.rs | 2 +- src/lib.rs | 1 + src/storage.rs | 12 ++++++------ src/util/testing.rs | 6 +++--- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/api.rs b/src/api.rs index 2b6d094..d3f5e18 100644 --- a/src/api.rs +++ b/src/api.rs @@ -84,7 +84,7 @@ fn get_request_responses(params: Params, storage: Arc) -> futures:: let try_parse = params.parse::(); match try_parse { Ok(parse) => { - let responses = storage.get_responses(parse.txid).unwrap(); + let responses = storage.get_response(parse.txid).unwrap(); let res_serialized = serde_json::to_string(&GetRequestResponsesResponse { responses }).unwrap(); return futures::finished(Value::String(res_serialized)); } diff --git a/src/challenger.rs b/src/challenger.rs index 2016548..93cdad4 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -404,7 +404,7 @@ mod tests { match res { Ok(_) => { - let resps = storage.get_responses(dummy_request.txid).unwrap(); + let resps = storage.get_response(dummy_request.txid).unwrap(); assert_eq!(1, resps.len()); let bids = storage.get_bids(dummy_request.txid).unwrap(); assert_eq!(challenge_state.bids, bids); @@ -440,7 +440,7 @@ mod tests { match res { Ok(_) => { - let resps = storage.get_responses(dummy_request.txid).unwrap(); + let resps = storage.get_response(dummy_request.txid).unwrap(); assert_eq!(5, resps.len()); assert_eq!(1, resps[1].len()); assert_eq!(dummy_bid.txid, *resps[1].iter().next().unwrap()); diff --git a/src/coordinator.rs b/src/coordinator.rs index b46d6fd..712ce71 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -33,7 +33,7 @@ pub fn run(config: Config) -> Result<()> { if let Some(request_id) = run_request(&config, &service, &clientchain, storage.clone(), genesis_hash)? { // if challenge request succeeds print responses println! {"***** Responses *****"} - let resp = storage.get_responses(request_id).unwrap(); + let resp = storage.get_response(request_id).unwrap(); println! {"{}", serde_json::to_string_pretty(&resp).unwrap()}; } info! {"Sleeping for {} sec...", config.block_time} diff --git a/src/lib.rs b/src/lib.rs index 12dec6c..b31af30 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,7 @@ pub mod error; pub mod listener; pub mod ocean; pub mod request; +pub mod response; pub mod service; pub mod storage; /// utilities diff --git a/src/storage.rs b/src/storage.rs index 0b38609..a87ebed 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -22,10 +22,10 @@ pub trait Storage { fn save_challenge_state(&self, challenge: &ChallengeState) -> Result<()>; /// Update request in storage fn update_request(&self, request: Request) -> Result<()>; - /// Store responses for a specific challenge request + /// Store response for a specific challenge request fn save_response(&self, request_hash: sha256d::Hash, ids: &ChallengeResponseIds) -> Result<()>; - /// Get all challenge responses for a specific request - fn get_responses(&self, request_hash: sha256d::Hash) -> Result>; + /// Get challenge response for a specific request + fn get_response(&self, request_hash: sha256d::Hash) -> Result>; /// Get all bids for a specific request fn get_bids(&self, request_hash: sha256d::Hash) -> Result; /// Get all the requests @@ -132,7 +132,7 @@ impl Storage for MongoStorage { Ok(()) } - /// Store responses for a specific challenge request + /// Store response for a specific challenge request fn save_response(&self, request_hash: sha256d::Hash, ids: &ChallengeResponseIds) -> Result<()> { let db_locked = self.db.lock().unwrap(); self.auth(&db_locked)?; @@ -153,8 +153,8 @@ impl Storage for MongoStorage { Ok(()) } - /// Get all challenge responses for a specific request - fn get_responses(&self, request_hash: sha256d::Hash) -> Result> { + /// Get challenge response for a specific request + fn get_response(&self, request_hash: sha256d::Hash) -> Result> { let db_locked = self.db.lock().unwrap(); self.auth(&db_locked)?; diff --git a/src/util/testing.rs b/src/util/testing.rs index e576d5b..89ebb06 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -284,7 +284,7 @@ impl Storage for MockStorage { Ok(()) } - /// Store responses for a specific challenge request + /// Store response for a specific challenge request fn save_response(&self, request_hash: sha256d::Hash, ids: &ChallengeResponseIds) -> Result<()> { if self.return_err { return Err(Error::from(CError::Generic("save_response failed".to_owned()))); @@ -295,8 +295,8 @@ impl Storage for MockStorage { Ok(()) } - /// Get all challenge responses for a specific request - fn get_responses(&self, request_hash: sha256d::Hash) -> Result> { + /// Get challenge response for a specific request + fn get_response(&self, request_hash: sha256d::Hash) -> Result> { let mut challenge_responses = vec![]; for doc in self.challenge_responses.borrow().to_vec().iter() { if doc.get("request_id").unwrap().as_str().unwrap() == request_hash.to_string() { From a254f6c3f24981657ef67288ecda7c163cdc998d Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Mon, 11 Nov 2019 17:52:17 +0000 Subject: [PATCH 09/40] Restructure challenge Response model --- src/api.rs | 34 ++++++++++++++---- src/challenger.rs | 17 +++++---- src/coordinator.rs | 6 ++-- src/response.rs | 39 ++++++++++++++++++++ src/storage.rs | 44 ++++++++++++++++------- src/util/doc_format.rs | 81 ++++++++++++++++++++++++++++-------------- src/util/testing.rs | 22 +++++++++--- 7 files changed, 184 insertions(+), 59 deletions(-) create mode 100644 src/response.rs diff --git a/src/api.rs b/src/api.rs index d3f5e18..6615e35 100644 --- a/src/api.rs +++ b/src/api.rs @@ -14,9 +14,9 @@ use jsonrpc_http_server::jsonrpc_core::{Error, ErrorCode, IoHandler, Params, Val use jsonrpc_http_server::{hyper::header, AccessControlAllowOrigin, DomainsValidation, Response, ServerBuilder}; use serde::{Deserialize, Serialize}; -use crate::challenger::ChallengeResponseIds; use crate::config::ApiConfig; use crate::request::{BidSet, Request as ServiceRequest}; +use crate::response::Response as ChallengeResponse; use crate::storage::Storage; #[derive(Deserialize, Debug)] @@ -75,7 +75,7 @@ struct GetRequestResponsesParams { #[derive(Serialize, Debug)] struct GetRequestResponsesResponse { - responses: Vec, + response: ChallengeResponse, } /// Get requests responses RPC call returning all responses for a specific @@ -84,9 +84,17 @@ fn get_request_responses(params: Params, storage: Arc) -> futures:: let try_parse = params.parse::(); match try_parse { Ok(parse) => { - let responses = storage.get_response(parse.txid).unwrap(); - let res_serialized = serde_json::to_string(&GetRequestResponsesResponse { responses }).unwrap(); - return futures::finished(Value::String(res_serialized)); + let response_get = storage.get_response(parse.txid).unwrap(); + if let Some(response) = response_get { + let res_serialized = serde_json::to_string(&GetRequestResponsesResponse { response }).unwrap(); + return futures::finished(Value::String(res_serialized)); + } else { + return futures::failed(Error { + code: ErrorCode::InvalidParams, + message: "Invalid params: `txid` does not exist.".to_string(), + data: None, + }); + } } Err(e) => return futures::failed(e), } @@ -161,6 +169,7 @@ mod tests { use futures::Future; + use crate::challenger::ChallengeResponseIds; use crate::util::testing::{gen_challenge_state, gen_dummy_hash, MockStorage}; #[test] @@ -232,6 +241,16 @@ mod tests { let storage = Arc::new(MockStorage::new()); let dummy_hash = gen_dummy_hash(1); let dummy_hash_bid = gen_dummy_hash(2); + + // no such request + let s = format!(r#"{{"txid": "{}"}}"#, dummy_hash.to_string()); + let params: Params = serde_json::from_str(&s).unwrap(); + let resp = get_request_responses(params, storage.clone()); + assert_eq!( + "Invalid params: `txid` does not exist.", + resp.wait().unwrap_err().message + ); + let mut dummy_response_set = ChallengeResponseIds::new(); let _ = dummy_response_set.insert(dummy_hash_bid); let _ = storage.save_response(dummy_hash, &dummy_response_set); @@ -259,7 +278,10 @@ mod tests { let params: Params = serde_json::from_str(&s).unwrap(); let resp = get_request_responses(params, storage.clone()); assert_eq!( - format!("{{\"responses\":[[\"{}\"]]}}", dummy_hash_bid.to_string()), + format!( + r#"{{"response":{{"num_challenges":1,"bid_responses":{{"{}":1}}}}}}"#, + dummy_hash_bid.to_string() + ), resp.wait().unwrap() ); } diff --git a/src/challenger.rs b/src/challenger.rs index 93cdad4..1d85638 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -213,6 +213,7 @@ mod tests { use std::sync::mpsc::{channel, Receiver, Sender}; use crate::error::Error; + use crate::response::Response; use crate::util::testing::{gen_dummy_hash, MockClientChain, MockService, MockStorage}; #[test] @@ -398,14 +399,14 @@ mod tests { storage.clone(), time::Duration::from_millis(10), time::Duration::from_millis(10), - 3, + 50, time::Duration::from_millis(10), ); match res { Ok(_) => { let resps = storage.get_response(dummy_request.txid).unwrap(); - assert_eq!(1, resps.len()); + assert_eq!(resps, None); let bids = storage.get_bids(dummy_request.txid).unwrap(); assert_eq!(challenge_state.bids, bids); let requests = storage.get_requests().unwrap(); @@ -441,10 +442,14 @@ mod tests { match res { Ok(_) => { let resps = storage.get_response(dummy_request.txid).unwrap(); - assert_eq!(5, resps.len()); - assert_eq!(1, resps[1].len()); - assert_eq!(dummy_bid.txid, *resps[1].iter().next().unwrap()); - assert_eq!(5, storage.challenge_responses.borrow().len()); + assert_eq!( + resps.unwrap(), + Response { + num_challenges: 4, + bid_responses: [(dummy_bid.txid, 1)].iter().cloned().collect() + } + ); + assert_eq!(1, storage.challenge_responses.borrow().len()); let bids = storage.get_bids(dummy_request.txid).unwrap(); assert_eq!(challenge_state.bids, bids); let requests = storage.get_requests().unwrap(); diff --git a/src/coordinator.rs b/src/coordinator.rs index 712ce71..590f563 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -32,9 +32,9 @@ pub fn run(config: Config) -> Result<()> { loop { if let Some(request_id) = run_request(&config, &service, &clientchain, storage.clone(), genesis_hash)? { // if challenge request succeeds print responses - println! {"***** Responses *****"} - let resp = storage.get_response(request_id).unwrap(); - println! {"{}", serde_json::to_string_pretty(&resp).unwrap()}; + info! {"***** Response *****"} + let resp = storage.get_response(request_id)?.unwrap(); + info! {"{}", serde_json::to_string_pretty(&resp).unwrap()}; } info! {"Sleeping for {} sec...", config.block_time} thread::sleep(time::Duration::from_secs(config.block_time)) diff --git a/src/response.rs b/src/response.rs new file mode 100644 index 0000000..2fd0bc3 --- /dev/null +++ b/src/response.rs @@ -0,0 +1,39 @@ +//! # Response +//! +//! Response model for service challenge responses + +use std::collections::HashMap; + +use crate::challenger::ChallengeResponseIds; +use bitcoin_hashes::sha256d; +use serde::Serialize; + +/// Response struct that models responses to service challenges +/// by keeping track of the total number of challengers and the +/// number of challenges that each bid owner responded to +#[derive(Debug, Serialize, PartialEq)] +pub struct Response { + /// Total number of challenges + pub num_challenges: u32, + /// Number of responses per bid txid + pub bid_responses: HashMap, +} + +impl Response { + /// Create new Response instance + pub fn new() -> Response { + Response { + num_challenges: 0, + bid_responses: HashMap::new(), + } + } + + /// Update Response struct from challenge response ids + pub fn update(&mut self, responses: &ChallengeResponseIds) { + self.num_challenges += 1; + for txid in responses.iter() { + let bid_entry = self.bid_responses.entry(*txid).or_insert(0); + *bid_entry += 1; + } + } +} diff --git a/src/storage.rs b/src/storage.rs index a87ebed..77d31ea 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -14,6 +14,7 @@ use crate::challenger::{ChallengeResponseIds, ChallengeState}; use crate::config::StorageConfig; use crate::error::{Error::MongoDb, Result}; use crate::request::{BidSet, Request}; +use crate::response::Response; /// Storage trait defining required functionality for objects that store request /// and challenge information @@ -25,7 +26,7 @@ pub trait Storage { /// Store response for a specific challenge request fn save_response(&self, request_hash: sha256d::Hash, ids: &ChallengeResponseIds) -> Result<()>; /// Get challenge response for a specific request - fn get_response(&self, request_hash: sha256d::Hash) -> Result>; + fn get_response(&self, request_hash: sha256d::Hash) -> Result>; /// Get all bids for a specific request fn get_bids(&self, request_hash: sha256d::Hash) -> Result; /// Get all the requests @@ -137,7 +138,7 @@ impl Storage for MongoStorage { let db_locked = self.db.lock().unwrap(); self.auth(&db_locked)?; - let request = db_locked + let request_id = db_locked .collection("Request") .find_one( Some(doc! { @@ -145,16 +146,31 @@ impl Storage for MongoStorage { }), None, )? - .unwrap(); + .unwrap() + .get("_id") + .unwrap() + .clone(); - let _ = db_locked - .collection("Response") - .insert_one(challenge_responses_to_doc(request.get("_id").unwrap(), ids), None)?; + let coll = db_locked.collection("Response"); + let filter = doc! {"request_id": request_id.clone()}; + match coll.find_one(Some(filter.clone()), None)? { + Some(res) => { + let mut resp = doc_to_response(&res); + resp.update(ids); + let update = doc! {"$set" => response_to_doc(&request_id, &resp)}; + let _ = coll.update_one(filter, update, None)?; + } + None => { + let mut resp = Response::new(); + resp.update(ids); + let _ = coll.insert_one(response_to_doc(&request_id, &resp), None)?; + } + } Ok(()) } /// Get challenge response for a specific request - fn get_response(&self, request_hash: sha256d::Hash) -> Result> { + fn get_response(&self, request_hash: sha256d::Hash) -> Result> { let db_locked = self.db.lock().unwrap(); self.auth(&db_locked)?; @@ -165,7 +181,7 @@ impl Storage for MongoStorage { "from": "Response", "localField": "_id", "foreignField": "request_id", - "as": "challenges" + "as": "response" } }, doc! { @@ -173,19 +189,21 @@ impl Storage for MongoStorage { "txid": request_hash.to_string() }, }, + doc! { + "$unwind": { + "path": "$response" + } + }, ] .to_vec(), None, )?; drop(db_locked); // drop immediately on get requests - let mut all_resps: Vec = Vec::new(); if let Some(resp) = resp_aggr.next() { - for challenge in resp?.get_array("challenges").unwrap().iter() { - all_resps.push(doc_to_challenge_responses(challenge.as_document().unwrap())) - } + return Ok(Some(doc_to_response(&resp?.get_document("response").unwrap()))); } - Ok(all_resps) + Ok(None) } /// Get all bids for a specific request diff --git a/src/util/doc_format.rs b/src/util/doc_format.rs index 15343ed..3eba501 100644 --- a/src/util/doc_format.rs +++ b/src/util/doc_format.rs @@ -3,13 +3,15 @@ //! doc format is used to store items in the db. //! File contains methods to convert to/from document format. +use std::collections::HashMap; +use std::str::FromStr; + use bitcoin_hashes::{hex::FromHex, sha256d}; use mongodb::{ordered::OrderedDocument, Bson}; use secp256k1::key::PublicKey; -use std::str::FromStr; -use crate::challenger::ChallengeResponseIds; use crate::request::{Bid, Request}; +use crate::response::Response; /// Util method that generates a Request document from a request pub fn request_to_doc(request: &Request) -> OrderedDocument { @@ -56,25 +58,39 @@ pub fn doc_to_bid(doc: &OrderedDocument) -> Bid { } } -/// Util method that generates a Response document from challenge responses -pub fn challenge_responses_to_doc(request_id: &Bson, responses: &ChallengeResponseIds) -> OrderedDocument { - let bids = responses +/// Util method that generates a Response document from request response +pub fn response_to_doc(request_id: &Bson, response: &Response) -> OrderedDocument { + let bid_resps_doc: OrderedDocument = response + .bid_responses .iter() - .map(|x| Bson::String(x.to_string())) - .collect::>(); + .map(|(key, val)| (key.to_string(), Bson::I32(*val as i32))) + .collect(); doc! { "request_id": request_id.clone(), - "bid_txids": bids + "num_challenges": response.num_challenges, + "bid_responses": bid_resps_doc } } -/// Util method that generates challenge responses from a Response document -pub fn doc_to_challenge_responses(doc: &OrderedDocument) -> ChallengeResponseIds { - doc.get_array("bid_txids") +/// Util method that generates request response from a Response document +pub fn doc_to_response(doc: &OrderedDocument) -> Response { + let bid_resps: HashMap = doc + .get("bid_responses") + .unwrap() + .as_document() .unwrap() .iter() - .map(|x| sha256d::Hash::from_hex(x.as_str().unwrap()).unwrap()) - .collect() + .map(|(key, val)| { + ( + sha256d::Hash::from_hex(key.as_str()).unwrap(), + val.as_i32().unwrap() as u32, + ) + }) + .collect(); + Response { + num_challenges: doc.get("num_challenges").unwrap().as_i32().unwrap() as u32, + bid_responses: bid_resps, + } } #[cfg(test)] @@ -87,6 +103,7 @@ mod tests { use secp256k1::key::PublicKey; use std::str::FromStr; + use crate::challenger::ChallengeResponseIds; use crate::request::Bid; use crate::util::testing::gen_dummy_hash; @@ -145,40 +162,52 @@ mod tests { } #[test] - fn challenge_responses_doc_test() { + fn response_doc_test() { let id = ObjectId::new().unwrap(); let mut ids = ChallengeResponseIds::new(); + let mut resp = Response::new(); - let doc = challenge_responses_to_doc(&Bson::ObjectId(id.clone()), &ids); + let doc = response_to_doc(&Bson::ObjectId(id.clone()), &resp); assert_eq!( doc! { "request_id": id.clone(), - "bid_txids": [] + "num_challenges": 0, + "bid_responses": doc! {} }, doc ); - assert_eq!(ids, doc_to_challenge_responses(&doc)); + assert_eq!(resp, doc_to_response(&doc)); - let _ = ids.insert(gen_dummy_hash(0)); - let doc = challenge_responses_to_doc(&Bson::ObjectId(id.clone()), &ids); + let hash0 = gen_dummy_hash(0); + let _ = ids.insert(hash0); + resp.update(&ids); + let doc = response_to_doc(&Bson::ObjectId(id.clone()), &resp); assert_eq!( doc! { "request_id": id.clone(), - "bid_txids": [gen_dummy_hash(0).to_string()] + "num_challenges": 1, + "bid_responses": doc! { gen_dummy_hash(0).to_string(): 1 } }, doc ); - assert_eq!(ids, doc_to_challenge_responses(&doc)); + assert_eq!(resp, doc_to_response(&doc)); let _ = ids.insert(gen_dummy_hash(1)); let _ = ids.insert(gen_dummy_hash(2)); let _ = ids.insert(gen_dummy_hash(3)); - let doc = challenge_responses_to_doc(&Bson::ObjectId(id.clone()), &ids); + resp.update(&ids); + let doc = response_to_doc(&Bson::ObjectId(id.clone()), &resp); assert_eq!(&id, doc.get("request_id").unwrap().as_object_id().unwrap()); - for id in doc.get_array("bid_txids").unwrap().iter() { - assert!(ids.contains(&sha256d::Hash::from_hex(id.as_str().unwrap()).unwrap())); + assert_eq!(2, doc.get("num_challenges").unwrap().as_i32().unwrap()); + for (key, val) in doc.get_document("bid_responses").unwrap().iter() { + if sha256d::Hash::from_hex(key.as_str()).unwrap() == hash0 { + assert_eq!(2, val.as_i32().unwrap()); + } else { + assert_eq!(1, val.as_i32().unwrap()); + } + assert!(ids.contains(&sha256d::Hash::from_hex(key.as_str()).unwrap())); } - assert_eq!(4, doc.get_array("bid_txids").unwrap().len()); - assert_eq!(ids, doc_to_challenge_responses(&doc)); + assert_eq!(4, doc.get_document("bid_responses").unwrap().len()); + assert_eq!(resp, doc_to_response(&doc)); } } diff --git a/src/util/testing.rs b/src/util/testing.rs index 89ebb06..becc794 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -13,6 +13,7 @@ use util::doc_format::*; use crate::challenger::{ChallengeResponseIds, ChallengeState}; use crate::clientchain::ClientChain; use crate::request::{Bid, BidSet, Request as ServiceRequest}; +use crate::response::Response; use crate::service::Service; use crate::storage::*; @@ -289,21 +290,32 @@ impl Storage for MockStorage { if self.return_err { return Err(Error::from(CError::Generic("save_response failed".to_owned()))); } + + for resp_doc in self.challenge_responses.borrow_mut().iter_mut() { + if resp_doc.get("request_id").unwrap().as_str().unwrap() == &request_hash.to_string() { + let mut resp = doc_to_response(resp_doc); + resp.update(&ids); + *resp_doc = response_to_doc(&Bson::String(request_hash.to_string()), &resp); + return Ok(()); + } + } + + let mut resp = Response::new(); + resp.update(&ids); self.challenge_responses .borrow_mut() - .push(challenge_responses_to_doc(&Bson::String(request_hash.to_string()), ids)); + .push(response_to_doc(&Bson::String(request_hash.to_string()), &resp)); Ok(()) } /// Get challenge response for a specific request - fn get_response(&self, request_hash: sha256d::Hash) -> Result> { - let mut challenge_responses = vec![]; + fn get_response(&self, request_hash: sha256d::Hash) -> Result> { for doc in self.challenge_responses.borrow().to_vec().iter() { if doc.get("request_id").unwrap().as_str().unwrap() == request_hash.to_string() { - challenge_responses.push(doc_to_challenge_responses(doc)); + return Ok(Some(doc_to_response(doc))); } } - Ok(challenge_responses) + Ok(None) } /// Get all bids for a specific request From fde79f3be188e0f237e9a353f630e0bcf06f71bb Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Tue, 12 Nov 2019 11:21:44 +0000 Subject: [PATCH 10/40] getrequestreponses->getrequestreponse --- src/api.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/api.rs b/src/api.rs index 6615e35..197a49b 100644 --- a/src/api.rs +++ b/src/api.rs @@ -74,19 +74,19 @@ struct GetRequestResponsesParams { } #[derive(Serialize, Debug)] -struct GetRequestResponsesResponse { +struct GetRequestResponseResponse { response: ChallengeResponse, } /// Get requests responses RPC call returning all responses for a specific /// request transaction id hash -fn get_request_responses(params: Params, storage: Arc) -> futures::Finished { +fn get_request_response(params: Params, storage: Arc) -> futures::Finished { let try_parse = params.parse::(); match try_parse { Ok(parse) => { let response_get = storage.get_response(parse.txid).unwrap(); if let Some(response) = response_get { - let res_serialized = serde_json::to_string(&GetRequestResponsesResponse { response }).unwrap(); + let res_serialized = serde_json::to_string(&GetRequestResponseResponse { response }).unwrap(); return futures::finished(Value::String(res_serialized)); } else { return futures::failed(Error { @@ -127,8 +127,8 @@ pub fn run_api_server( ) -> thread::JoinHandle<()> { let mut io = IoHandler::default(); let storage_ref = storage.clone(); - io.add_method("getrequestresponses", move |params: Params| { - get_request_responses(params, storage_ref.clone()) + io.add_method("getrequestresponse", move |params: Params| { + get_request_response(params, storage_ref.clone()) }); let storage_ref = storage.clone(); io.add_method("getrequest", move |params: Params| { @@ -237,7 +237,7 @@ mod tests { } #[test] - fn get_request_responses_test() { + fn get_request_response_test() { let storage = Arc::new(MockStorage::new()); let dummy_hash = gen_dummy_hash(1); let dummy_hash_bid = gen_dummy_hash(2); @@ -245,7 +245,7 @@ mod tests { // no such request let s = format!(r#"{{"txid": "{}"}}"#, dummy_hash.to_string()); let params: Params = serde_json::from_str(&s).unwrap(); - let resp = get_request_responses(params, storage.clone()); + let resp = get_request_response(params, storage.clone()); assert_eq!( "Invalid params: `txid` does not exist.", resp.wait().unwrap_err().message @@ -258,7 +258,7 @@ mod tests { // invalid key let s = format!(r#"{{"hash": "{}"}}"#, dummy_hash.to_string()); let params: Params = serde_json::from_str(&s).unwrap(); - let resp = get_request_responses(params, storage.clone()); + let resp = get_request_response(params, storage.clone()); assert_eq!( "Invalid params: missing field `txid`.", resp.wait().unwrap_err().message @@ -267,7 +267,7 @@ mod tests { // invalid value let s = format!(r#"{{"txid": "{}a"}}"#, dummy_hash.to_string()); let params: Params = serde_json::from_str(&s).unwrap(); - let resp = get_request_responses(params, storage.clone()); + let resp = get_request_response(params, storage.clone()); assert_eq!( "Invalid params: bad hex string length 65 (expected 64).", resp.wait().unwrap_err().message @@ -276,7 +276,7 @@ mod tests { // valid key and value let s = format!(r#"{{"txid": "{}"}}"#, dummy_hash.to_string()); let params: Params = serde_json::from_str(&s).unwrap(); - let resp = get_request_responses(params, storage.clone()); + let resp = get_request_response(params, storage.clone()); assert_eq!( format!( r#"{{"response":{{"num_challenges":1,"bid_responses":{{"{}":1}}}}}}"#, From 2d033910b43b4fe4e10e1356832c74290d281d0c Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Tue, 12 Nov 2019 14:54:30 +0000 Subject: [PATCH 11/40] Fix report.py script for API changes --- scripts/report.py | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/scripts/report.py b/scripts/report.py index 849ed6b..b6e9afc 100755 --- a/scripts/report.py +++ b/scripts/report.py @@ -3,7 +3,7 @@ # # First connection to a local Ocean node is made, the request data for a # txid is found via getrequest RPC and fee size is calculated. -# Then getrequestresponses RPC is called to get challenge responses which can be +# Then getrequestresponse RPC is called to get challenge responses which can be # used to determine rewards for guardnodes. #!/usr/bin/env python3 @@ -82,9 +82,9 @@ def calculate_fees(rpc, start_height, end_height): return fee addr_prefix = 235 -txid = "78f954d07de5badbc1526a60fe0ea639216f17f490a3bf41e48840453eca243f" -url = 'https://userApi:passwordApi@coordinator-api.testnet.commerceblock.com:10006' -rpc = connect("ocean", "oceanpass", "localhost", "7043") +txid = "6e993034df3203c0867c98f420f85b5ffecd7cb8580e2b6f2d33764e1cbfb074" +url = 'http://userApi:passwordApi@localhost:3333' +rpc = connect("user1", "password1", "localhost", "5555") payload = '{{"jsonrpc": "2.0", "method": "getrequest", "params": {{"txid": "{}"}}, "id": 1}}'.format(txid) headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'} @@ -98,11 +98,8 @@ def calculate_fees(rpc, start_height, end_height): print("") print("Calculating total fees...") -# For requests that are serving the service chain the fee start/end heights -# can be picked up from the request information. For requests in client chains -# these heights need to be found manually and inserted below to calculate fees -fee_start_height = request['start_blockheight'] -fee_end_height = request['end_blockheight'] +fee_start_height = request['start_blockheight_clientchain'] +fee_end_height = request['end_blockheight_clientchain'] fee = calculate_fees(rpc, fee_start_height, fee_end_height) fee_percentage = request['fee_percentage'] fee_out = fee*fee_percentage/100 @@ -120,21 +117,17 @@ def calculate_fees(rpc, start_height, end_height): fee_per_guard = float(fee_out/len(bids)) print("") -payload = '{{"jsonrpc": "2.0", "method": "getrequestresponses", "params": {{"txid": "{}"}}, "id": 1}}'.format(txid) +payload = '{{"jsonrpc": "2.0", "method": "getrequestresponse", "params": {{"txid": "{}"}}, "id": 1}}'.format(txid) headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'} r = requests.post(url, data=payload, headers=headers) result = json.loads(json.loads(r.content)['result']) -challenge_resps = result["responses"] -num_of_challenges = len(challenge_resps) +challenge_resps = result["response"] +num_of_challenges = challenge_resps["num_challenges"] print("Number of challenges: {}".format(num_of_challenges)) resps = {} -for challenge_resp in challenge_resps: - for bid_resp in challenge_resp: - if bid_resp in resps: - resps[bid_resp] += (1/num_of_challenges) - else: - resps[bid_resp] = (1/num_of_challenges) +for (bid, resp_num) in challenge_resps["bid_responses"].items(): + resps[bid] = resp_num / num_of_challenges print("Results") for bid, key in bids.items(): From 31eeddf4527ecc9389f6703f1e87b461ecad2f07 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Tue, 12 Nov 2019 16:19:13 +0000 Subject: [PATCH 12/40] remove unused import --- src/util/doc_format.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/util/doc_format.rs b/src/util/doc_format.rs index 3eba501..8308f77 100644 --- a/src/util/doc_format.rs +++ b/src/util/doc_format.rs @@ -97,14 +97,9 @@ pub fn doc_to_response(doc: &OrderedDocument) -> Response { mod tests { use super::*; - use bitcoin_hashes::hex::FromHex; use mongodb::oid::ObjectId; - use mongodb::Bson; - use secp256k1::key::PublicKey; - use std::str::FromStr; use crate::challenger::ChallengeResponseIds; - use crate::request::Bid; use crate::util::testing::gen_dummy_hash; #[test] From 3265e006d32dc5686e43e435dc39eb0c2275b744 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Tue, 12 Nov 2019 16:22:21 +0000 Subject: [PATCH 13/40] Bump version to 0.3.9 --- CHANGELOG.md | 16 ++++++++++++++++ Cargo.toml | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d39ac66..3a6eab0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,20 @@ +# 0.3.x + +1. Fix issue with coordinator not storing empty responses +2. Report script improvements +3. Height checks in service not clientchain +4. Challenge asset key import +5. Docker secrets +6. Docker secrets +7. Bitcoin library updates +8. Docker secrets +9. Enhancements + +# 0.3.0 + +* RPC API + # 0.2.0 * Finished core interfaces and testing diff --git a/Cargo.toml b/Cargo.toml index 558c720..ed53ece 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "coordinator" -version = "0.1.0" +version = "0.3.9" authors = ["nkostoulas "] description = "Guardnode Coordinator implementation for the Commerceblock Covalence system" homepage = "https://github.com/commerceblock" From b3c33635ab330dba7e81d36ea4674811365298a8 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Tue, 12 Nov 2019 16:46:21 +0000 Subject: [PATCH 14/40] Move ocean lib to util --- Cargo.lock | 2 +- examples/demo.rs | 2 +- src/clientchain.rs | 2 +- src/lib.rs | 9 ++------- src/service.rs | 2 +- src/util/mod.rs | 8 ++++++++ src/{ => util}/ocean.rs | 0 7 files changed, 14 insertions(+), 11 deletions(-) create mode 100644 src/util/mod.rs rename src/{ => util}/ocean.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index e749ba2..418f9b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -242,7 +242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "coordinator" -version = "0.1.0" +version = "0.3.9" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitcoin 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/examples/demo.rs b/examples/demo.rs index 3538ffc..f2363da 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -29,7 +29,7 @@ use secp256k1::{Message, Secp256k1, SecretKey}; use coordinator::clientchain::get_first_unspent; use coordinator::coordinator as coordinator_main; -use coordinator::ocean::OceanClient; +use coordinator::util::ocean::OceanClient; /// Demo coordinator with listener and challenge service running /// mock implementation for service chain interface and ocean diff --git a/src/clientchain.rs b/src/clientchain.rs index cfb2d62..f6b2546 100644 --- a/src/clientchain.rs +++ b/src/clientchain.rs @@ -9,7 +9,7 @@ use ocean_rpc::{json, RpcApi}; use crate::config::ClientChainConfig; use crate::error::{CError, Error, Result}; -use crate::ocean::OceanClient; +use crate::util::ocean::OceanClient; /// Method that returns the first unspent output for given asset /// or an error if the client wallet does not have any unspent/funds diff --git a/src/lib.rs b/src/lib.rs index b31af30..a977636 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ //! # Coordinator Library //! -//! Basic functionality required by Coordinator daemon +//! Core functionality of the coordinator library // Coding conventions #![deny(non_upper_case_globals)] @@ -40,14 +40,9 @@ pub mod config; pub mod coordinator; pub mod error; pub mod listener; -pub mod ocean; pub mod request; pub mod response; pub mod service; pub mod storage; /// utilities -pub mod util { - pub mod checks; - pub mod doc_format; - pub mod testing; -} +pub mod util; diff --git a/src/service.rs b/src/service.rs index bb31319..d1b316d 100644 --- a/src/service.rs +++ b/src/service.rs @@ -7,8 +7,8 @@ use ocean_rpc::RpcApi; use crate::config::ServiceConfig; use crate::error::Result; -use crate::ocean::OceanClient; use crate::request::{Bid, BidSet, Request}; +use crate::util::ocean::OceanClient; /// Service trait defining functionality for interfacing with service chain pub trait Service { diff --git a/src/util/mod.rs b/src/util/mod.rs new file mode 100644 index 0000000..0d18852 --- /dev/null +++ b/src/util/mod.rs @@ -0,0 +1,8 @@ +//! # Util +//! +//! Util functionality required by the coordinator library + +pub mod checks; +pub mod doc_format; +pub mod ocean; +pub mod testing; diff --git a/src/ocean.rs b/src/util/ocean.rs similarity index 100% rename from src/ocean.rs rename to src/util/ocean.rs From a147b6077a99b61cdeac88cf4ad04d19dd7f3122 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Tue, 12 Nov 2019 16:59:26 +0000 Subject: [PATCH 15/40] Interfaces sub-module --- examples/demo.rs | 2 +- src/api.rs | 6 +++--- src/challenger.rs | 10 +++++----- src/coordinator.rs | 6 +++--- src/{ => interfaces}/clientchain.rs | 0 src/interfaces/mod.rs | 9 +++++++++ src/{ => interfaces}/request.rs | 0 src/{ => interfaces}/response.rs | 0 src/{ => interfaces}/service.rs | 2 +- src/{ => interfaces}/storage.rs | 4 ++-- src/lib.rs | 9 +++------ src/listener.rs | 2 +- src/util/doc_format.rs | 4 ++-- src/util/testing.rs | 10 +++++----- 14 files changed, 35 insertions(+), 29 deletions(-) rename src/{ => interfaces}/clientchain.rs (100%) create mode 100644 src/interfaces/mod.rs rename src/{ => interfaces}/request.rs (100%) rename src/{ => interfaces}/response.rs (100%) rename src/{ => interfaces}/service.rs (98%) rename src/{ => interfaces}/storage.rs (99%) diff --git a/examples/demo.rs b/examples/demo.rs index f2363da..11c066f 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -27,8 +27,8 @@ use hyper::{ use ocean_rpc::RpcApi; use secp256k1::{Message, Secp256k1, SecretKey}; -use coordinator::clientchain::get_first_unspent; use coordinator::coordinator as coordinator_main; +use coordinator::interfaces::clientchain::get_first_unspent; use coordinator::util::ocean::OceanClient; /// Demo coordinator with listener and challenge service running diff --git a/src/api.rs b/src/api.rs index 197a49b..6535635 100644 --- a/src/api.rs +++ b/src/api.rs @@ -15,9 +15,9 @@ use jsonrpc_http_server::{hyper::header, AccessControlAllowOrigin, DomainsValida use serde::{Deserialize, Serialize}; use crate::config::ApiConfig; -use crate::request::{BidSet, Request as ServiceRequest}; -use crate::response::Response as ChallengeResponse; -use crate::storage::Storage; +use crate::interfaces::request::{BidSet, Request as ServiceRequest}; +use crate::interfaces::response::Response as ChallengeResponse; +use crate::interfaces::storage::Storage; #[derive(Deserialize, Debug)] struct GetRequestParams { diff --git a/src/challenger.rs b/src/challenger.rs index 1d85638..515269a 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -9,11 +9,11 @@ use std::{thread, time}; use bitcoin_hashes::sha256d; -use crate::clientchain::ClientChain; use crate::error::{CError, Error, Result}; -use crate::request::{Bid, BidSet, Request}; -use crate::service::Service; -use crate::storage::Storage; +use crate::interfaces::clientchain::ClientChain; +use crate::interfaces::request::{Bid, BidSet, Request}; +use crate::interfaces::service::Service; +use crate::interfaces::storage::Storage; /// Verify attempt interval to client in ms pub const CHALLENGER_VERIFY_INTERVAL: u64 = 100; @@ -213,7 +213,7 @@ mod tests { use std::sync::mpsc::{channel, Receiver, Sender}; use crate::error::Error; - use crate::response::Response; + use crate::interfaces::response::Response; use crate::util::testing::{gen_dummy_hash, MockClientChain, MockService, MockStorage}; #[test] diff --git a/src/coordinator.rs b/src/coordinator.rs index 590f563..b6beeb2 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -10,11 +10,11 @@ use bitcoin_hashes::{hex::FromHex, sha256d}; use futures::sync::oneshot; use crate::challenger::ChallengeResponse; -use crate::clientchain::{ClientChain, RpcClientChain}; use crate::config::Config; use crate::error::Result; -use crate::service::{RpcService, Service}; -use crate::storage::{MongoStorage, Storage}; +use crate::interfaces::clientchain::{ClientChain, RpcClientChain}; +use crate::interfaces::service::{RpcService, Service}; +use crate::interfaces::storage::{MongoStorage, Storage}; /// Run coordinator main method pub fn run(config: Config) -> Result<()> { diff --git a/src/clientchain.rs b/src/interfaces/clientchain.rs similarity index 100% rename from src/clientchain.rs rename to src/interfaces/clientchain.rs diff --git a/src/interfaces/mod.rs b/src/interfaces/mod.rs new file mode 100644 index 0000000..b9cc2b0 --- /dev/null +++ b/src/interfaces/mod.rs @@ -0,0 +1,9 @@ +//! # Interfaces +//! +//! Interfaces used by the coordinator library + +pub mod clientchain; +pub mod request; +pub mod response; +pub mod service; +pub mod storage; diff --git a/src/request.rs b/src/interfaces/request.rs similarity index 100% rename from src/request.rs rename to src/interfaces/request.rs diff --git a/src/response.rs b/src/interfaces/response.rs similarity index 100% rename from src/response.rs rename to src/interfaces/response.rs diff --git a/src/service.rs b/src/interfaces/service.rs similarity index 98% rename from src/service.rs rename to src/interfaces/service.rs index d1b316d..2428143 100644 --- a/src/service.rs +++ b/src/interfaces/service.rs @@ -7,7 +7,7 @@ use ocean_rpc::RpcApi; use crate::config::ServiceConfig; use crate::error::Result; -use crate::request::{Bid, BidSet, Request}; +use crate::interfaces::request::{Bid, BidSet, Request}; use crate::util::ocean::OceanClient; /// Service trait defining functionality for interfacing with service chain diff --git a/src/storage.rs b/src/interfaces/storage.rs similarity index 99% rename from src/storage.rs rename to src/interfaces/storage.rs index 77d31ea..a95ce80 100644 --- a/src/storage.rs +++ b/src/interfaces/storage.rs @@ -13,8 +13,8 @@ use util::doc_format::*; use crate::challenger::{ChallengeResponseIds, ChallengeState}; use crate::config::StorageConfig; use crate::error::{Error::MongoDb, Result}; -use crate::request::{BidSet, Request}; -use crate::response::Response; +use crate::interfaces::request::{BidSet, Request}; +use crate::interfaces::response::Response; /// Storage trait defining required functionality for objects that store request /// and challenge information diff --git a/src/lib.rs b/src/lib.rs index a977636..cc27544 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,14 +35,11 @@ extern crate jsonrpc_http_server; pub mod api; pub mod challenger; -pub mod clientchain; pub mod config; pub mod coordinator; pub mod error; pub mod listener; -pub mod request; -pub mod response; -pub mod service; -pub mod storage; -/// utilities + +pub mod interfaces; +/// sub-mods pub mod util; diff --git a/src/listener.rs b/src/listener.rs index 0cc59c1..e3ae231 100644 --- a/src/listener.rs +++ b/src/listener.rs @@ -20,7 +20,7 @@ use serde_json::{self, Value}; use crate::challenger::{ChallengeResponse, ChallengeState}; use crate::error::Result; -use crate::request::Bid; +use crate::interfaces::request::Bid; /// Messsage type for challenge proofs sent by guardnodes #[derive(Debug)] diff --git a/src/util/doc_format.rs b/src/util/doc_format.rs index 8308f77..ea4f718 100644 --- a/src/util/doc_format.rs +++ b/src/util/doc_format.rs @@ -10,8 +10,8 @@ use bitcoin_hashes::{hex::FromHex, sha256d}; use mongodb::{ordered::OrderedDocument, Bson}; use secp256k1::key::PublicKey; -use crate::request::{Bid, Request}; -use crate::response::Response; +use crate::interfaces::request::{Bid, Request}; +use crate::interfaces::response::Response; /// Util method that generates a Request document from a request pub fn request_to_doc(request: &Request) -> OrderedDocument { diff --git a/src/util/testing.rs b/src/util/testing.rs index becc794..0ad1c82 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -11,11 +11,11 @@ use std::str::FromStr; use util::doc_format::*; use crate::challenger::{ChallengeResponseIds, ChallengeState}; -use crate::clientchain::ClientChain; -use crate::request::{Bid, BidSet, Request as ServiceRequest}; -use crate::response::Response; -use crate::service::Service; -use crate::storage::*; +use crate::interfaces::clientchain::ClientChain; +use crate::interfaces::request::{Bid, BidSet, Request as ServiceRequest}; +use crate::interfaces::response::Response; +use crate::interfaces::service::Service; +use crate::interfaces::storage::*; use crate::error::*; From ccc4c345bb33c50f2fb943796e5c3dfa8105d390 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Tue, 12 Nov 2019 17:13:28 +0000 Subject: [PATCH 16/40] Move main.rs to bin/ --- src/{ => bin}/main.rs | 0 src/lib.rs | 1 - 2 files changed, 1 deletion(-) rename src/{ => bin}/main.rs (100%) diff --git a/src/main.rs b/src/bin/main.rs similarity index 100% rename from src/main.rs rename to src/bin/main.rs diff --git a/src/lib.rs b/src/lib.rs index cc27544..8e8a3df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,5 +41,4 @@ pub mod error; pub mod listener; pub mod interfaces; -/// sub-mods pub mod util; From 722380eadab815a98e1ce074c5351c27d34b3b83 Mon Sep 17 00:00:00 2001 From: tomossomot Date: Wed, 13 Nov 2019 17:56:10 +0000 Subject: [PATCH 17/40] issue 52 --- config/default.toml | 4 ++ src/challenger.rs | 105 +++++++++++++++++++++++++++++++++++++++----- src/clientchain.rs | 5 ++- src/config.rs | 12 ++++- src/coordinator.rs | 16 ++----- src/util/testing.rs | 2 +- 6 files changed, 116 insertions(+), 28 deletions(-) diff --git a/config/default.toml b/config/default.toml index 758ec6f..4ef0cae 100644 --- a/config/default.toml +++ b/config/default.toml @@ -7,6 +7,9 @@ # Frequency of creating new challenges, in number of blocks # challenge_frequency = 2 +# Block find time of service chain, in seconds +# block_time = 60 + # Host address that the listener binds to and receives guardnode requests listener_host = "127.0.0.1:9999" @@ -25,6 +28,7 @@ host = "127.0.0.1:5555" user = "user1" pass = "password1" genesis_hash = "ff8950160a77988cdc485913568d06c2d69a8c952ef0f179b4b097e3de63d7cc" +block_time = 60 asset = "CHALLENGE" asset_key = "cScSHCQp9AEwzZoucRpX9bMRkLCJ4LoQWBNFTZuD6tPX9qwNMWfQ" diff --git a/src/challenger.rs b/src/challenger.rs index 1d85638..ff19fd1 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -1,6 +1,7 @@ //! Challenger //! -//! Methods and models for fetching, structuring and running challenge requests +//! Methods and models for fetching, structuring, storing and running challenge +//! requests use std::collections::HashSet; use std::sync::mpsc::{Receiver, RecvTimeoutError}; @@ -10,6 +11,7 @@ use std::{thread, time}; use bitcoin_hashes::sha256d; use crate::clientchain::ClientChain; +use crate::config::Config; use crate::error::{CError, Error, Result}; use crate::request::{Bid, BidSet, Request}; use crate::service::Service; @@ -97,15 +99,13 @@ pub fn run_challenge_request( challenge_frequency: u64, refresh_delay: time::Duration, ) -> Result<()> { - let mut request = challenge_state.lock().unwrap().request.clone(); // clone as const and drop mutex + let request = challenge_state.lock().unwrap().request.clone(); // clone as const and drop mutex info! {"Running challenge request: {:?}", request.txid}; let mut prev_challenge_height: u64 = 0; loop { let challenge_height = service.get_blockheight()?; info! {"service chain height: {}", challenge_height} if (request.end_blockheight as u64) < challenge_height { - request.end_blockheight_clientchain = clientchain.get_block_count()?; - storage.update_request(request)?; break; } else if (challenge_height - prev_challenge_height) < challenge_frequency { info! {"Sleeping for {} sec...",time::Duration::as_secs(&refresh_delay)} @@ -134,6 +134,34 @@ pub fn run_challenge_request( Ok(()) } +/// Update challenge state request with client chain start and end block +/// heights and store challenge state +/// If request already stored set challenge state request to request in +/// storage (catcher for coordinator failure after storing request but +/// before request service period over) +pub fn update_challenge_request_state( + config: &Config, + clientchain: &K, + storage: Arc, + challenge: &mut ChallengeState, +) -> Result<()> { + match storage.get_request(challenge.request.txid)? { + Some(req) => challenge.request = req, + None => { + // Set request's start_blockheight_clientchain + challenge.request.start_blockheight_clientchain = clientchain.get_blockheight()?; + let service_period_time_s = + (challenge.request.end_blockheight - challenge.request.start_blockheight) * config.block_time as u32; + // Calculate and set request's end_blockheight_clientchain + challenge.request.end_blockheight_clientchain = challenge.request.start_blockheight_clientchain + + (service_period_time_s as f32 / config.clientchain.block_time as f32).floor() as u32; + storage.save_challenge_state(&challenge)?; // Store Challenge + // Request + } + } + Ok(()) +} + /// Tuple struct to store a verified challenge response /// for a winning bid on a specific challenge hash #[derive(Debug, Hash, Clone)] @@ -212,9 +240,10 @@ mod tests { use std::sync::mpsc::{channel, Receiver, Sender}; + use crate::config; use crate::error::Error; use crate::response::Response; - use crate::util::testing::{gen_dummy_hash, MockClientChain, MockService, MockStorage}; + use crate::util::testing::{gen_challenge_state, gen_dummy_hash, MockClientChain, MockService, MockStorage}; #[test] fn verify_challenge_test() { @@ -282,6 +311,64 @@ mod tests { } } + #[test] + fn update_challenge_request_state_test() { + let mut config = config::Config::new().unwrap(); + let clientchain = MockClientChain::new(); + let storage = Arc::new(MockStorage::new()); + + let dummy_hash = gen_dummy_hash(11); + let mut challenge = gen_challenge_state(&dummy_hash); + + // Test challenge state request set and stored correctly + let _ = clientchain.height.replace(1); + config.block_time = 1; + config.clientchain.block_time = 1; + let _ = update_challenge_request_state(&config, &clientchain, storage.clone(), &mut challenge); + // All fields stay the same but start and end blockheight_clientchain + let mut comparison_challenge_request = challenge.request.clone(); + comparison_challenge_request.start_blockheight_clientchain = 1; + comparison_challenge_request.end_blockheight_clientchain = 1 + 3; + assert_eq!(challenge.request, comparison_challenge_request); + assert_eq!( + storage.get_request(challenge.request.txid).unwrap().unwrap(), + comparison_challenge_request + ); + + // Test challenge state set and storage performed correctly + // for client chain block time half of service chain block time + let storage = Arc::new(MockStorage::new()); //reset storage + let _ = clientchain.height.replace(1); + config.block_time = 2; + config.clientchain.block_time = 1; + let _ = update_challenge_request_state(&config, &clientchain, storage.clone(), &mut challenge); + let mut comparison_challenge_request = challenge.request.clone(); + comparison_challenge_request.start_blockheight_clientchain = 1; + comparison_challenge_request.end_blockheight_clientchain = 1 + 2 * 3; + assert_eq!(challenge.request, comparison_challenge_request); + assert_eq!( + storage.get_request(challenge.request.txid).unwrap().unwrap(), + comparison_challenge_request + ); + + // Test stored version unchanged if attempt is made to store request a second + // time + let old_challenge = challenge.clone(); // save old challenge state + challenge.request.fee_percentage = 25; // alter random field + let new_challenge = challenge.clone(); // save new challenge state + let _ = update_challenge_request_state(&config, &clientchain, storage.clone(), &mut challenge); + assert_eq!(challenge.request, old_challenge.request); + assert_eq!( + storage.get_request(challenge.request.txid).unwrap().unwrap(), + old_challenge.request + ); + assert_ne!(challenge.request, new_challenge.request); + assert_ne!( + storage.get_request(challenge.request.txid).unwrap().unwrap(), + new_challenge.request + ); + } + #[test] fn check_request_test() { let service = MockService::new(); @@ -371,13 +458,13 @@ mod tests { let dummy_hash = gen_dummy_hash(0); let dummy_other_hash = gen_dummy_hash(9); - let mut dummy_request = service.get_request(&dummy_hash).unwrap().unwrap(); + let dummy_request = service.get_request(&dummy_hash).unwrap().unwrap(); // test normal operation of run_challenge_request by adding some responses for // the first challenge let _ = service.height.replace(dummy_request.start_blockheight as u64); // set height for fetch_next to succeed - let mut challenge_state = fetch_next(&service, &dummy_hash).unwrap().unwrap(); + let challenge_state = fetch_next(&service, &dummy_hash).unwrap().unwrap(); storage.save_challenge_state(&challenge_state).unwrap(); let (vtx, vrx): (Sender, Receiver) = channel(); @@ -411,8 +498,6 @@ mod tests { assert_eq!(challenge_state.bids, bids); let requests = storage.get_requests().unwrap(); assert_eq!(1, requests.len()); - // manually set to allow for comparison of all unchanged fields - challenge_state.request.end_blockheight_clientchain = 3; assert_eq!(&challenge_state.request, &requests[0]); assert_eq!( challenge_state.request, @@ -481,8 +566,6 @@ mod tests { ); match res { Ok(_) => { - // manual set of end_blockheight_clientchain for comparison - dummy_request.end_blockheight_clientchain = *clientchain.height.borrow(); assert_eq!(storage.get_requests().unwrap()[0], dummy_request); } Err(_) => assert!(false, "should not return error"), diff --git a/src/clientchain.rs b/src/clientchain.rs index cfb2d62..ab8d402 100644 --- a/src/clientchain.rs +++ b/src/clientchain.rs @@ -34,7 +34,7 @@ pub trait ClientChain { /// Verify challenge transaction has been included in the chain fn verify_challenge(&self, txid: &sha256d::Hash) -> Result; /// Get height of client chain - fn get_block_count(&self) -> Result; + fn get_blockheight(&self) -> Result; } /// Rpc implementation of Service using an underlying ocean rpc connection @@ -126,8 +126,9 @@ impl<'a> ClientChain for RpcClientChain<'a> { } Ok(false) } + /// Return block count of chain - fn get_block_count(&self) -> Result { + fn get_blockheight(&self) -> Result { Ok(self.client.get_block_count()? as u32) } } diff --git a/src/config.rs b/src/config.rs index 4f983d9..4a43e3c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -63,6 +63,8 @@ pub struct ClientChainConfig { pub pass: String, /// Client genesis hash pub genesis_hash: String, + /// Block time in seconds + pub block_time: u64, /// Client asset label pub asset: String, /// Client asset key @@ -76,6 +78,7 @@ impl Default for ClientChainConfig { user: String::new(), pass: String::new(), genesis_hash: String::new(), + block_time: CONFIG_BLOCK_TIME_DEFAULT, asset: String::from("CHALLENGE"), asset_key: String::new(), } @@ -106,6 +109,10 @@ impl Default for StorageConfig { } } +// pub trait Config { +// fn new(&self) -> Result where Self: std::marker::Sized; +// } + /// Config struct storing all config #[derive(Debug, Serialize, Deserialize)] pub struct Config { @@ -115,7 +122,7 @@ pub struct Config { pub challenge_duration: u64, /// Challenge frequency in number of blocks pub challenge_frequency: u64, - /// Block time in seconds + /// Block time of service chain in seconds pub block_time: u64, /// Listener host address pub listener_host: String, @@ -215,6 +222,9 @@ impl Config { if let Ok(v) = env::var("CO_CLIENTCHAIN_GENESIS_HASH") { let _ = conf_rs.set("clientchain.genesis_hash", v)?; } + if let Ok(v) = env::var("CO_CLIENTCHAIN_BLOCK_TIME") { + let _ = conf_rs.set("clientchain.block_time", v)?; + } if let Ok(v) = env::var("CO_STORAGE_HOST") { let _ = conf_rs.set("storage.host", v)?; diff --git a/src/coordinator.rs b/src/coordinator.rs index 590f563..7e98a77 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -54,19 +54,9 @@ pub fn run_request( match ::challenger::fetch_next(service, &genesis_hash)? { Some(mut challenge) => { // First attempt to store the challenge state information - // on requests and winning bids and exit if that fails - // Check if request already stored. If so set challenge request to - // request in table (catcher for coordinator failure after storing - // request but before request service period over) - match storage.get_request(challenge.request.txid)? { - Some(req) => challenge.request = req, - None => { - // Set request's start_blockheight_clientchain - challenge.request.start_blockheight_clientchain = clientchain.get_block_count()?; - // Store Challenge Request - storage.save_challenge_state(&challenge)?; - } - } + // on requests and winning bids and exit if it fails. + // If already set update challenge state with correct version from storage + ::challenger::update_challenge_request_state(config, clientchain, storage.clone(), &mut challenge)?; // create a challenge state mutex to share between challenger and listener let shared_challenge = Arc::new(Mutex::new(challenge)); diff --git a/src/util/testing.rs b/src/util/testing.rs index becc794..19cdeea 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -121,7 +121,7 @@ impl ClientChain for MockClientChain { } /// Get block count dummy - fn get_block_count(&self) -> Result { + fn get_blockheight(&self) -> Result { Ok(self.height.clone().into_inner()) } } From 47d087f2b79e45017339e5a624d84a50e32daa50 Mon Sep 17 00:00:00 2001 From: tomossomot Date: Wed, 13 Nov 2019 18:05:46 +0000 Subject: [PATCH 18/40] removed old test --- src/challenger.rs | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/src/challenger.rs b/src/challenger.rs index 2c2aa78..7775c00 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -10,6 +10,7 @@ use std::{thread, time}; use bitcoin_hashes::sha256d; +use crate::config::Config; use crate::error::{CError, Error, Result}; use crate::interfaces::clientchain::ClientChain; use crate::interfaces::request::{Bid, BidSet, Request}; @@ -242,7 +243,7 @@ mod tests { use crate::config; use crate::error::Error; use crate::interfaces::response::Response; - use crate::util::testing::{gen_dummy_hash, MockClientChain, MockService, MockStorage}; + use crate::util::testing::{gen_challenge_state, gen_dummy_hash, MockClientChain, MockService, MockStorage}; #[test] fn verify_challenge_test() { @@ -548,28 +549,6 @@ mod tests { Err(_) => assert!(false, "should not return error"), } - // test end_blockheight_clientchain set correctly in request - vtx.send(ChallengeResponse(dummy_challenge_hash, dummy_bid.clone())) - .unwrap(); // send again - let _ = service.height.replace(dummy_request.start_blockheight as u64); // set height back to starting height - let res = run_challenge_request( - &service, - &clientchain, - Arc::new(Mutex::new(challenge_state.clone())), - &vrx, - storage.clone(), - time::Duration::from_millis(10), - time::Duration::from_millis(10), - 1, - time::Duration::from_millis(10), - ); - match res { - Ok(_) => { - assert_eq!(storage.get_requests().unwrap()[0], dummy_request); - } - Err(_) => assert!(false, "should not return error"), - }; - // test client chain failure let _ = service.height.replace(dummy_request.start_blockheight as u64); // set height for fetch_next to succeed let challenge_state = fetch_next(&service, &dummy_hash).unwrap().unwrap(); From cde3cb4cca995b1881d91f53de8daa15b651f94a Mon Sep 17 00:00:00 2001 From: tomossomot Date: Wed, 13 Nov 2019 18:11:01 +0000 Subject: [PATCH 19/40] remove old code --- src/config.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/config.rs b/src/config.rs index 4a43e3c..65c3a8b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -109,10 +109,6 @@ impl Default for StorageConfig { } } -// pub trait Config { -// fn new(&self) -> Result where Self: std::marker::Sized; -// } - /// Config struct storing all config #[derive(Debug, Serialize, Deserialize)] pub struct Config { From 8479c7d1cc243c3c009360d654bb95eea31068cf Mon Sep 17 00:00:00 2001 From: tomossomot Date: Thu, 14 Nov 2019 11:21:43 +0000 Subject: [PATCH 20/40] update_challenge_request_state improvements --- src/challenger.rs | 34 ++++++++++++++++------------------ src/coordinator.rs | 8 +++++++- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/challenger.rs b/src/challenger.rs index 7775c00..a9eb59f 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -10,7 +10,6 @@ use std::{thread, time}; use bitcoin_hashes::sha256d; -use crate::config::Config; use crate::error::{CError, Error, Result}; use crate::interfaces::clientchain::ClientChain; use crate::interfaces::request::{Bid, BidSet, Request}; @@ -140,21 +139,22 @@ pub fn run_challenge_request( /// storage (catcher for coordinator failure after storing request but /// before request service period over) pub fn update_challenge_request_state( - config: &Config, clientchain: &K, storage: Arc, challenge: &mut ChallengeState, + block_time_servicechain: u64, + block_time_clientchain: u64, ) -> Result<()> { match storage.get_request(challenge.request.txid)? { Some(req) => challenge.request = req, None => { // Set request's start_blockheight_clientchain challenge.request.start_blockheight_clientchain = clientchain.get_blockheight()?; - let service_period_time_s = - (challenge.request.end_blockheight - challenge.request.start_blockheight) * config.block_time as u32; + let service_period_time_s = (challenge.request.end_blockheight - challenge.request.start_blockheight) + * block_time_servicechain as u32; // Calculate and set request's end_blockheight_clientchain challenge.request.end_blockheight_clientchain = challenge.request.start_blockheight_clientchain - + (service_period_time_s as f32 / config.clientchain.block_time as f32).floor() as u32; + + (service_period_time_s as f32 / block_time_clientchain as f32).floor() as u32; storage.save_challenge_state(&challenge)?; // Store Challenge // Request } @@ -240,7 +240,6 @@ mod tests { use std::sync::mpsc::{channel, Receiver, Sender}; - use crate::config; use crate::error::Error; use crate::interfaces::response::Response; use crate::util::testing::{gen_challenge_state, gen_dummy_hash, MockClientChain, MockService, MockStorage}; @@ -313,22 +312,21 @@ mod tests { #[test] fn update_challenge_request_state_test() { - let mut config = config::Config::new().unwrap(); let clientchain = MockClientChain::new(); let storage = Arc::new(MockStorage::new()); let dummy_hash = gen_dummy_hash(11); let mut challenge = gen_challenge_state(&dummy_hash); + let num_service_chain_blocks = challenge.request.end_blockheight - challenge.request.start_blockheight; // Test challenge state request set and stored correctly let _ = clientchain.height.replace(1); - config.block_time = 1; - config.clientchain.block_time = 1; - let _ = update_challenge_request_state(&config, &clientchain, storage.clone(), &mut challenge); + let _ = update_challenge_request_state(&clientchain, storage.clone(), &mut challenge, 1, 1); // All fields stay the same but start and end blockheight_clientchain let mut comparison_challenge_request = challenge.request.clone(); - comparison_challenge_request.start_blockheight_clientchain = 1; - comparison_challenge_request.end_blockheight_clientchain = 1 + 3; + comparison_challenge_request.start_blockheight_clientchain = challenge.request.start_blockheight_clientchain; + comparison_challenge_request.end_blockheight_clientchain = + challenge.request.start_blockheight_clientchain + num_service_chain_blocks; // start_height + number of servcie chain blocks assert_eq!(challenge.request, comparison_challenge_request); assert_eq!( storage.get_request(challenge.request.txid).unwrap().unwrap(), @@ -339,12 +337,12 @@ mod tests { // for client chain block time half of service chain block time let storage = Arc::new(MockStorage::new()); //reset storage let _ = clientchain.height.replace(1); - config.block_time = 2; - config.clientchain.block_time = 1; - let _ = update_challenge_request_state(&config, &clientchain, storage.clone(), &mut challenge); + let _ = update_challenge_request_state(&clientchain, storage.clone(), &mut challenge, 2, 1); let mut comparison_challenge_request = challenge.request.clone(); - comparison_challenge_request.start_blockheight_clientchain = 1; - comparison_challenge_request.end_blockheight_clientchain = 1 + 2 * 3; + comparison_challenge_request.start_blockheight_clientchain = challenge.request.start_blockheight_clientchain; + comparison_challenge_request.end_blockheight_clientchain = + challenge.request.start_blockheight_clientchain + 2 * num_service_chain_blocks; // start_height + (2 times client chain blocks as service chain blocks in same + // time period * number of service chain block) assert_eq!(challenge.request, comparison_challenge_request); assert_eq!( storage.get_request(challenge.request.txid).unwrap().unwrap(), @@ -356,7 +354,7 @@ mod tests { let old_challenge = challenge.clone(); // save old challenge state challenge.request.fee_percentage = 25; // alter random field let new_challenge = challenge.clone(); // save new challenge state - let _ = update_challenge_request_state(&config, &clientchain, storage.clone(), &mut challenge); + let _ = update_challenge_request_state(&clientchain, storage.clone(), &mut challenge, 2, 1); assert_eq!(challenge.request, old_challenge.request); assert_eq!( storage.get_request(challenge.request.txid).unwrap().unwrap(), diff --git a/src/coordinator.rs b/src/coordinator.rs index ca471c8..eb00ff8 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -56,7 +56,13 @@ pub fn run_request( // First attempt to store the challenge state information // on requests and winning bids and exit if it fails. // If already set update challenge state with correct version from storage - ::challenger::update_challenge_request_state(config, clientchain, storage.clone(), &mut challenge)?; + ::challenger::update_challenge_request_state( + clientchain, + storage.clone(), + &mut challenge, + config.block_time, + config.clientchain.block_time, + )?; // create a challenge state mutex to share between challenger and listener let shared_challenge = Arc::new(Mutex::new(challenge)); From 7122b165bde2ac3058a558b57812b1c679bee1f1 Mon Sep 17 00:00:00 2001 From: tomossomot Date: Thu, 14 Nov 2019 11:33:01 +0000 Subject: [PATCH 21/40] fix test --- src/challenger.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/challenger.rs b/src/challenger.rs index a9eb59f..79a956b 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -321,10 +321,10 @@ mod tests { // Test challenge state request set and stored correctly let _ = clientchain.height.replace(1); + let mut comparison_challenge_request = challenge.request.clone(); // Clone request for comparison let _ = update_challenge_request_state(&clientchain, storage.clone(), &mut challenge, 1, 1); // All fields stay the same but start and end blockheight_clientchain - let mut comparison_challenge_request = challenge.request.clone(); - comparison_challenge_request.start_blockheight_clientchain = challenge.request.start_blockheight_clientchain; + comparison_challenge_request.start_blockheight_clientchain = *clientchain.height.borrow(); comparison_challenge_request.end_blockheight_clientchain = challenge.request.start_blockheight_clientchain + num_service_chain_blocks; // start_height + number of servcie chain blocks assert_eq!(challenge.request, comparison_challenge_request); @@ -337,9 +337,10 @@ mod tests { // for client chain block time half of service chain block time let storage = Arc::new(MockStorage::new()); //reset storage let _ = clientchain.height.replace(1); + let mut comparison_challenge_request = challenge.request.clone(); // Clone request for comparison let _ = update_challenge_request_state(&clientchain, storage.clone(), &mut challenge, 2, 1); - let mut comparison_challenge_request = challenge.request.clone(); - comparison_challenge_request.start_blockheight_clientchain = challenge.request.start_blockheight_clientchain; + // All fields stay the same but start and end blockheight_clientchain + comparison_challenge_request.start_blockheight_clientchain = *clientchain.height.borrow(); comparison_challenge_request.end_blockheight_clientchain = challenge.request.start_blockheight_clientchain + 2 * num_service_chain_blocks; // start_height + (2 times client chain blocks as service chain blocks in same // time period * number of service chain block) From c85099e70a7870b82a528c578e0075994cb38291 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Fri, 15 Nov 2019 16:19:12 +0000 Subject: [PATCH 22/40] Update bitcoin and rust/bitcoin related libraries --- Cargo.lock | 198 +++++++++++++--------------------- Cargo.toml | 4 +- examples/demo.rs | 8 +- examples/hyperclient.rs | 8 +- examples/rpc.rs | 4 +- src/api.rs | 4 +- src/challenger.rs | 2 +- src/coordinator.rs | 2 +- src/error.rs | 15 ++- src/interfaces/clientchain.rs | 23 ++-- src/interfaces/request.rs | 8 +- src/interfaces/response.rs | 2 +- src/interfaces/service.rs | 2 +- src/interfaces/storage.rs | 2 +- src/lib.rs | 2 - src/listener.rs | 12 +-- src/util/doc_format.rs | 4 +- src/util/ocean.rs | 10 +- src/util/testing.rs | 4 +- 19 files changed, 134 insertions(+), 180 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 418f9b7..6525e8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,71 +54,38 @@ dependencies = [ [[package]] name = "bech32" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bech32" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitcoin" -version = "0.17.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitcoin-bech32 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin_hashes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitcoin_hashes 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", - "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "strason 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitcoin" -version = "0.18.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitcoin-bech32 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin_hashes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitcoin_hashes 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", - "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_test 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitcoin-amount" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitcoin-bech32" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bech32 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitcoin-bech32" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitcoin_hashes" -version = "0.3.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -193,7 +160,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.26" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -208,7 +175,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -245,8 +212,7 @@ name = "coordinator" version = "0.3.9" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin_hashes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", "config 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", @@ -254,9 +220,8 @@ dependencies = [ "jsonrpc-http-server 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mongodb 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", - "ocean-rpc 0.3.0 (git+https://github.com/commerceblock/rust-ocean-rpc)", - "rust-ocean 0.6.0 (git+https://github.com/commerceblock/rust-ocean)", - "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ocean-rpc 0.8.0 (git+https://github.com/commerceblock/rust-ocean-rpc)", + "rust-ocean 0.10.0 (git+https://github.com/commerceblock/rust-ocean)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -389,7 +354,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -504,7 +469,7 @@ dependencies = [ "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -605,7 +570,7 @@ dependencies = [ "jsonrpc-server-utils 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -618,10 +583,10 @@ dependencies = [ "jsonrpc-core 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -825,7 +790,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -835,7 +800,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -843,12 +808,12 @@ name = "num-traits" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -856,7 +821,7 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -865,36 +830,30 @@ dependencies = [ [[package]] name = "ocean-rpc" -version = "0.3.0" -source = "git+https://github.com/commerceblock/rust-ocean-rpc#4281e8656729470be5a1b6083a0337a34bc4454e" +version = "0.8.0" +source = "git+https://github.com/commerceblock/rust-ocean-rpc#99bccc2a8daf0220f28d32ca7be1b5ba6fd9bf00" dependencies = [ - "bitcoin 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin-amount 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin_hashes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ocean-rpc-json 0.3.0 (git+https://github.com/commerceblock/rust-ocean-rpc)", - "rust-ocean 0.6.0 (git+https://github.com/commerceblock/rust-ocean)", - "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ocean-rpc-json 0.8.0 (git+https://github.com/commerceblock/rust-ocean-rpc)", + "rust-ocean 0.10.0 (git+https://github.com/commerceblock/rust-ocean)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ocean-rpc-json" -version = "0.3.0" -source = "git+https://github.com/commerceblock/rust-ocean-rpc#4281e8656729470be5a1b6083a0337a34bc4454e" +version = "0.8.0" +source = "git+https://github.com/commerceblock/rust-ocean-rpc#99bccc2a8daf0220f28d32ca7be1b5ba6fd9bf00" dependencies = [ - "bitcoin 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin-amount 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin_hashes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-ocean 0.10.0 (git+https://github.com/commerceblock/rust-ocean)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1148,13 +1107,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rust-ocean" -version = "0.6.0" -source = "git+https://github.com/commerceblock/rust-ocean#82329da46e80d367ab62b8be8b8c2573dc90c79c" +version = "0.10.0" +source = "git+https://github.com/commerceblock/rust-ocean#fdabe0afb50ea58eadcfa0b80c77f1da64182a45" dependencies = [ - "bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin_hashes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitcoin 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1190,12 +1147,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "secp256k1" -version = "0.12.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "secp256k1" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1278,14 +1243,6 @@ dependencies = [ "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "serde_test" -version = "1.0.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "sha-1" version = "0.7.0" @@ -1321,14 +1278,6 @@ dependencies = [ "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "strason" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "string" version = "0.2.1" @@ -1394,7 +1343,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1477,7 +1426,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1518,7 +1467,7 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1613,10 +1562,10 @@ dependencies = [ [[package]] name = "unicase" -version = "2.5.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1660,6 +1609,11 @@ name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "want" version = "0.2.0" @@ -1749,14 +1703,10 @@ dependencies = [ "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -"checksum bech32 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad20b907fd16610c3960c7fe9dae13dd243343409bab80299774c9a8b5d7bed8" -"checksum bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58946044516aa9dc922182e0d6e9d124a31aafe6b421614654eb27cf90cec09c" -"checksum bitcoin 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0105a5a9c83f4ac366ca45f99ba502805a097fdf426ade4af0a822853cdd0886" -"checksum bitcoin 0.18.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5e7935f613ba170459072926f01dc5ddb8aa22382dc4badf44bbb55e2d243d" -"checksum bitcoin-amount 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0bd5ae6712113fac4edfa917b1d865801f476b021a108e6749ce20d3057abb9e" -"checksum bitcoin-bech32 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f0a5cfe5abcb5040b36d4ea8acba95288fefebd7959b59475f2c4ec705974b4c" -"checksum bitcoin-bech32 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e67e8ccfc663811145e6cabdb9a2a6978877f72b048516e83eb95622e9b2554" -"checksum bitcoin_hashes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b7a2e9773ee7ae7f2560f0426c938f57902dcb9e39321b0cbd608f47ed579a4" +"checksum bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0089c35ab7c6f2bc55ab23f769913f0ac65b1023e7e74638a1f43128dd5df2" +"checksum bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd1353f2950c2ca1b67032a8984ef6cf4a732dd757cbb32b6dcc2825a9e56a3" +"checksum bitcoin 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "01337c65290ce0c948738d821aa9f87488ca6c2b0f02d672ef778f9ae54f22c8" +"checksum bitcoin_hashes 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "db6b697833d852acea530c9e815e6adc724267856b6506bc500362a068a39c7b" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" "checksum bson 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8984b7b33b1f8ac97468df3cefa76c7035abb0786473aa2a437dea0c72855702" @@ -1765,7 +1715,7 @@ dependencies = [ "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "389803e36973d242e7fecb092b2de44a3d35ac62524b3b9339e51d577d668e02" +"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -1835,10 +1785,10 @@ dependencies = [ "checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155394f924cdddf08149da25bfb932d226b4a593ca7468b08191ff6335941af5" -"checksum ocean-rpc 0.3.0 (git+https://github.com/commerceblock/rust-ocean-rpc)" = "" -"checksum ocean-rpc-json 0.3.0 (git+https://github.com/commerceblock/rust-ocean-rpc)" = "" +"checksum num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "443c53b3c3531dfcbfa499d8893944db78474ad7a1d87fa2d94d1a2231693ac6" +"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" +"checksum ocean-rpc 0.8.0 (git+https://github.com/commerceblock/rust-ocean-rpc)" = "" +"checksum ocean-rpc-json 0.8.0 (git+https://github.com/commerceblock/rust-ocean-rpc)" = "" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum pbkdf2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0c09cddfbfc98de7f76931acf44460972edb4023eb14d0c6d4018800e552d8e0" @@ -1866,13 +1816,14 @@ dependencies = [ "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" -"checksum rust-ocean 0.6.0 (git+https://github.com/commerceblock/rust-ocean)" = "" +"checksum rust-ocean 0.10.0 (git+https://github.com/commerceblock/rust-ocean)" = "" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum scan_fmt 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b87497427f9fbe539ee6b9626f5a5e899331fdf1c1d62f14c637a462969db30" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaccd3a23619349e0878d9a241f34b1982343cdf67367058cd7d078d326b63e" +"checksum secp256k1 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4070f3906e65249228094cf97b04a90799fba04468190bbbcfa812309cf86e32" +"checksum secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4d311229f403d64002e9eed9964dfa5a0a0c1ac443344f7546bf48e916c6053a" "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" @@ -1883,12 +1834,10 @@ dependencies = [ "checksum serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "ca13fc1a832f793322228923fbb3aba9f3f44444898f835d31ad1b74fa0a2bf8" "checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum serde_test 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5" -"checksum serde_test 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "00d9d9443b1a25de2526ad21a2efc89267df5387c36035fe3902fbda8a79d83c" "checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded" "checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -"checksum strason 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dcd1098ae32c583b8d538072380c340a01e46fbca379d6248ff77721373e2cef" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" @@ -1917,13 +1866,14 @@ dependencies = [ "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" +"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" diff --git a/Cargo.toml b/Cargo.toml index ed53ece..a14b019 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,4 @@ mongodb = "0.3.11" jsonrpc-http-server = "11.0" rust-ocean = { git = "https://github.com/commerceblock/rust-ocean"} ocean-rpc = { git = "https://github.com/commerceblock/rust-ocean-rpc"} -bitcoin = { version = "0.17", features = [ "serde-decimal" ] } -bitcoin_hashes = "0.3" -secp256k1 = "0.12.2" +bitcoin = { version = "0.19.1", features = [ "use-serde" ] } diff --git a/examples/demo.rs b/examples/demo.rs index 11c066f..e7faff8 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -8,24 +8,22 @@ #[macro_use] extern crate log; extern crate bitcoin; -extern crate bitcoin_hashes; extern crate coordinator; extern crate env_logger; extern crate hyper; extern crate ocean_rpc; -extern crate secp256k1; use std::sync::Arc; use std::{env, thread, time}; use bitcoin::consensus::encode::serialize; -use bitcoin_hashes::{hex::FromHex, hex::ToHex, sha256d}; +use bitcoin::hashes::{hex::FromHex, hex::ToHex, sha256d}; +use bitcoin::secp256k1::{Message, Secp256k1, SecretKey}; use hyper::{ rt::{self, Future, Stream}, Body, Client, Method, Request, }; use ocean_rpc::RpcApi; -use secp256k1::{Message, Secp256k1, SecretKey}; use coordinator::coordinator as coordinator_main; use coordinator::interfaces::clientchain::get_first_unspent; @@ -58,7 +56,7 @@ fn main() { let client_rpc_clone = client_rpc.clone(); thread::spawn(move || loop { thread::sleep(time::Duration::from_secs(10)); - if let Err(e) = client_rpc_clone.clone().client.generate(1) { + if let Err(e) = client_rpc_clone.clone().client.generate(1, None) { error!("{}", e); } }); diff --git a/examples/hyperclient.rs b/examples/hyperclient.rs index ff1cf02..48e6340 100644 --- a/examples/hyperclient.rs +++ b/examples/hyperclient.rs @@ -1,19 +1,17 @@ //! Mock Example of client sending a POST request to server extern crate bitcoin; -extern crate bitcoin_hashes; extern crate hyper; -extern crate secp256k1; use bitcoin::consensus::encode::serialize; -use bitcoin_hashes::hex::{FromHex, ToHex}; -use bitcoin_hashes::sha256d; +use bitcoin::hashes::hex::{FromHex, ToHex}; +use bitcoin::hashes::sha256d; +use bitcoin::secp256k1::{Message, Secp256k1, SecretKey}; use hyper::{ header::HeaderValue, rt::{self, Future, Stream}, Body, Client, Method, Request, }; -use secp256k1::{Message, Secp256k1, SecretKey}; fn main() { let client = Client::new(); diff --git a/examples/rpc.rs b/examples/rpc.rs index 1720d70..5a689aa 100644 --- a/examples/rpc.rs +++ b/examples/rpc.rs @@ -3,7 +3,7 @@ extern crate ocean_rpc; extern crate rust_ocean; -use ocean_rpc::{Client, Error, RpcApi}; +use ocean_rpc::{Auth, Client, Error, RpcApi}; fn main_result() -> Result<(), Error> { let mut args = std::env::args(); @@ -14,7 +14,7 @@ fn main_result() -> Result<(), Error> { let user = args.next(); let pass = args.next(); - let rpc = Client::new(url, user, pass); + let rpc = Client::new(url, Auth::UserPass(user.unwrap(), pass.unwrap())).unwrap(); let blockchain_info = rpc.get_blockchain_info()?; println!("info\n{:?}", blockchain_info); diff --git a/src/api.rs b/src/api.rs index 6535635..6a5204e 100644 --- a/src/api.rs +++ b/src/api.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use std::thread; use base64::decode; -use bitcoin_hashes::sha256d; +use bitcoin::hashes::sha256d; use hyper::{Body, Request, StatusCode}; use jsonrpc_http_server::jsonrpc_core::{Error, ErrorCode, IoHandler, Params, Value}; use jsonrpc_http_server::{hyper::header, AccessControlAllowOrigin, DomainsValidation, Response, ServerBuilder}; @@ -269,7 +269,7 @@ mod tests { let params: Params = serde_json::from_str(&s).unwrap(); let resp = get_request_response(params, storage.clone()); assert_eq!( - "Invalid params: bad hex string length 65 (expected 64).", + "Invalid params: odd hex string length 65.", resp.wait().unwrap_err().message ); diff --git a/src/challenger.rs b/src/challenger.rs index 79a956b..2f1ae9a 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -8,7 +8,7 @@ use std::sync::mpsc::{Receiver, RecvTimeoutError}; use std::sync::{Arc, Mutex}; use std::{thread, time}; -use bitcoin_hashes::sha256d; +use bitcoin::hashes::sha256d; use crate::error::{CError, Error, Result}; use crate::interfaces::clientchain::ClientChain; diff --git a/src/coordinator.rs b/src/coordinator.rs index eb00ff8..98404e7 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -6,7 +6,7 @@ use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::{Arc, Mutex}; use std::{thread, time}; -use bitcoin_hashes::{hex::FromHex, sha256d}; +use bitcoin::hashes::{hex::FromHex, sha256d}; use futures::sync::oneshot; use crate::challenger::ChallengeResponse; diff --git a/src/error.rs b/src/error.rs index dd25fa8..cc827fc 100644 --- a/src/error.rs +++ b/src/error.rs @@ -6,11 +6,12 @@ use std::error; use std::fmt; use std::result; -use bitcoin_hashes::Error as HashesError; +use bitcoin::hashes::hex::Error as HashesHexError; +use bitcoin::hashes::Error as HashesError; +use bitcoin::secp256k1::Error as Secp256k1Error; use config_rs::ConfigError; use mongodb::Error as MongoDbError; use ocean_rpc::Error as OceanRpcError; -use secp256k1::Error as Secp256k1Error; /// Crate specific Result for crate specific Errors pub type Result = result::Result; @@ -99,6 +100,8 @@ pub enum Error { OceanRpc(OceanRpcError), /// Bitcoin hashes error BitcoinHashes(HashesError), + /// Bitcoin hex hashes error + BitcoinHashesHex(HashesHexError), /// Secp256k1 error Secp256k1(Secp256k1Error), /// Mongodb error @@ -127,6 +130,12 @@ impl From for Error { } } +impl From for Error { + fn from(e: HashesHexError) -> Error { + Error::BitcoinHashesHex(e) + } +} + impl From for Error { fn from(e: Secp256k1Error) -> Error { Error::Secp256k1(e) @@ -150,6 +159,7 @@ impl fmt::Display for Error { match *self { Error::OceanRpc(ref e) => write!(f, "ocean rpc error: {}", e), Error::BitcoinHashes(ref e) => write!(f, "bitcoin hashes error: {}", e), + Error::BitcoinHashesHex(ref e) => write!(f, "bitcoin hashes hex error: {}", e), Error::Secp256k1(ref e) => write!(f, "secp256k1 error: {}", e), Error::MongoDb(ref e) => write!(f, "mongodb error: {}", e), Error::Config(ref e) => write!(f, "config error: {}", e), @@ -163,6 +173,7 @@ impl error::Error for Error { match *self { Error::OceanRpc(ref e) => Some(e), Error::BitcoinHashes(ref e) => Some(e), + Error::BitcoinHashesHex(ref e) => Some(e), Error::Secp256k1(ref e) => Some(e), Error::MongoDb(ref e) => Some(e), Error::Config(ref e) => Some(e), diff --git a/src/interfaces/clientchain.rs b/src/interfaces/clientchain.rs index 72e1a47..9bfb93a 100644 --- a/src/interfaces/clientchain.rs +++ b/src/interfaces/clientchain.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; -use bitcoin_hashes::{hex::FromHex, sha256d}; +use bitcoin::hashes::{hex::FromHex, sha256d}; use ocean_rpc::{json, RpcApi}; use crate::config::ClientChainConfig; @@ -13,7 +13,7 @@ use crate::util::ocean::OceanClient; /// Method that returns the first unspent output for given asset /// or an error if the client wallet does not have any unspent/funds -pub fn get_first_unspent(client: &OceanClient, asset: &str) -> Result { +pub fn get_first_unspent(client: &OceanClient, asset: &str) -> Result { // Check asset is held by the wallet and return unspent tx let unspent = client.list_unspent(None, None, None, None, Some(asset))?; if unspent.is_empty() { @@ -87,26 +87,21 @@ impl<'a> ClientChain for RpcClientChain<'a> { }]; let mut outs = HashMap::new(); - let _ = outs.insert( - unspent.address.clone(), - (unspent.amount.into_inner() / 100000000) as f64, - ); + let _ = outs.insert(unspent.address.to_string(), unspent.amount); let mut outs_assets = HashMap::new(); - let _ = outs_assets.insert(unspent.address.clone(), unspent.asset.to_string()); + let _ = outs_assets.insert(unspent.address.to_string(), unspent.asset); let tx_hex = self .client - .create_raw_transaction_hex(&utxos, Some(&outs), Some(&outs_assets), None)?; + .create_raw_transaction_hex(&utxos, &outs, Some(&outs_assets), None)?; // sign the transaction and send via the client rpc - let tx_signed = - self.client - .sign_raw_transaction((&Vec::::from_hex(&tx_hex)? as &[u8]).into(), None, None, None)?; + let tx_signed = self + .client + .sign_raw_transaction(&Vec::::from_hex(&tx_hex)? as &[u8], None, None, None)?; - Ok(sha256d::Hash::from_hex( - &self.client.send_raw_transaction(&tx_signed.hex)?, - )?) + Ok(self.client.send_raw_transaction(&tx_signed.hex)?) } /// Verify challenge transaction has been included in the chain diff --git a/src/interfaces/request.rs b/src/interfaces/request.rs index a790878..6b006a6 100644 --- a/src/interfaces/request.rs +++ b/src/interfaces/request.rs @@ -4,9 +4,9 @@ use std::collections::HashSet; -use bitcoin_hashes::sha256d; +use bitcoin::hashes::sha256d; +use bitcoin::secp256k1::PublicKey; use ocean_rpc::json::{GetRequestBidsResultBid, GetRequestsResult}; -use secp256k1::key::PublicKey; use serde::{Serialize, Serializer}; /// Request struct storing info on client request and modelling data that need @@ -62,7 +62,7 @@ impl Bid { pub fn from_json(res: &GetRequestBidsResultBid) -> Self { Bid { txid: res.txid, - pubkey: res.fee_pub_key, + pubkey: res.fee_pub_key.key, } } } @@ -85,7 +85,7 @@ mod tests { use std::str::FromStr; - use bitcoin_hashes::hex::FromHex; + use bitcoin::hashes::hex::FromHex; #[test] fn serialize_pubkey_test() { diff --git a/src/interfaces/response.rs b/src/interfaces/response.rs index 2fd0bc3..f031694 100644 --- a/src/interfaces/response.rs +++ b/src/interfaces/response.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use crate::challenger::ChallengeResponseIds; -use bitcoin_hashes::sha256d; +use bitcoin::hashes::sha256d; use serde::Serialize; /// Response struct that models responses to service challenges diff --git a/src/interfaces/service.rs b/src/interfaces/service.rs index 2428143..a044548 100644 --- a/src/interfaces/service.rs +++ b/src/interfaces/service.rs @@ -2,7 +2,7 @@ //! //! Service chain interface and implementations -use bitcoin_hashes::sha256d; +use bitcoin::hashes::sha256d; use ocean_rpc::RpcApi; use crate::config::ServiceConfig; diff --git a/src/interfaces/storage.rs b/src/interfaces/storage.rs index a95ce80..d332af3 100644 --- a/src/interfaces/storage.rs +++ b/src/interfaces/storage.rs @@ -5,7 +5,7 @@ use std::mem::drop; use std::sync::{Mutex, MutexGuard}; -use bitcoin_hashes::sha256d; +use bitcoin::hashes::sha256d; use mongodb::db::{Database, ThreadedDatabase}; use mongodb::{coll::options::FindOptions, Client, ThreadedClient}; use util::doc_format::*; diff --git a/src/lib.rs b/src/lib.rs index 8e8a3df..8ef066f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,13 +20,11 @@ extern crate log; extern crate base64; extern crate bitcoin; -extern crate bitcoin_hashes; extern crate config as config_rs; extern crate futures; extern crate hyper; extern crate ocean_rpc; extern crate rust_ocean as _ocean; -extern crate secp256k1; extern crate serde as serde; extern crate serde_json; #[macro_use] diff --git a/src/listener.rs b/src/listener.rs index e3ae231..4d86f25 100644 --- a/src/listener.rs +++ b/src/listener.rs @@ -9,13 +9,13 @@ use std::sync::{Arc, Mutex}; use std::thread; use bitcoin::consensus::serialize; -use bitcoin_hashes::{hex::FromHex, sha256d}; +use bitcoin::hashes::{hex::FromHex, sha256d}; +use bitcoin::secp256k1::{Message, PublicKey, Secp256k1, Signature}; use futures::future; use futures::sync::oneshot; use hyper::rt::{self, Future, Stream}; use hyper::service::service_fn; use hyper::{Body, Method, Request, Response, Server, StatusCode}; -use secp256k1::{Message, PublicKey, Secp256k1, Signature}; use serde_json::{self, Value}; use crate::challenger::{ChallengeResponse, ChallengeState}; @@ -177,8 +177,8 @@ mod tests { use std::sync::mpsc::{channel, Receiver, TryRecvError}; - use bitcoin_hashes::hex::ToHex; - use secp256k1::SecretKey; + use bitcoin::hashes::hex::ToHex; + use bitcoin::secp256k1::SecretKey; use crate::util::testing::{gen_challenge_state_with_challenge, gen_dummy_hash}; @@ -204,7 +204,7 @@ mod tests { "sig": "304402201742daea5ec3b7306b9164be862fc1659cc830032180b8b17beffe02645860d602201039eba402d22e630308e6af05da8dd4f05b51b7d672ca5fc9e3b0a57776365c" }"#; let proof = ChallengeProof::from_json(serde_json::from_str::(data).unwrap()); - assert!(proof.err().unwrap().to_string().contains("bitcoin hashes error")); + assert!(proof.err().unwrap().to_string().contains("bitcoin hashes hex error")); // bad pubkey let data = r#" @@ -226,7 +226,7 @@ mod tests { "sig": "304402201742daea5ec3b7306b9164be862fc1659cc830032180b8b17beffe02645860d602201039eba402d22e630308e6af05da8dd4f05b51b7d672ca5fc9e3b0a57776365c" }"#; let proof = ChallengeProof::from_json(serde_json::from_str::(data).unwrap()); - assert!(proof.err().unwrap().to_string().contains("bitcoin hashes error")); + assert!(proof.err().unwrap().to_string().contains("bitcoin hashes hex error")); // bad sig let data = r#" diff --git a/src/util/doc_format.rs b/src/util/doc_format.rs index ea4f718..da45408 100644 --- a/src/util/doc_format.rs +++ b/src/util/doc_format.rs @@ -6,9 +6,9 @@ use std::collections::HashMap; use std::str::FromStr; -use bitcoin_hashes::{hex::FromHex, sha256d}; +use bitcoin::hashes::{hex::FromHex, sha256d}; +use bitcoin::secp256k1::PublicKey; use mongodb::{ordered::OrderedDocument, Bson}; -use secp256k1::key::PublicKey; use crate::interfaces::request::{Bid, Request}; use crate::interfaces::response::Response; diff --git a/src/util/ocean.rs b/src/util/ocean.rs index 4576471..c9d38aa 100644 --- a/src/util/ocean.rs +++ b/src/util/ocean.rs @@ -2,7 +2,7 @@ //! //! Ocean node communication implementations -use ocean_rpc::{Client, RpcApi}; +use ocean_rpc::{Auth, Client, RpcApi}; use crate::error::Result; @@ -15,8 +15,14 @@ pub struct OceanClient { impl OceanClient { /// Create an OceanClient with underlying rpc client connectivity pub fn new(url: String, user: Option, pass: Option) -> Result { + let mut auth = Auth::None; + if let Some(ref _user) = user { + if let Some(ref _pass) = pass { + auth = Auth::UserPass(_user.clone(), _pass.clone()); + } + } Ok(OceanClient { - client: Client::new(format!("http://{}", url), user, pass), + client: Client::new(format!("http://{}", url), auth)?, }) } } diff --git a/src/util/testing.rs b/src/util/testing.rs index 06db7ac..4887cd2 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -2,10 +2,10 @@ //! //! Colleciton of helper functions used in tests module -use bitcoin_hashes::{hex::FromHex, sha256d, Hash}; +use bitcoin::hashes::{hex::FromHex, sha256d, Hash}; +use bitcoin::secp256k1::PublicKey; use mongodb::ordered::OrderedDocument; use mongodb::Bson; -use secp256k1::PublicKey; use std::cell::RefCell; use std::str::FromStr; use util::doc_format::*; From 96f16ebac6908c0ce28ad9bb39f6fd3c28d509e4 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Fri, 15 Nov 2019 16:31:35 +0000 Subject: [PATCH 23/40] Mock payments functionality --- src/coordinator.rs | 3 ++ src/lib.rs | 1 + src/payments.rs | 96 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 src/payments.rs diff --git a/src/coordinator.rs b/src/coordinator.rs index 98404e7..8e26731 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -26,12 +26,15 @@ pub fn run(config: Config) -> Result<()> { let genesis_hash = sha256d::Hash::from_hex(&config.clientchain.genesis_hash)?; let _ = ::api::run_api_server(&config.api, storage.clone()); + let (req_send, req_recv): (Sender, Receiver) = channel(); + let _ = ::payments::run_payments(&config.clientchain, storage.clone(), req_recv); // This loop runs continuously fetching and running challenge requests, // generating challenge responses and fails on any errors that occur loop { if let Some(request_id) = run_request(&config, &service, &clientchain, storage.clone(), genesis_hash)? { // if challenge request succeeds print responses + req_send.send(request_id).unwrap(); info! {"***** Response *****"} let resp = storage.get_response(request_id)?.unwrap(); info! {"{}", serde_json::to_string_pretty(&resp).unwrap()}; diff --git a/src/lib.rs b/src/lib.rs index 8ef066f..85fb15e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,6 +37,7 @@ pub mod config; pub mod coordinator; pub mod error; pub mod listener; +pub mod payments; pub mod interfaces; pub mod util; diff --git a/src/payments.rs b/src/payments.rs new file mode 100644 index 0000000..ced7e73 --- /dev/null +++ b/src/payments.rs @@ -0,0 +1,96 @@ +//! Payments +//! +//! TODO: Add description + +use std::sync::mpsc::{Receiver, RecvError}; +use std::sync::Arc; +use std::thread; + +use bitcoin::hashes::sha256d; +use bitcoin::Amount; +use ocean_rpc::RpcApi; + +use crate::config::ClientChainConfig; +use crate::error::{CError, Error, Result}; +use crate::interfaces::{request::Request, storage::Storage}; +use crate::util::ocean::OceanClient; + +/// +fn calculate_fees(request: &Request, client: &OceanClient) -> Result { + let mut fee_sum = Amount::ZERO; + for i in request.start_blockheight_clientchain..request.end_blockheight_clientchain { + let block = client.get_block_info(&client.get_block_hash(i.into())?)?; + let tx = client.get_raw_transaction_verbose(&block.tx[0], None)?; + for txout in tx.vout { + // do label check :) + fee_sum += txout.value; + } + } + Ok(fee_sum) +} + +/// +fn do_request_payment(request: &Request, client: &OceanClient, storage: &Arc) -> Result<()> { + let bids = storage.get_bids(request.txid)?; + let resp = storage.get_response(request.txid)?; + + Ok(()) + + // calculate_fees() + // for bids: + // lookup in resps + // get address + // pay + // store + // update Bid + // update Request +} + +/// +fn do_request_payments( + client: OceanClient, + storage: Arc, + req_recv: Receiver, +) -> Result<()> { + // get payment mode from config + + // get addr prefix from config + + // First pay out any past requests that have not been fully paid yet + let incomplete_requests = storage.get_requests()?; //paid = False) + for req in incomplete_requests { + let _ = do_request_payment(&req, &client, &storage)?; + } + + // Wait for new requests + loop { + match req_recv.recv() { + Ok(resp) => { + let req = storage.get_request(resp)?.unwrap(); + let _ = do_request_payment(&req, &client, &storage)?; + } + Err(RecvError) => { + return Err(Error::from(CError::ReceiverDisconnected)); + } + } + } +} + +/// +pub fn run_payments( + clientchain_config: &ClientChainConfig, + storage: Arc, + req_recv: Receiver, +) -> Result> { + let client = OceanClient::new( + clientchain_config.host.clone(), + Some(clientchain_config.user.clone()), + Some(clientchain_config.pass.clone()), + )?; + + Ok(thread::spawn(move || { + if let Err(err) = do_request_payments(client, storage.clone(), req_recv) { + error! {"payments error: {}", err} + } + })) +} From e392bc61f4dc28d656fd992ec3920783ef95fec6 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Mon, 18 Nov 2019 10:08:57 +0000 Subject: [PATCH 24/40] Update demo and cargo --- Cargo.lock | 4 ++-- examples/demo.rs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6525e8f..b571f70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -831,7 +831,7 @@ dependencies = [ [[package]] name = "ocean-rpc" version = "0.8.0" -source = "git+https://github.com/commerceblock/rust-ocean-rpc#99bccc2a8daf0220f28d32ca7be1b5ba6fd9bf00" +source = "git+https://github.com/commerceblock/rust-ocean-rpc#f20a236d1f310bfc0869bec08bc901451e196e7c" dependencies = [ "bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -847,7 +847,7 @@ dependencies = [ [[package]] name = "ocean-rpc-json" version = "0.8.0" -source = "git+https://github.com/commerceblock/rust-ocean-rpc#99bccc2a8daf0220f28d32ca7be1b5ba6fd9bf00" +source = "git+https://github.com/commerceblock/rust-ocean-rpc#f20a236d1f310bfc0869bec08bc901451e196e7c" dependencies = [ "bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/examples/demo.rs b/examples/demo.rs index e7faff8..6997b5b 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -38,6 +38,7 @@ fn main() { config.challenge_duration = 5; config.challenge_frequency = 2; config.block_time = 10; + config.clientchain.block_time = 10; env::set_var("RUST_LOG", "coordinator,demo"); env::set_var("RUST_BACKTRACE", "1"); @@ -56,7 +57,7 @@ fn main() { let client_rpc_clone = client_rpc.clone(); thread::spawn(move || loop { thread::sleep(time::Duration::from_secs(10)); - if let Err(e) = client_rpc_clone.clone().client.generate(1, None) { + if let Err(e) = client_rpc_clone.clone().client.generate(1) { error!("{}", e); } }); From 0b45352eaf40b2f079a09355383d0cc5c21eea4a Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Mon, 18 Nov 2019 11:53:55 +0000 Subject: [PATCH 25/40] Update rust-ocean-rpc for tx/block updates --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b571f70..b12464b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -831,7 +831,7 @@ dependencies = [ [[package]] name = "ocean-rpc" version = "0.8.0" -source = "git+https://github.com/commerceblock/rust-ocean-rpc#f20a236d1f310bfc0869bec08bc901451e196e7c" +source = "git+https://github.com/commerceblock/rust-ocean-rpc#2b7f5a9a3a9a6d360dcdacb1ea4ea0c9db7bd6bc" dependencies = [ "bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -847,7 +847,7 @@ dependencies = [ [[package]] name = "ocean-rpc-json" version = "0.8.0" -source = "git+https://github.com/commerceblock/rust-ocean-rpc#f20a236d1f310bfc0869bec08bc901451e196e7c" +source = "git+https://github.com/commerceblock/rust-ocean-rpc#2b7f5a9a3a9a6d360dcdacb1ea4ea0c9db7bd6bc" dependencies = [ "bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", From b5b1373f527f8ba134aaafb40507dd1746101873 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Mon, 18 Nov 2019 15:10:07 +0000 Subject: [PATCH 26/40] Add config required for fee payments --- config/default.toml | 2 ++ docker-compose.yml | 2 ++ examples/demo.rs | 1 - src/bin/main.rs | 30 ++++++++++++++--------- src/config.rs | 60 ++++++++++++++++++++++++++++++++++----------- src/error.rs | 13 +++++----- src/lib.rs | 2 +- src/util/checks.rs | 2 ++ 8 files changed, 77 insertions(+), 35 deletions(-) diff --git a/config/default.toml b/config/default.toml index 4ef0cae..cff639f 100644 --- a/config/default.toml +++ b/config/default.toml @@ -31,6 +31,8 @@ genesis_hash = "ff8950160a77988cdc485913568d06c2d69a8c952ef0f179b4b097e3de63d7cc block_time = 60 asset = "CHALLENGE" asset_key = "cScSHCQp9AEwzZoucRpX9bMRkLCJ4LoQWBNFTZuD6tPX9qwNMWfQ" +chain = "ocean_test" +payment_asset = "CBT" [storage] host = "localhost:27017" diff --git a/docker-compose.yml b/docker-compose.yml index 8a0886c..9fa705c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -46,6 +46,8 @@ services: CO_CLIENTCHAIN_PASS: password1 CO_CLIENTCHAIN_GENESIS_HASH: d1fbd07bd9a7a80a85445b8e28246f0b644c01ac7412e81ce3ffc0815386ad77 CO_CLIENTCHAIN_ASSET_KEY: cScSHCQp9AEwzZoucRpX9bMRkLCJ4LoQWBNFTZuD6tPX9qwNMWfQ + CO_CLIENTCHAIN_CHAIN: ocean_test + CO_CLIENTCHAIN_PAYMENT_ASSET: CBT # cb service chain node connectivity CO_SERVICE_HOST: service_chain:5555 diff --git a/examples/demo.rs b/examples/demo.rs index 6997b5b..fca821f 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -73,7 +73,6 @@ fn main() { for bid in client_rpc.get_request_bids(&request_txid).unwrap().unwrap().bids { if bid.fee_pub_key.to_string() == guardnode_pubkey { guardnode_txid = bid.txid; - println!("Guardnode bid txid: {}", guardnode_txid); break; } } diff --git a/src/bin/main.rs b/src/bin/main.rs index 3bc2708..f760e7d 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -13,17 +13,23 @@ use std::process; fn main() { // Fetch config which is set from default values in config // and any values overriden by the corresponding env variable - let config = coordinator::config::Config::new().unwrap(); - - // To see results set RUST_LOG to one of the following: - // info, warning, debug, error, coordinator(for all) - env::set_var("RUST_LOG", &config.log_level); - env::set_var("RUST_BACKTRACE", "1"); - // Init env logger with value set from config - env_logger::init(); - - if let Err(e) = coordinator::coordinator::run(config) { - error!("daemon failure: {}", e); - process::exit(1); + match coordinator::config::Config::new() { + Ok(config) => { + // To see results set RUST_LOG to one of the following: + // info, warning, debug, error, coordinator(for all) + env::set_var("RUST_LOG", &config.log_level); + env::set_var("RUST_BACKTRACE", "1"); + // Init env logger with value set from config + env_logger::init(); + if let Err(e) = coordinator::coordinator::run(config) { + error!("daemon failure: {}", e); + } + } + Err(e) => { + env::set_var("RUST_LOG", "error"); + env_logger::init(); + error!("config failure: {}", e); + } } + process::exit(1); } diff --git a/src/config.rs b/src/config.rs index 65c3a8b..10918f8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,13 +2,14 @@ //! //! Config module handling config options from file/env +use std::env; + use config_rs::{Config as ConfigRs, Environment, File}; -use error::InputErrorType::{GenHash, PrivKey}; use serde::{Deserialize, Serialize}; -use std::env; -use util::checks::{check_hash_string, check_privkey_string}; +use crate::error::InputErrorType::{GenHash, MissingArgument, PrivKey}; use crate::error::{CError, Error, Result}; +use crate::util::checks::{check_hash_string, check_privkey_string}; #[derive(Debug, Serialize, Deserialize)] /// Api specific config @@ -69,6 +70,12 @@ pub struct ClientChainConfig { pub asset: String, /// Client asset key pub asset_key: String, + /// Client chain name + pub chain: String, + /// Payment asset label or asset id or ANY asset to be used for payments + pub payment_asset: String, + /// Payment key; optional as the coordinator might not be doing payments + pub payment_key: Option, } impl Default for ClientChainConfig { @@ -81,6 +88,9 @@ impl Default for ClientChainConfig { block_time: CONFIG_BLOCK_TIME_DEFAULT, asset: String::from("CHALLENGE"), asset_key: String::new(), + chain: String::new(), + payment_asset: String::new(), + payment_key: None, } } } @@ -221,6 +231,15 @@ impl Config { if let Ok(v) = env::var("CO_CLIENTCHAIN_BLOCK_TIME") { let _ = conf_rs.set("clientchain.block_time", v)?; } + if let Ok(v) = env::var("CO_CLIENTCHAIN_CHAIN") { + let _ = conf_rs.set("clientchain.chain", v)?; + } + if let Ok(v) = env::var("CO_CLIENTCHAIN_PAYMENT_ASSET") { + let _ = conf_rs.set("clientchain.payment_asset", v)?; + } + if let Ok(v) = env::var("CO_CLIENTCHAIN_PAYMENT_KEY") { + let _ = conf_rs.set("clientchain.payment_key", v)?; + } if let Ok(v) = env::var("CO_STORAGE_HOST") { let _ = conf_rs.set("storage.host", v)?; @@ -236,18 +255,31 @@ impl Config { } // Perform type checks - if let Ok(key) = conf_rs.get_str("clientchain.asset_key") { - if !check_privkey_string(&key) { - println!("{}", CError::InputError(PrivKey, key.clone())); - return Err(Error::from(CError::InputError(PrivKey, key))); - } - } - if let Ok(hash) = conf_rs.get_str("clientchain.genesis_hash") { - if !check_hash_string(&hash) { - println!("{}", CError::InputError(GenHash, hash.clone())); - return Err(Error::from(CError::InputError(GenHash, hash))); - } + let key = conf_rs.get_str("clientchain.asset_key")?; + if !check_privkey_string(&key) { + return Err(Error::from(CError::InputError(PrivKey, key))); } + let payment_key = conf_rs.get::>("clientchain.payment_key")?; + if !payment_key.is_none() && !check_privkey_string(&payment_key.clone().unwrap()) { + return Err(Error::from(CError::InputError(PrivKey, payment_key.unwrap()))); + } + let hash = conf_rs.get_str("clientchain.genesis_hash")?; + if !check_hash_string(&hash) { + return Err(Error::from(CError::InputError(GenHash, hash))); + } + if conf_rs.get_str("clientchain.chain")?.len() == 0 { + return Err(Error::from(CError::InputError( + MissingArgument, + "clientchain.chain".into(), + ))); + } + if conf_rs.get_str("clientchain.payment_asset")?.len() == 0 { + return Err(Error::from(CError::InputError( + MissingArgument, + "clientchain.payment_asset".into(), + ))); + } + Ok(conf_rs.try_into()?) } } diff --git a/src/error.rs b/src/error.rs index cc827fc..44943fc 100644 --- a/src/error.rs +++ b/src/error.rs @@ -47,15 +47,16 @@ pub enum InputErrorType { PrivKey, /// Invalid genesis hash string GenHash, + /// Missing input argument + MissingArgument, } impl InputErrorType { fn as_str(&self) -> &'static str { match *self { - InputErrorType::PrivKey => "Invalid private key input - must be base58check string of length 52.", - InputErrorType::GenHash => { - "Invalid client chain genesis hash input - must be hexadecimal string of length 64." - } + InputErrorType::PrivKey => "Private key input - must be base58check string of length 52", + InputErrorType::GenHash => "Chain genesis hash input must be hexadecimal string of length 64", + InputErrorType::MissingArgument => "Argument missing", } } } @@ -64,9 +65,7 @@ impl fmt::Display for CError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { CError::Generic(ref e) => write!(f, "generic Error: {}", e), - CError::InputError(ref error, ref value) => { - write!(f, "Input Error: {} \nProblem value: {}", error.as_str(), value) - } + CError::InputError(ref error, ref value) => write!(f, "Input Error: {} (value: {})", error.as_str(), value), CError::MissingUnspent(ref asset, ref chain) => { write!(f, "No unspent found for {} asset on {} chain", asset, chain) } diff --git a/src/lib.rs b/src/lib.rs index 85fb15e..34c7106 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,7 @@ extern crate config as config_rs; extern crate futures; extern crate hyper; extern crate ocean_rpc; -extern crate rust_ocean as _ocean; +extern crate rust_ocean as ocean; extern crate serde as serde; extern crate serde_json; #[macro_use] diff --git a/src/util/checks.rs b/src/util/checks.rs index 8dfd270..56edeb0 100644 --- a/src/util/checks.rs +++ b/src/util/checks.rs @@ -9,6 +9,7 @@ fn is_base58_char(char: &char) -> bool { _ => false, } } + /// Check for correct priv key input string format pub fn check_privkey_string(str: &String) -> bool { if str.len() == 52 && str.chars().all(|x| is_base58_char(&x)) { @@ -16,6 +17,7 @@ pub fn check_privkey_string(str: &String) -> bool { } return false; } + /// Check for correct hash input string format pub fn check_hash_string(str: &String) -> bool { if str.len() == 64 && str.chars().all(|x| x.is_ascii_hexdigit()) { From 7ab52899ceb9d17308078b864e64bae82832b9d4 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Mon, 18 Nov 2019 16:50:30 +0000 Subject: [PATCH 27/40] Add payment addr and key import --- src/config.rs | 13 ++++++++- src/coordinator.rs | 2 +- src/error.rs | 11 ++++++++ src/payments.rs | 66 +++++++++++++++++++++++++++++++++++----------- 4 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/config.rs b/src/config.rs index 10918f8..cb4ecd6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,8 +3,10 @@ //! Config module handling config options from file/env use std::env; +use std::str::FromStr; use config_rs::{Config as ConfigRs, Environment, File}; +use ocean::Address; use serde::{Deserialize, Serialize}; use crate::error::InputErrorType::{GenHash, MissingArgument, PrivKey}; @@ -53,7 +55,7 @@ impl Default for ServiceConfig { } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] /// Clientchain specific config pub struct ClientChainConfig { /// Client rpc host @@ -76,6 +78,8 @@ pub struct ClientChainConfig { pub payment_asset: String, /// Payment key; optional as the coordinator might not be doing payments pub payment_key: Option, + /// Payment address corresponding to payment key + pub payment_addr: Option, } impl Default for ClientChainConfig { @@ -91,6 +95,7 @@ impl Default for ClientChainConfig { chain: String::new(), payment_asset: String::new(), payment_key: None, + payment_addr: None, } } } @@ -240,6 +245,9 @@ impl Config { if let Ok(v) = env::var("CO_CLIENTCHAIN_PAYMENT_KEY") { let _ = conf_rs.set("clientchain.payment_key", v)?; } + if let Ok(v) = env::var("CO_CLIENTCHAIN_PAYMENT_ADDR") { + let _ = conf_rs.set("clientchain.payment_addr", v)?; + } if let Ok(v) = env::var("CO_STORAGE_HOST") { let _ = conf_rs.set("storage.host", v)?; @@ -263,6 +271,9 @@ impl Config { if !payment_key.is_none() && !check_privkey_string(&payment_key.clone().unwrap()) { return Err(Error::from(CError::InputError(PrivKey, payment_key.unwrap()))); } + if let Some(payment_addr) = conf_rs.get::>("clientchain.payment_addr")? { + let _ = Address::from_str(&payment_addr)?; + } let hash = conf_rs.get_str("clientchain.genesis_hash")?; if !check_hash_string(&hash) { return Err(Error::from(CError::InputError(GenHash, hash))); diff --git a/src/coordinator.rs b/src/coordinator.rs index 8e26731..d818ab0 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -27,7 +27,7 @@ pub fn run(config: Config) -> Result<()> { let _ = ::api::run_api_server(&config.api, storage.clone()); let (req_send, req_recv): (Sender, Receiver) = channel(); - let _ = ::payments::run_payments(&config.clientchain, storage.clone(), req_recv); + let _ = ::payments::run_payments(config.clientchain.clone(), storage.clone(), req_recv); // This loop runs continuously fetching and running challenge requests, // generating challenge responses and fails on any errors that occur diff --git a/src/error.rs b/src/error.rs index 44943fc..b62ebe4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -11,6 +11,7 @@ use bitcoin::hashes::Error as HashesError; use bitcoin::secp256k1::Error as Secp256k1Error; use config_rs::ConfigError; use mongodb::Error as MongoDbError; +use ocean::AddressError; use ocean_rpc::Error as OceanRpcError; /// Crate specific Result for crate specific Errors @@ -101,6 +102,8 @@ pub enum Error { BitcoinHashes(HashesError), /// Bitcoin hex hashes error BitcoinHashesHex(HashesHexError), + /// Ocean address error + OceanAddress(AddressError), /// Secp256k1 error Secp256k1(Secp256k1Error), /// Mongodb error @@ -141,6 +144,12 @@ impl From for Error { } } +impl From for Error { + fn from(e: AddressError) -> Error { + Error::OceanAddress(e) + } +} + impl From for Error { fn from(e: MongoDbError) -> Error { Error::MongoDb(e) @@ -160,6 +169,7 @@ impl fmt::Display for Error { Error::BitcoinHashes(ref e) => write!(f, "bitcoin hashes error: {}", e), Error::BitcoinHashesHex(ref e) => write!(f, "bitcoin hashes hex error: {}", e), Error::Secp256k1(ref e) => write!(f, "secp256k1 error: {}", e), + Error::OceanAddress(ref e) => write!(f, "ocean address error: {}", e), Error::MongoDb(ref e) => write!(f, "mongodb error: {}", e), Error::Config(ref e) => write!(f, "config error: {}", e), Error::Coordinator(ref e) => write!(f, "coordinator error: {}", e), @@ -174,6 +184,7 @@ impl error::Error for Error { Error::BitcoinHashes(ref e) => Some(e), Error::BitcoinHashesHex(ref e) => Some(e), Error::Secp256k1(ref e) => Some(e), + Error::OceanAddress(ref e) => Some(e), Error::MongoDb(ref e) => Some(e), Error::Config(ref e) => Some(e), Error::Coordinator(_) => None, diff --git a/src/payments.rs b/src/payments.rs index ced7e73..0156747 100644 --- a/src/payments.rs +++ b/src/payments.rs @@ -2,12 +2,14 @@ //! //! TODO: Add description +use std::str::FromStr; use std::sync::mpsc::{Receiver, RecvError}; use std::sync::Arc; use std::thread; use bitcoin::hashes::sha256d; use bitcoin::Amount; +use ocean::{Address, AddressParams}; use ocean_rpc::RpcApi; use crate::config::ClientChainConfig; @@ -15,11 +17,25 @@ use crate::error::{CError, Error, Result}; use crate::interfaces::{request::Request, storage::Storage}; use crate::util::ocean::OceanClient; -/// +/// Get addr params from chain name +pub fn get_chain_addr_params(chain: &String) -> AddressParams { + match chain.to_lowercase().as_ref() { + "ocean_main" => return AddressParams::OCEAN, + "gold_main" => return AddressParams::GOLD, + _ => AddressParams::ELEMENTS, + } +} + +/// TODO: add comments fn calculate_fees(request: &Request, client: &OceanClient) -> Result { let mut fee_sum = Amount::ZERO; for i in request.start_blockheight_clientchain..request.end_blockheight_clientchain { let block = client.get_block_info(&client.get_block_hash(i.into())?)?; + // using raw rpc to get asset label + // check also coinbase destination ? + // check is coinbase + // check is correct label + // check ownership let tx = client.get_raw_transaction_verbose(&block.tx[0], None)?; for txout in tx.vout { // do label check :) @@ -29,11 +45,17 @@ fn calculate_fees(request: &Request, client: &OceanClient) -> Result { Ok(fee_sum) } -/// -fn do_request_payment(request: &Request, client: &OceanClient, storage: &Arc) -> Result<()> { +/// TODO: add comments +fn do_request_payment( + clientchain_config: &ClientChainConfig, + request: &Request, + client: &OceanClient, + storage: &Arc, +) -> Result<()> { let bids = storage.get_bids(request.txid)?; let resp = storage.get_response(request.txid)?; - + let amount = calculate_fees(request, client)?; + info!("amount: {}", amount); Ok(()) // calculate_fees() @@ -46,20 +68,18 @@ fn do_request_payment(request: &Request, client: &OceanClient, storage: &Arc, req_recv: Receiver, ) -> Result<()> { - // get payment mode from config - - // get addr prefix from config - // First pay out any past requests that have not been fully paid yet - let incomplete_requests = storage.get_requests()?; //paid = False) + // TODO: only get incomplete only from storage + let incomplete_requests = storage.get_requests()?; for req in incomplete_requests { - let _ = do_request_payment(&req, &client, &storage)?; + let _ = do_request_payment(&clientchain_config, &req, &client, &storage)?; } // Wait for new requests @@ -67,7 +87,7 @@ fn do_request_payments( match req_recv.recv() { Ok(resp) => { let req = storage.get_request(resp)?.unwrap(); - let _ = do_request_payment(&req, &client, &storage)?; + let _ = do_request_payment(&clientchain_config, &req, &client, &storage)?; } Err(RecvError) => { return Err(Error::from(CError::ReceiverDisconnected)); @@ -76,9 +96,9 @@ fn do_request_payments( } } -/// +/// TODO: add comments pub fn run_payments( - clientchain_config: &ClientChainConfig, + clientchain_config: ClientChainConfig, storage: Arc, req_recv: Receiver, ) -> Result> { @@ -88,8 +108,24 @@ pub fn run_payments( Some(clientchain_config.pass.clone()), )?; + if let Some(addr) = &clientchain_config.payment_addr { + let ocean_addr = Address::from_str(&addr)?; + if *ocean_addr.params != get_chain_addr_params(&clientchain_config.chain) { + warn!("payment addr and chain config addr param mismatch"); + } else if let Some(key) = &clientchain_config.payment_key { + let addr_unspent = client.list_unspent(None, None, Some(&[ocean_addr]), None, None)?; + if addr_unspent.len() == 0 { + client.import_priv_key(key, None, Some(true))?; + } + } else { + warn!("payment key missing"); + } + } else { + warn!("payment addr missing"); + } + Ok(thread::spawn(move || { - if let Err(err) = do_request_payments(client, storage.clone(), req_recv) { + if let Err(err) = do_request_payments(clientchain_config, client, storage.clone(), req_recv) { error! {"payments error: {}", err} } })) From a474f021b0982c4dbb2c6f1e76a52ff25cc3e1a0 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Tue, 19 Nov 2019 15:55:56 +0000 Subject: [PATCH 28/40] Update to bitcoin 0.20 --- Cargo.lock | 36 ++++++------------------------------ Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b12464b..c0e5f07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,19 +57,6 @@ name = "bech32" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "bitcoin" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin_hashes 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "secp256k1 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "bitcoin" version = "0.20.0" @@ -212,7 +199,7 @@ name = "coordinator" version = "0.3.9" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitcoin 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "config 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", @@ -831,9 +818,9 @@ dependencies = [ [[package]] name = "ocean-rpc" version = "0.8.0" -source = "git+https://github.com/commerceblock/rust-ocean-rpc#2b7f5a9a3a9a6d360dcdacb1ea4ea0c9db7bd6bc" +source = "git+https://github.com/commerceblock/rust-ocean-rpc#1215da59f5bca1f2f86727d1212b7367acff3290" dependencies = [ - "bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitcoin 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -847,9 +834,9 @@ dependencies = [ [[package]] name = "ocean-rpc-json" version = "0.8.0" -source = "git+https://github.com/commerceblock/rust-ocean-rpc#2b7f5a9a3a9a6d360dcdacb1ea4ea0c9db7bd6bc" +source = "git+https://github.com/commerceblock/rust-ocean-rpc#1215da59f5bca1f2f86727d1212b7367acff3290" dependencies = [ - "bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitcoin 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rust-ocean 0.10.0 (git+https://github.com/commerceblock/rust-ocean)", @@ -1108,7 +1095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rust-ocean" version = "0.10.0" -source = "git+https://github.com/commerceblock/rust-ocean#fdabe0afb50ea58eadcfa0b80c77f1da64182a45" +source = "git+https://github.com/commerceblock/rust-ocean#0caa99b3948e71d82f32a3f898b6385ce42884ef" dependencies = [ "bitcoin 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1145,15 +1132,6 @@ name = "scopeguard" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "secp256k1" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "secp256k1" version = "0.15.5" @@ -1704,7 +1682,6 @@ dependencies = [ "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0089c35ab7c6f2bc55ab23f769913f0ac65b1023e7e74638a1f43128dd5df2" -"checksum bitcoin 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd1353f2950c2ca1b67032a8984ef6cf4a732dd757cbb32b6dcc2825a9e56a3" "checksum bitcoin 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "01337c65290ce0c948738d821aa9f87488ca6c2b0f02d672ef778f9ae54f22c8" "checksum bitcoin_hashes 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "db6b697833d852acea530c9e815e6adc724267856b6506bc500362a068a39c7b" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" @@ -1822,7 +1799,6 @@ dependencies = [ "checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum scan_fmt 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b87497427f9fbe539ee6b9626f5a5e899331fdf1c1d62f14c637a462969db30" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum secp256k1 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4070f3906e65249228094cf97b04a90799fba04468190bbbcfa812309cf86e32" "checksum secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4d311229f403d64002e9eed9964dfa5a0a0c1ac443344f7546bf48e916c6053a" "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" diff --git a/Cargo.toml b/Cargo.toml index a14b019..0bc9fe6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,4 +19,4 @@ mongodb = "0.3.11" jsonrpc-http-server = "11.0" rust-ocean = { git = "https://github.com/commerceblock/rust-ocean"} ocean-rpc = { git = "https://github.com/commerceblock/rust-ocean-rpc"} -bitcoin = { version = "0.19.1", features = [ "use-serde" ] } +bitcoin = { version = "0.20", features = [ "use-serde" ] } From d07bd0d924c0e7809f7a464c20660374d7341190 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Tue, 19 Nov 2019 15:56:11 +0000 Subject: [PATCH 29/40] Complete mock payments template (pre model update --- src/payments.rs | 91 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/src/payments.rs b/src/payments.rs index 0156747..2a4c482 100644 --- a/src/payments.rs +++ b/src/payments.rs @@ -9,20 +9,25 @@ use std::thread; use bitcoin::hashes::sha256d; use bitcoin::Amount; +use bitcoin::PublicKey; use ocean::{Address, AddressParams}; use ocean_rpc::RpcApi; use crate::config::ClientChainConfig; use crate::error::{CError, Error, Result}; -use crate::interfaces::{request::Request, storage::Storage}; +use crate::interfaces::{ + request::{BidSet, Request}, + response::Response, + storage::Storage, +}; use crate::util::ocean::OceanClient; /// Get addr params from chain name -pub fn get_chain_addr_params(chain: &String) -> AddressParams { +pub fn get_chain_addr_params(chain: &String) -> &'static AddressParams { match chain.to_lowercase().as_ref() { - "ocean_main" => return AddressParams::OCEAN, - "gold_main" => return AddressParams::GOLD, - _ => AddressParams::ELEMENTS, + "ocean_main" => return &AddressParams::OCEAN, + "gold_main" => return &AddressParams::GOLD, + _ => &AddressParams::ELEMENTS, } } @@ -45,6 +50,51 @@ fn calculate_fees(request: &Request, client: &OceanClient) -> Result { Ok(fee_sum) } +/// TODO +fn calculate_bid_payment(fee_amount: &Amount, fee_percentage: u64, num_bids: u64) -> Result { + info!("amount: {}", fee_amount); + let gn_amount = *fee_amount * fee_percentage / 100; + info!("gn_amount: {}", gn_amount); + let gn_amount_per_gn = gn_amount / num_bids; + info!("gn_amount_per_gn: {}", gn_amount_per_gn); + Ok(gn_amount_per_gn) +} + +/// TODO +fn pay_bids(_client: &OceanClient, _clientchain_config: &ClientChainConfig, _bids: &BidSet) -> Result<()> { + // pay + // set bid txid + // update bid + Ok(()) +} + +/// TODO +fn process_bids( + bids: &BidSet, + bids_amount: &Amount, + response: &Response, + addr_params: &'static AddressParams, +) -> Result<()> { + for bid in bids { + if let Some(bid_resp) = response.bid_responses.get(&bid.txid) { + let gn_amount_corrected = *bids_amount * (*bid_resp).into() / response.num_challenges.into(); + let das_pub = PublicKey { + key: bid.pubkey, + compressed: true, + }; + let gn_pay_to_addr = Address::p2pkh(&das_pub, None, addr_params); + info!( + "bid: {}\naddr: {}\ngn_amount_corrected: {}\n", + bid.txid, gn_pay_to_addr, gn_amount_corrected + ); + + // set bid amount, addr + // update bid + } + } + Ok(()) +} + /// TODO: add comments fn do_request_payment( clientchain_config: &ClientChainConfig, @@ -53,19 +103,24 @@ fn do_request_payment( storage: &Arc, ) -> Result<()> { let bids = storage.get_bids(request.txid)?; - let resp = storage.get_response(request.txid)?; - let amount = calculate_fees(request, client)?; - info!("amount: {}", amount); - Ok(()) + if bids.len() > 0 { + if let Some(resp) = storage.get_response(request.txid)? { + let amount = calculate_fees(request, client)?; + let bid_payment = calculate_bid_payment(&amount, request.fee_percentage.into(), bids.len() as u64)?; + process_bids( + &bids, + &bid_payment, + &resp, + get_chain_addr_params(&clientchain_config.chain), + )?; + //pay_bids()?; + } + } - // calculate_fees() - // for bids: - // lookup in resps - // get address - // pay - // store - // update Bid - // update Request + // set request complete + // update request + + Ok(()) } /// TODO: add comments @@ -110,7 +165,7 @@ pub fn run_payments( if let Some(addr) = &clientchain_config.payment_addr { let ocean_addr = Address::from_str(&addr)?; - if *ocean_addr.params != get_chain_addr_params(&clientchain_config.chain) { + if *ocean_addr.params != *get_chain_addr_params(&clientchain_config.chain) { warn!("payment addr and chain config addr param mismatch"); } else if let Some(key) = &clientchain_config.payment_key { let addr_unspent = client.list_unspent(None, None, Some(&[ocean_addr]), None, None)?; From 715aaa87b1bcea784e0107114c90985d699e49f3 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Tue, 19 Nov 2019 17:09:48 +0000 Subject: [PATCH 30/40] Create Payments struct --- src/coordinator.rs | 2 +- src/payments.rs | 198 +++++++++++++++++++++++---------------------- 2 files changed, 101 insertions(+), 99 deletions(-) diff --git a/src/coordinator.rs b/src/coordinator.rs index d818ab0..3e583e2 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -27,7 +27,7 @@ pub fn run(config: Config) -> Result<()> { let _ = ::api::run_api_server(&config.api, storage.clone()); let (req_send, req_recv): (Sender, Receiver) = channel(); - let _ = ::payments::run_payments(config.clientchain.clone(), storage.clone(), req_recv); + let _ = ::payments::run_payments(config.clientchain.clone(), storage.clone(), req_recv)?; // This loop runs continuously fetching and running challenge requests, // generating challenge responses and fails on any errors that occur diff --git a/src/payments.rs b/src/payments.rs index 2a4c482..cf760d5 100644 --- a/src/payments.rs +++ b/src/payments.rs @@ -60,94 +60,117 @@ fn calculate_bid_payment(fee_amount: &Amount, fee_percentage: u64, num_bids: u64 Ok(gn_amount_per_gn) } -/// TODO -fn pay_bids(_client: &OceanClient, _clientchain_config: &ClientChainConfig, _bids: &BidSet) -> Result<()> { - // pay - // set bid txid - // update bid - Ok(()) +/// TODO: add comments +pub struct Payments { + storage: Arc, + config: ClientChainConfig, + client: OceanClient, + addr_params: &'static AddressParams, } -/// TODO -fn process_bids( - bids: &BidSet, - bids_amount: &Amount, - response: &Response, - addr_params: &'static AddressParams, -) -> Result<()> { - for bid in bids { - if let Some(bid_resp) = response.bid_responses.get(&bid.txid) { - let gn_amount_corrected = *bids_amount * (*bid_resp).into() / response.num_challenges.into(); - let das_pub = PublicKey { - key: bid.pubkey, - compressed: true, - }; - let gn_pay_to_addr = Address::p2pkh(&das_pub, None, addr_params); - info!( - "bid: {}\naddr: {}\ngn_amount_corrected: {}\n", - bid.txid, gn_pay_to_addr, gn_amount_corrected - ); - - // set bid amount, addr - // update bid - } +impl Payments { + /// TODO + fn pay_bids(&self, _bids: &BidSet) -> Result<()> { + // pay + // set bid txid + // update bid + Ok(()) } - Ok(()) -} -/// TODO: add comments -fn do_request_payment( - clientchain_config: &ClientChainConfig, - request: &Request, - client: &OceanClient, - storage: &Arc, -) -> Result<()> { - let bids = storage.get_bids(request.txid)?; - if bids.len() > 0 { - if let Some(resp) = storage.get_response(request.txid)? { - let amount = calculate_fees(request, client)?; - let bid_payment = calculate_bid_payment(&amount, request.fee_percentage.into(), bids.len() as u64)?; - process_bids( - &bids, - &bid_payment, - &resp, - get_chain_addr_params(&clientchain_config.chain), - )?; - //pay_bids()?; + /// TODO + fn process_bids(&self, bids: &BidSet, bid_payment: &Amount, response: &Response) -> Result<()> { + for bid in bids { + if let Some(bid_resp) = response.bid_responses.get(&bid.txid) { + let gn_amount_corrected = *bid_payment * (*bid_resp).into() / response.num_challenges.into(); + let das_pub = PublicKey { + key: bid.pubkey, + compressed: true, + }; + let gn_pay_to_addr = Address::p2pkh(&das_pub, None, self.addr_params); + info!( + "bid: {}\naddr: {}\ngn_amount_corrected: {}\n", + bid.txid, gn_pay_to_addr, gn_amount_corrected + ); + + // set bid amount, addr + // update bid + } } + Ok(()) } - // set request complete - // update request + /// TODO: add comments + fn do_request_payment(&self, request: &Request) -> Result<()> { + let bids = self.storage.get_bids(request.txid)?; + if bids.len() > 0 { + if let Some(resp) = self.storage.get_response(request.txid)? { + let amount = calculate_fees(request, &self.client)?; + let bid_payment = calculate_bid_payment(&amount, request.fee_percentage.into(), bids.len() as u64)?; + self.process_bids(&bids, &bid_payment, &resp)?; + self.pay_bids(&bids)?; + } + } - Ok(()) -} + // set request complete + // update request -/// TODO: add comments -fn do_request_payments( - clientchain_config: ClientChainConfig, - client: OceanClient, - storage: Arc, - req_recv: Receiver, -) -> Result<()> { - // First pay out any past requests that have not been fully paid yet - // TODO: only get incomplete only from storage - let incomplete_requests = storage.get_requests()?; - for req in incomplete_requests { - let _ = do_request_payment(&clientchain_config, &req, &client, &storage)?; + Ok(()) } - // Wait for new requests - loop { - match req_recv.recv() { - Ok(resp) => { - let req = storage.get_request(resp)?.unwrap(); - let _ = do_request_payment(&clientchain_config, &req, &client, &storage)?; + /// TODO: add comments + fn do_request_payments(&self, req_recv: Receiver) -> Result<()> { + // First pay out any past requests that have not been fully paid yet + // TODO: only get incomplete only from storage + let incomplete_requests = self.storage.get_requests()?; + for req in incomplete_requests { + let _ = self.do_request_payment(&req)?; + } + + // Wait for new requests + loop { + match req_recv.recv() { + Ok(resp) => { + let req = self.storage.get_request(resp)?.unwrap(); + let _ = self.do_request_payment(&req)?; + } + Err(RecvError) => { + return Err(Error::from(CError::ReceiverDisconnected)); + } } - Err(RecvError) => { - return Err(Error::from(CError::ReceiverDisconnected)); + } + } + + /// TODO: add comments + pub fn new(clientchain_config: ClientChainConfig, storage: Arc) -> Result { + let client = OceanClient::new( + clientchain_config.host.clone(), + Some(clientchain_config.user.clone()), + Some(clientchain_config.pass.clone()), + )?; + + let addr_params = get_chain_addr_params(&clientchain_config.chain); + if let Some(addr) = &clientchain_config.payment_addr { + let ocean_addr = Address::from_str(&addr)?; + if *ocean_addr.params != *addr_params { + warn!("payment addr and chain config addr param mismatch"); + } else if let Some(key) = &clientchain_config.payment_key { + let addr_unspent = client.list_unspent(None, None, Some(&[ocean_addr]), None, None)?; + if addr_unspent.len() == 0 { + client.import_priv_key(key, None, Some(true))?; + } + } else { + warn!("payment key missing"); } + } else { + warn!("payment addr missing"); } + + Ok(Payments { + storage: storage, + config: clientchain_config, + client: client, + addr_params: addr_params, + }) } } @@ -157,31 +180,10 @@ pub fn run_payments( storage: Arc, req_recv: Receiver, ) -> Result> { - let client = OceanClient::new( - clientchain_config.host.clone(), - Some(clientchain_config.user.clone()), - Some(clientchain_config.pass.clone()), - )?; - - if let Some(addr) = &clientchain_config.payment_addr { - let ocean_addr = Address::from_str(&addr)?; - if *ocean_addr.params != *get_chain_addr_params(&clientchain_config.chain) { - warn!("payment addr and chain config addr param mismatch"); - } else if let Some(key) = &clientchain_config.payment_key { - let addr_unspent = client.list_unspent(None, None, Some(&[ocean_addr]), None, None)?; - if addr_unspent.len() == 0 { - client.import_priv_key(key, None, Some(true))?; - } - } else { - warn!("payment key missing"); - } - } else { - warn!("payment addr missing"); - } - + let payments = Payments::new(clientchain_config, storage)?; Ok(thread::spawn(move || { - if let Err(err) = do_request_payments(clientchain_config, client, storage.clone(), req_recv) { - error! {"payments error: {}", err} + if let Err(err) = payments.do_request_payments(req_recv) { + error! {"payments error: {}", err}; } })) } From 59d847b8ddf9a9a48cc57457f56db3fce2d7304a Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Wed, 20 Nov 2019 12:43:42 +0000 Subject: [PATCH 31/40] Add BidPayment struct to Bid --- src/api.rs | 6 +-- src/interfaces/request.rs | 23 ++++++++++-- src/listener.rs | 10 ++++- src/util/doc_format.rs | 78 +++++++++++++++++++++++++++++++++++++-- src/util/testing.rs | 5 +++ 5 files changed, 111 insertions(+), 11 deletions(-) diff --git a/src/api.rs b/src/api.rs index 6a5204e..9b6b332 100644 --- a/src/api.rs +++ b/src/api.rs @@ -194,7 +194,7 @@ mod tests { let resp = get_request(params, storage.clone()); assert_eq!( format!( - r#"{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}}"#, + r#"{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}}"#, dummy_hash.to_string() ), resp.wait().unwrap() @@ -216,7 +216,7 @@ mod tests { let resp = get_requests(storage.clone()); assert_eq!( format!( - r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}}]}}"#, + r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}}]}}"#, dummy_hash.to_string() ), resp.wait().unwrap() @@ -228,7 +228,7 @@ mod tests { let resp = get_requests(storage.clone()); assert_eq!( format!( - r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}},{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"}}]}}]}}"#, + r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}},{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}}]}}"#, dummy_hash.to_string(), dummy_hash2.to_string() ), diff --git a/src/interfaces/request.rs b/src/interfaces/request.rs index 6b006a6..968c16b 100644 --- a/src/interfaces/request.rs +++ b/src/interfaces/request.rs @@ -4,8 +4,8 @@ use std::collections::HashSet; -use bitcoin::hashes::sha256d; -use bitcoin::secp256k1::PublicKey; +use bitcoin::{hashes::sha256d, secp256k1::PublicKey, Amount}; +use ocean::Address; use ocean_rpc::json::{GetRequestBidsResultBid, GetRequestsResult}; use serde::{Serialize, Serializer}; @@ -55,6 +55,8 @@ pub struct Bid { /// Bid owner verification public key #[serde(serialize_with = "serialize_pubkey")] pub pubkey: PublicKey, + /// Bid payment optional + pub payment: Option, } impl Bid { @@ -63,10 +65,24 @@ impl Bid { Bid { txid: res.txid, pubkey: res.fee_pub_key.key, + payment: None, } } } +/// Bid payment struct holding information for fee payments received by bid +/// owners +#[derive(Clone, Debug, PartialEq, Hash, Eq, Serialize)] +pub struct BidPayment { + /// Bid payment transaction id; optional as might not be set yet + pub txid: Option, + /// Bid pay to address + pub address: Address, + /// Bid amount expected + #[serde(with = "bitcoin::util::amount::serde::as_btc")] + pub amount: Amount, +} + /// Type defining a set of Bids pub type BidSet = HashSet; @@ -94,11 +110,12 @@ mod tests { let bid = Bid { txid: sha256d::Hash::from_hex(txid_hex).unwrap(), pubkey: PublicKey::from_str(pubkey_hex).unwrap(), + payment: None, }; let serialized = serde_json::to_string(&bid); assert_eq!( - format!(r#"{{"txid":"{}","pubkey":"{}"}}"#, txid_hex, pubkey_hex), + format!(r#"{{"txid":"{}","pubkey":"{}","payment":null}}"#, txid_hex, pubkey_hex), serialized.unwrap() ); } diff --git a/src/listener.rs b/src/listener.rs index 4d86f25..9ee7fc4 100644 --- a/src/listener.rs +++ b/src/listener.rs @@ -43,7 +43,11 @@ impl ChallengeProof { Ok(ChallengeProof { hash, sig, - bid: Bid { txid, pubkey }, + bid: Bid { + txid, + pubkey, + payment: None, + }, }) } @@ -258,6 +262,7 @@ mod tests { bid: Bid { txid: bid_txid, pubkey: bid_pubkey, + payment: None, }, }; @@ -274,6 +279,7 @@ mod tests { bid: Bid { txid: bid_txid, pubkey: bid_pubkey, + payment: None, }, }; @@ -414,6 +420,7 @@ mod tests { Bid { txid: bid_txid, pubkey: bid_pubkey, + payment: None }, )) ); // check receiver not empty @@ -662,6 +669,7 @@ mod tests { Bid { txid: bid_txid, pubkey: bid_pubkey, + payment: None }, )) ); // check receiver not empty diff --git a/src/util/doc_format.rs b/src/util/doc_format.rs index da45408..2412e4c 100644 --- a/src/util/doc_format.rs +++ b/src/util/doc_format.rs @@ -8,9 +8,11 @@ use std::str::FromStr; use bitcoin::hashes::{hex::FromHex, sha256d}; use bitcoin::secp256k1::PublicKey; +use bitcoin::Amount; use mongodb::{ordered::OrderedDocument, Bson}; +use ocean::Address; -use crate::interfaces::request::{Bid, Request}; +use crate::interfaces::request::{Bid, BidPayment, Request}; use crate::interfaces::response::Response; /// Util method that generates a Request document from a request @@ -43,18 +45,43 @@ pub fn doc_to_request(doc: &OrderedDocument) -> Request { /// Util method that generates a Bid document from a request bid pub fn bid_to_doc(request_id: &Bson, bid: &Bid) -> OrderedDocument { - doc! { + let mut bid_doc = doc! { "request_id": request_id.clone(), "txid": bid.txid.to_string(), - "pubkey": bid.pubkey.to_string() + "pubkey": bid.pubkey.to_string(), + }; + if let Some(payment) = &bid.payment { + let mut bid_payment_doc = doc! { + "address": payment.address.to_string(), + "amount": payment.amount.as_btc(), + }; + if let Some(txid) = payment.txid { + let _ = bid_payment_doc.insert("txid", txid.to_string()); + } + let _ = bid_doc.insert("payment", bid_payment_doc); } + bid_doc } /// Util method that generates a request bid from a Bid document pub fn doc_to_bid(doc: &OrderedDocument) -> Bid { + let mut payment: Option = None; + if let Some(doc_payment) = doc.get("payment") { + let doc_doc_payment = doc_payment.as_document().unwrap(); + let mut payment_txid: Option = None; + if let Some(doc_payment_txid) = doc_doc_payment.get("txid") { + payment_txid = Some(sha256d::Hash::from_hex(doc_payment_txid.as_str().unwrap()).unwrap()) + } + payment = Some(BidPayment { + txid: payment_txid, + address: Address::from_str(doc_doc_payment.get("address").unwrap().as_str().unwrap()).unwrap(), + amount: Amount::from_btc(doc_doc_payment.get("amount").unwrap().as_f64().unwrap()).unwrap(), + }); + } Bid { txid: sha256d::Hash::from_hex(doc.get("txid").unwrap().as_str().unwrap()).unwrap(), pubkey: PublicKey::from_str(doc.get("pubkey").unwrap().as_str().unwrap()).unwrap(), + payment: payment, } } @@ -139,9 +166,10 @@ mod tests { let id = ObjectId::new().unwrap(); let pubkey_hex = "026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"; let hash = gen_dummy_hash(1); - let bid = Bid { + let mut bid = Bid { txid: hash, pubkey: PublicKey::from_str(pubkey_hex).unwrap(), + payment: None, }; let doc = bid_to_doc(&Bson::ObjectId(id.clone()), &bid); @@ -154,6 +182,48 @@ mod tests { doc ); assert_eq!(bid, doc_to_bid(&doc)); + + let addr = "1HXfr2qBwT4qGZYn8FczNy68rw5dwG8trc"; + let amount = 56.123; + let mut bid_payment = BidPayment { + txid: None, + address: Address::from_str(addr).unwrap(), + amount: Amount::from_btc(amount).unwrap(), + }; + bid.payment = Some(bid_payment.clone()); + let doc = bid_to_doc(&Bson::ObjectId(id.clone()), &bid); + assert_eq!( + doc! { + "request_id": id.clone(), + "txid": hash.to_string(), + "pubkey": pubkey_hex, + "payment": doc!{ + "address": addr, + "amount": amount + } + }, + doc + ); + assert_eq!(bid, doc_to_bid(&doc)); + + let payment_txid = gen_dummy_hash(123); + bid_payment.txid = Some(payment_txid); + bid.payment = Some(bid_payment.clone()); + let doc = bid_to_doc(&Bson::ObjectId(id.clone()), &bid); + assert_eq!( + doc! { + "request_id": id.clone(), + "txid": hash.to_string(), + "pubkey": pubkey_hex, + "payment": doc!{ + "address": addr, + "amount": amount, + "txid": payment_txid.to_string() + } + }, + doc + ); + assert_eq!(bid, doc_to_bid(&doc)); } #[test] diff --git a/src/util/testing.rs b/src/util/testing.rs index 4887cd2..4bef5e1 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -40,6 +40,7 @@ pub fn gen_challenge_state(request_hash: &sha256d::Hash) -> ChallengeState { let _ = bids.insert(Bid { txid: sha256d::Hash::from_hex("1234567890000000000000000000000000000000000000000000000000000000").unwrap(), pubkey: PublicKey::from_str("026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3").unwrap(), + payment: None, }); ChallengeState { request, @@ -68,6 +69,7 @@ pub fn gen_challenge_state_with_challenge( txid: sha256d::Hash::from_hex("1234567890000000000000000000000000000000000000000000000000000000").unwrap(), // pubkey corresponding to SecretKey::from_slice(&[0xaa; 32]) pubkey: PublicKey::from_str("026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3").unwrap(), + payment: None, }); ChallengeState { request, @@ -200,16 +202,19 @@ impl Service for MockService { txid: sha256d::Hash::from_hex("1234567890000000000000000000000000000000000000000000000000000000").unwrap(), // pubkey corresponding to SecretKey::from_slice(&[0xaa; 32]) pubkey: PublicKey::from_str("026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3").unwrap(), + payment: None, }); let _ = bid_set.insert(Bid { txid: sha256d::Hash::from_hex("0000000001234567890000000000000000000000000000000000000000000000").unwrap(), // pubkey corresponding to SecretKey::from_slice(&[0xbb; 32]) pubkey: PublicKey::from_str("0268680737c76dabb801cb2204f57dbe4e4579e4f710cd67dc1b4227592c81e9b5").unwrap(), + payment: None, }); let _ = bid_set.insert(Bid { txid: sha256d::Hash::from_hex("0000000000000000001234567890000000000000000000000000000000000000").unwrap(), // pubkey corresponding to SecretKey::from_slice(&[0xcc; 32]) pubkey: PublicKey::from_str("02b95c249d84f417e3e395a127425428b540671cc15881eb828c17b722a53fc599").unwrap(), + payment: None, }); Ok(Some(bid_set)) } From 75f18ca313c12bcde59f52c6eeb0784bf8ad2be3 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Wed, 20 Nov 2019 12:54:45 +0000 Subject: [PATCH 32/40] Split Request and Bid --- src/api.rs | 2 +- src/challenger.rs | 5 ++- src/interfaces/bid.rs | 84 +++++++++++++++++++++++++++++++++++++++ src/interfaces/mod.rs | 1 + src/interfaces/request.rs | 84 ++------------------------------------- src/interfaces/service.rs | 5 ++- src/interfaces/storage.rs | 2 +- src/listener.rs | 2 +- src/payments.rs | 6 +-- src/util/doc_format.rs | 5 ++- src/util/testing.rs | 5 ++- 11 files changed, 109 insertions(+), 92 deletions(-) create mode 100644 src/interfaces/bid.rs diff --git a/src/api.rs b/src/api.rs index 9b6b332..04fcfde 100644 --- a/src/api.rs +++ b/src/api.rs @@ -15,9 +15,9 @@ use jsonrpc_http_server::{hyper::header, AccessControlAllowOrigin, DomainsValida use serde::{Deserialize, Serialize}; use crate::config::ApiConfig; -use crate::interfaces::request::{BidSet, Request as ServiceRequest}; use crate::interfaces::response::Response as ChallengeResponse; use crate::interfaces::storage::Storage; +use crate::interfaces::{bid::BidSet, request::Request as ServiceRequest}; #[derive(Deserialize, Debug)] struct GetRequestParams { diff --git a/src/challenger.rs b/src/challenger.rs index 2f1ae9a..22d6183 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -12,9 +12,12 @@ use bitcoin::hashes::sha256d; use crate::error::{CError, Error, Result}; use crate::interfaces::clientchain::ClientChain; -use crate::interfaces::request::{Bid, BidSet, Request}; use crate::interfaces::service::Service; use crate::interfaces::storage::Storage; +use crate::interfaces::{ + bid::{Bid, BidSet}, + request::Request, +}; /// Verify attempt interval to client in ms pub const CHALLENGER_VERIFY_INTERVAL: u64 = 100; diff --git a/src/interfaces/bid.rs b/src/interfaces/bid.rs new file mode 100644 index 0000000..0af7328 --- /dev/null +++ b/src/interfaces/bid.rs @@ -0,0 +1,84 @@ +//! # Bid +//! +//! Service request models for bids and bid payments + +use std::collections::HashSet; + +use bitcoin::{hashes::sha256d, secp256k1::PublicKey, Amount}; +use ocean::Address; +use ocean_rpc::json::GetRequestBidsResultBid; +use serde::{Serialize, Serializer}; + +/// Bid struct storing successful bids and modelling data that need to be stored +#[derive(Clone, Debug, PartialEq, Hash, Eq, Serialize)] +pub struct Bid { + /// Ocean transaction ID of the bid transaction + pub txid: sha256d::Hash, + /// Bid owner verification public key + #[serde(serialize_with = "serialize_pubkey")] + pub pubkey: PublicKey, + /// Bid payment optional + pub payment: Option, +} + +impl Bid { + /// Return an instance of Bid from an ocean json rpc GetRequestBidsResultBid + pub fn from_json(res: &GetRequestBidsResultBid) -> Self { + Bid { + txid: res.txid, + pubkey: res.fee_pub_key.key, + payment: None, + } + } +} + +/// Bid payment struct holding information for fee payments received by bid +/// owners +#[derive(Clone, Debug, PartialEq, Hash, Eq, Serialize)] +pub struct BidPayment { + /// Bid payment transaction id; optional as might not be set yet + pub txid: Option, + /// Bid pay to address + pub address: Address, + /// Bid amount expected + #[serde(with = "bitcoin::util::amount::serde::as_btc")] + pub amount: Amount, +} + +/// Type defining a set of Bids +pub type BidSet = HashSet; + +/// Custom serializer for type PublicKey in order to serialize +/// the key into a string and not the default u8 vector +fn serialize_pubkey(x: &PublicKey, s: S) -> Result +where + S: Serializer, +{ + s.serialize_str(&x.to_string()) +} + +#[cfg(test)] +mod tests { + use super::*; + + use std::str::FromStr; + + use bitcoin::hashes::hex::FromHex; + + #[test] + fn serialize_pubkey_test() { + let txid_hex = "1234567890000000000000000000000000000000000000000000000000000000"; + let pubkey_hex = "026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"; + let bid = Bid { + txid: sha256d::Hash::from_hex(txid_hex).unwrap(), + pubkey: PublicKey::from_str(pubkey_hex).unwrap(), + payment: None, + }; + + let serialized = serde_json::to_string(&bid); + assert_eq!( + format!(r#"{{"txid":"{}","pubkey":"{}","payment":null}}"#, txid_hex, pubkey_hex), + serialized.unwrap() + ); + } +} diff --git a/src/interfaces/mod.rs b/src/interfaces/mod.rs index b9cc2b0..a75dcf4 100644 --- a/src/interfaces/mod.rs +++ b/src/interfaces/mod.rs @@ -2,6 +2,7 @@ //! //! Interfaces used by the coordinator library +pub mod bid; pub mod clientchain; pub mod request; pub mod response; diff --git a/src/interfaces/request.rs b/src/interfaces/request.rs index 968c16b..886f6ca 100644 --- a/src/interfaces/request.rs +++ b/src/interfaces/request.rs @@ -1,13 +1,11 @@ //! # Request //! -//! Service request models for client requests and bids +//! Service request models for client requests -use std::collections::HashSet; +use bitcoin::hashes::sha256d; -use bitcoin::{hashes::sha256d, secp256k1::PublicKey, Amount}; -use ocean::Address; -use ocean_rpc::json::{GetRequestBidsResultBid, GetRequestsResult}; -use serde::{Serialize, Serializer}; +use ocean_rpc::json::GetRequestsResult; +use serde::Serialize; /// Request struct storing info on client request and modelling data that need /// to be stored @@ -46,77 +44,3 @@ impl Request { } } } - -/// Bid struct storing successful bids and modelling data that need to be stored -#[derive(Clone, Debug, PartialEq, Hash, Eq, Serialize)] -pub struct Bid { - /// Ocean transaction ID of the bid transaction - pub txid: sha256d::Hash, - /// Bid owner verification public key - #[serde(serialize_with = "serialize_pubkey")] - pub pubkey: PublicKey, - /// Bid payment optional - pub payment: Option, -} - -impl Bid { - /// Return an instance of Bid from an ocean json rpc GetRequestBidsResultBid - pub fn from_json(res: &GetRequestBidsResultBid) -> Self { - Bid { - txid: res.txid, - pubkey: res.fee_pub_key.key, - payment: None, - } - } -} - -/// Bid payment struct holding information for fee payments received by bid -/// owners -#[derive(Clone, Debug, PartialEq, Hash, Eq, Serialize)] -pub struct BidPayment { - /// Bid payment transaction id; optional as might not be set yet - pub txid: Option, - /// Bid pay to address - pub address: Address, - /// Bid amount expected - #[serde(with = "bitcoin::util::amount::serde::as_btc")] - pub amount: Amount, -} - -/// Type defining a set of Bids -pub type BidSet = HashSet; - -/// Custom serializer for type PublicKey in order to serialize -/// the key into a string and not the default u8 vector -fn serialize_pubkey(x: &PublicKey, s: S) -> Result -where - S: Serializer, -{ - s.serialize_str(&x.to_string()) -} - -#[cfg(test)] -mod tests { - use super::*; - - use std::str::FromStr; - - use bitcoin::hashes::hex::FromHex; - - #[test] - fn serialize_pubkey_test() { - let txid_hex = "1234567890000000000000000000000000000000000000000000000000000000"; - let pubkey_hex = "026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"; - let bid = Bid { - txid: sha256d::Hash::from_hex(txid_hex).unwrap(), - pubkey: PublicKey::from_str(pubkey_hex).unwrap(), - payment: None, - }; - - let serialized = serde_json::to_string(&bid); - assert_eq!( - format!(r#"{{"txid":"{}","pubkey":"{}","payment":null}}"#, txid_hex, pubkey_hex), - serialized.unwrap() - ); - } -} diff --git a/src/interfaces/service.rs b/src/interfaces/service.rs index a044548..6cffe87 100644 --- a/src/interfaces/service.rs +++ b/src/interfaces/service.rs @@ -7,7 +7,10 @@ use ocean_rpc::RpcApi; use crate::config::ServiceConfig; use crate::error::Result; -use crate::interfaces::request::{Bid, BidSet, Request}; +use crate::interfaces::{ + bid::{Bid, BidSet}, + request::Request, +}; use crate::util::ocean::OceanClient; /// Service trait defining functionality for interfacing with service chain diff --git a/src/interfaces/storage.rs b/src/interfaces/storage.rs index d332af3..fb25d42 100644 --- a/src/interfaces/storage.rs +++ b/src/interfaces/storage.rs @@ -13,8 +13,8 @@ use util::doc_format::*; use crate::challenger::{ChallengeResponseIds, ChallengeState}; use crate::config::StorageConfig; use crate::error::{Error::MongoDb, Result}; -use crate::interfaces::request::{BidSet, Request}; use crate::interfaces::response::Response; +use crate::interfaces::{bid::BidSet, request::Request}; /// Storage trait defining required functionality for objects that store request /// and challenge information diff --git a/src/listener.rs b/src/listener.rs index 9ee7fc4..6352e59 100644 --- a/src/listener.rs +++ b/src/listener.rs @@ -20,7 +20,7 @@ use serde_json::{self, Value}; use crate::challenger::{ChallengeResponse, ChallengeState}; use crate::error::Result; -use crate::interfaces::request::Bid; +use crate::interfaces::bid::Bid; /// Messsage type for challenge proofs sent by guardnodes #[derive(Debug)] diff --git a/src/payments.rs b/src/payments.rs index cf760d5..14b8af3 100644 --- a/src/payments.rs +++ b/src/payments.rs @@ -15,11 +15,7 @@ use ocean_rpc::RpcApi; use crate::config::ClientChainConfig; use crate::error::{CError, Error, Result}; -use crate::interfaces::{ - request::{BidSet, Request}, - response::Response, - storage::Storage, -}; +use crate::interfaces::{bid::BidSet, request::Request, response::Response, storage::Storage}; use crate::util::ocean::OceanClient; /// Get addr params from chain name diff --git a/src/util/doc_format.rs b/src/util/doc_format.rs index 2412e4c..2d4dc65 100644 --- a/src/util/doc_format.rs +++ b/src/util/doc_format.rs @@ -12,8 +12,11 @@ use bitcoin::Amount; use mongodb::{ordered::OrderedDocument, Bson}; use ocean::Address; -use crate::interfaces::request::{Bid, BidPayment, Request}; use crate::interfaces::response::Response; +use crate::interfaces::{ + bid::{Bid, BidPayment}, + request::Request, +}; /// Util method that generates a Request document from a request pub fn request_to_doc(request: &Request) -> OrderedDocument { diff --git a/src/util/testing.rs b/src/util/testing.rs index 4bef5e1..884ea13 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -12,10 +12,13 @@ use util::doc_format::*; use crate::challenger::{ChallengeResponseIds, ChallengeState}; use crate::interfaces::clientchain::ClientChain; -use crate::interfaces::request::{Bid, BidSet, Request as ServiceRequest}; use crate::interfaces::response::Response; use crate::interfaces::service::Service; use crate::interfaces::storage::*; +use crate::interfaces::{ + bid::{Bid, BidSet}, + request::Request as ServiceRequest, +}; use crate::error::*; From d7603d18996b9669a6589ba989c7063625620e0a Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Wed, 20 Nov 2019 13:39:15 +0000 Subject: [PATCH 33/40] update cargo for rust-ocean update to support gold addresses --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index c0e5f07..37b59c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1095,7 +1095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rust-ocean" version = "0.10.0" -source = "git+https://github.com/commerceblock/rust-ocean#0caa99b3948e71d82f32a3f898b6385ce42884ef" +source = "git+https://github.com/commerceblock/rust-ocean#56a64d11f6f073caebfb37c2fc92b97a288be8ec" dependencies = [ "bitcoin 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", From 41a6d6f86d14556698c040d4a09c0556469b18d2 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Wed, 20 Nov 2019 14:54:08 +0000 Subject: [PATCH 34/40] Add is_payment_complete flag to Request model --- src/api.rs | 6 +++--- src/interfaces/request.rs | 3 +++ src/util/doc_format.rs | 6 +++++- src/util/testing.rs | 3 +++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/api.rs b/src/api.rs index 04fcfde..e95f553 100644 --- a/src/api.rs +++ b/src/api.rs @@ -194,7 +194,7 @@ mod tests { let resp = get_request(params, storage.clone()); assert_eq!( format!( - r#"{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}}"#, + r#"{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0,"is_payment_complete":false}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}}"#, dummy_hash.to_string() ), resp.wait().unwrap() @@ -216,7 +216,7 @@ mod tests { let resp = get_requests(storage.clone()); assert_eq!( format!( - r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}}]}}"#, + r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0,"is_payment_complete":false}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}}]}}"#, dummy_hash.to_string() ), resp.wait().unwrap() @@ -228,7 +228,7 @@ mod tests { let resp = get_requests(storage.clone()); assert_eq!( format!( - r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}},{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}}]}}"#, + r#"{{"requests":[{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0,"is_payment_complete":false}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}},{{"request":{{"txid":"{}","start_blockheight":2,"end_blockheight":5,"genesis_blockhash":"0000000000000000000000000000000000000000000000000000000000000000","fee_percentage":5,"num_tickets":10,"start_blockheight_clientchain":0,"end_blockheight_clientchain":0,"is_payment_complete":false}},"bids":[{{"txid":"1234567890000000000000000000000000000000000000000000000000000000","pubkey":"026a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3","payment":null}}]}}]}}"#, dummy_hash.to_string(), dummy_hash2.to_string() ), diff --git a/src/interfaces/request.rs b/src/interfaces/request.rs index 886f6ca..76b959f 100644 --- a/src/interfaces/request.rs +++ b/src/interfaces/request.rs @@ -27,6 +27,8 @@ pub struct Request { pub start_blockheight_clientchain: u32, /// Request client chain end block height pub end_blockheight_clientchain: u32, + /// Payment complete flag for request + pub is_payment_complete: bool, } impl Request { @@ -41,6 +43,7 @@ impl Request { num_tickets: res.num_tickets, start_blockheight_clientchain: 0, end_blockheight_clientchain: 0, + is_payment_complete: false, } } } diff --git a/src/util/doc_format.rs b/src/util/doc_format.rs index 2d4dc65..f346934 100644 --- a/src/util/doc_format.rs +++ b/src/util/doc_format.rs @@ -29,6 +29,7 @@ pub fn request_to_doc(request: &Request) -> OrderedDocument { "num_tickets": request.num_tickets, "start_blockheight_clientchain": request.start_blockheight_clientchain, "end_blockheight_clientchain": request.end_blockheight_clientchain, + "is_payment_complete": request.is_payment_complete, } } @@ -43,6 +44,7 @@ pub fn doc_to_request(doc: &OrderedDocument) -> Request { num_tickets: doc.get("num_tickets").unwrap().as_i32().unwrap() as u32, start_blockheight_clientchain: doc.get("start_blockheight_clientchain").unwrap().as_i32().unwrap() as u32, end_blockheight_clientchain: doc.get("end_blockheight_clientchain").unwrap().as_i32().unwrap() as u32, + is_payment_complete: doc.get("is_payment_complete").unwrap().as_bool().unwrap(), } } @@ -145,6 +147,7 @@ mod tests { num_tickets: 10, start_blockheight_clientchain: 0, end_blockheight_clientchain: 0, + is_payment_complete: false, }; let doc = request_to_doc(&request); @@ -157,7 +160,8 @@ mod tests { "fee_percentage": 5, "num_tickets": 10, "start_blockheight_clientchain":0, - "end_blockheight_clientchain":0 + "end_blockheight_clientchain":0, + "is_payment_complete": false, }, doc ); diff --git a/src/util/testing.rs b/src/util/testing.rs index 884ea13..1006d02 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -38,6 +38,7 @@ pub fn gen_challenge_state(request_hash: &sha256d::Hash) -> ChallengeState { num_tickets: 10, start_blockheight_clientchain: 0, end_blockheight_clientchain: 0, + is_payment_complete: false, }; let mut bids = BidSet::new(); let _ = bids.insert(Bid { @@ -66,6 +67,7 @@ pub fn gen_challenge_state_with_challenge( num_tickets: 10, start_blockheight_clientchain: 0, end_blockheight_clientchain: 0, + is_payment_complete: false, }; let mut bids = BidSet::new(); let _ = bids.insert(Bid { @@ -161,6 +163,7 @@ impl MockService { num_tickets: 10, start_blockheight_clientchain: 0, end_blockheight_clientchain: 0, + is_payment_complete: false, }; MockService { From 56def855635877d41949e0f2666c3daccee953e3 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Thu, 21 Nov 2019 09:56:47 +0000 Subject: [PATCH 35/40] Add payment complete flag to getrequests from db --- src/api.rs | 2 +- src/challenger.rs | 4 ++-- src/interfaces/storage.rs | 17 ++++++++++++----- src/payments.rs | 2 +- src/util/testing.rs | 5 +++-- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/api.rs b/src/api.rs index e95f553..bf58f07 100644 --- a/src/api.rs +++ b/src/api.rs @@ -59,7 +59,7 @@ struct GetRequestsResponse { /// Get requests RPC call returning all stored requests fn get_requests(storage: Arc) -> futures::Finished { - let requests = storage.get_requests().unwrap(); + let requests = storage.get_requests(None).unwrap(); let mut response = GetRequestsResponse { requests: vec![] }; for request in requests { let bids = storage.get_bids(request.txid).unwrap(); diff --git a/src/challenger.rs b/src/challenger.rs index 22d6183..5d56a50 100644 --- a/src/challenger.rs +++ b/src/challenger.rs @@ -498,7 +498,7 @@ mod tests { assert_eq!(resps, None); let bids = storage.get_bids(dummy_request.txid).unwrap(); assert_eq!(challenge_state.bids, bids); - let requests = storage.get_requests().unwrap(); + let requests = storage.get_requests(None).unwrap(); assert_eq!(1, requests.len()); assert_eq!(&challenge_state.request, &requests[0]); assert_eq!( @@ -539,7 +539,7 @@ mod tests { assert_eq!(1, storage.challenge_responses.borrow().len()); let bids = storage.get_bids(dummy_request.txid).unwrap(); assert_eq!(challenge_state.bids, bids); - let requests = storage.get_requests().unwrap(); + let requests = storage.get_requests(None).unwrap(); assert_eq!(1, requests.len()); assert_eq!(&challenge_state.request, &requests[0]); assert_eq!( diff --git a/src/interfaces/storage.rs b/src/interfaces/storage.rs index fb25d42..7175f09 100644 --- a/src/interfaces/storage.rs +++ b/src/interfaces/storage.rs @@ -29,8 +29,9 @@ pub trait Storage { fn get_response(&self, request_hash: sha256d::Hash) -> Result>; /// Get all bids for a specific request fn get_bids(&self, request_hash: sha256d::Hash) -> Result; - /// Get all the requests - fn get_requests(&self) -> Result>; + /// Get all the requests, with an optional flag to return payment complete + /// only + fn get_requests(&self, complete: Option) -> Result>; /// Get request for a specific request txid fn get_request(&self, request_hash: sha256d::Hash) -> Result>; } @@ -241,14 +242,20 @@ impl Storage for MongoStorage { Ok(all_bids) } - /// Get all the requests - fn get_requests(&self) -> Result> { + /// Get all the requests, with an optional flag to return payment complete + /// only + fn get_requests(&self, complete: Option) -> Result> { let db_locked = self.db.lock().unwrap(); self.auth(&db_locked)?; let mut options = FindOptions::new(); options.sort = Some(doc! { "_id" : 1 }); // sort ascending, latest request is last - let resps = db_locked.collection("Request").find(None, Some(options))?; + let filter = if let Some(is_complete) = complete { + Some(doc! { "is_payment_complete": is_complete }) + } else { + None + }; + let resps = db_locked.collection("Request").find(filter, Some(options))?; drop(db_locked); // drop immediately on get requests let mut requests = vec![]; diff --git a/src/payments.rs b/src/payments.rs index 14b8af3..3f61eae 100644 --- a/src/payments.rs +++ b/src/payments.rs @@ -117,7 +117,7 @@ impl Payments { fn do_request_payments(&self, req_recv: Receiver) -> Result<()> { // First pay out any past requests that have not been fully paid yet // TODO: only get incomplete only from storage - let incomplete_requests = self.storage.get_requests()?; + let incomplete_requests = self.storage.get_requests(Some(false))?; for req in incomplete_requests { let _ = self.do_request_payment(&req)?; } diff --git a/src/util/testing.rs b/src/util/testing.rs index 1006d02..ff836e6 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -340,8 +340,9 @@ impl Storage for MockStorage { Ok(bids) } - /// Get all the requests - fn get_requests(&self) -> Result> { + /// Get all the requests, with an optional flag to return payment complete + /// only + fn get_requests(&self, complete: Option) -> Result> { let mut requests = vec![]; for doc in self.requests.borrow().to_vec().iter() { requests.push(doc_to_request(doc)) From d028836c778a4026fa4f24b64020c424719ef960 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Thu, 21 Nov 2019 11:29:33 +0000 Subject: [PATCH 36/40] payments daemon more details --- src/interfaces/storage.rs | 4 +- src/payments.rs | 100 +++++++++++++++++++++++++------------- src/util/testing.rs | 4 +- 3 files changed, 70 insertions(+), 38 deletions(-) diff --git a/src/interfaces/storage.rs b/src/interfaces/storage.rs index 7175f09..7dca229 100644 --- a/src/interfaces/storage.rs +++ b/src/interfaces/storage.rs @@ -22,7 +22,7 @@ pub trait Storage { /// Store the state of a challenge request fn save_challenge_state(&self, challenge: &ChallengeState) -> Result<()>; /// Update request in storage - fn update_request(&self, request: Request) -> Result<()>; + fn update_request(&self, request: &Request) -> Result<()>; /// Store response for a specific challenge request fn save_response(&self, request_hash: sha256d::Hash, ids: &ChallengeResponseIds) -> Result<()>; /// Get challenge response for a specific request @@ -124,7 +124,7 @@ impl Storage for MongoStorage { } /// Update entry in Request collection with given Request model - fn update_request(&self, request: Request) -> Result<()> { + fn update_request(&self, request: &Request) -> Result<()> { let db_locked = self.db.lock().unwrap(); self.auth(&db_locked)?; let coll = db_locked.collection("Request"); diff --git a/src/payments.rs b/src/payments.rs index 3f61eae..707348d 100644 --- a/src/payments.rs +++ b/src/payments.rs @@ -15,7 +15,12 @@ use ocean_rpc::RpcApi; use crate::config::ClientChainConfig; use crate::error::{CError, Error, Result}; -use crate::interfaces::{bid::BidSet, request::Request, response::Response, storage::Storage}; +use crate::interfaces::{ + bid::{Bid, BidPayment}, + request::Request, + response::Response, + storage::Storage, +}; use crate::util::ocean::OceanClient; /// Get addr params from chain name @@ -66,68 +71,90 @@ pub struct Payments { impl Payments { /// TODO - fn pay_bids(&self, _bids: &BidSet) -> Result<()> { + fn complete_bid_payments(&self, _bids: &mut Vec) -> Result<()> { // pay // set bid txid // update bid Ok(()) } - /// TODO - fn process_bids(&self, bids: &BidSet, bid_payment: &Amount, response: &Response) -> Result<()> { + /// Process bid payments method handles calculating the payment to be + /// received per bid and on which address, and updates the corresponding + /// payment info in Storage + fn process_bid_payments(&self, bids: &mut Vec, bid_payment: &Amount, response: &Response) -> Result<()> { for bid in bids { if let Some(bid_resp) = response.bid_responses.get(&bid.txid) { - let gn_amount_corrected = *bid_payment * (*bid_resp).into() / response.num_challenges.into(); - let das_pub = PublicKey { - key: bid.pubkey, - compressed: true, - }; - let gn_pay_to_addr = Address::p2pkh(&das_pub, None, self.addr_params); - info!( - "bid: {}\naddr: {}\ngn_amount_corrected: {}\n", - bid.txid, gn_pay_to_addr, gn_amount_corrected + // correct bid payment by calculating the performance + // base on successful responses / total responses + let bid_payment_corrected = *bid_payment * (*bid_resp).into() / response.num_challenges.into(); + let bid_pay_to_addr = Address::p2pkh( + &PublicKey { + key: bid.pubkey, + compressed: true, + }, + None, + self.addr_params, ); - // set bid amount, addr + bid.payment = Some(BidPayment { + amount: bid_payment_corrected, + address: bid_pay_to_addr, + txid: None, + }); // update bid } } Ok(()) } - /// TODO: add comments - fn do_request_payment(&self, request: &Request) -> Result<()> { - let bids = self.storage.get_bids(request.txid)?; - if bids.len() > 0 { + /// Method that handles payments for a single request, fetching bid + /// information, calculating fees, updating payment information and doing + /// payments + fn do_request_payment(&self, request: &mut Request) -> Result<()> { + // skip requests that have not finished + if request.end_blockheight_clientchain == 0 + || (self.client.get_block_count()? as u32) < request.end_blockheight_clientchain + { + warn! {"Skipping unfinished request: {}", request.txid}; + } + + // fetch bids and responses + let bids_set = self.storage.get_bids(request.txid)?; + if bids_set.len() > 0 { + let mut bids: Vec = bids_set.iter().map(|val| val.clone()).collect(); if let Some(resp) = self.storage.get_response(request.txid)? { - let amount = calculate_fees(request, &self.client)?; - let bid_payment = calculate_bid_payment(&amount, request.fee_percentage.into(), bids.len() as u64)?; - self.process_bids(&bids, &bid_payment, &resp)?; - self.pay_bids(&bids)?; + let fees_amount = calculate_fees(request, &self.client)?; + info! {"Total fees: {}", fees_amount}; + let bid_payment_amount = + calculate_bid_payment(&fees_amount, request.fee_percentage.into(), bids.len() as u64)?; + self.process_bid_payments(&mut bids, &bid_payment_amount, &resp)?; + self.complete_bid_payments(&mut bids)?; } } - // set request complete - // update request - + // update request with payment complete + request.is_payment_complete = true; + self.storage.update_request(request)?; Ok(()) } - /// TODO: add comments + /// Main Request payments method; first checks for any incomplete requests + /// and then listens for new requests on the receiver channel fn do_request_payments(&self, req_recv: Receiver) -> Result<()> { - // First pay out any past requests that have not been fully paid yet - // TODO: only get incomplete only from storage + // Look for incomplete requests let incomplete_requests = self.storage.get_requests(Some(false))?; - for req in incomplete_requests { - let _ = self.do_request_payment(&req)?; + for mut req in incomplete_requests { + info! {"Found incomplete request: {} ", req.txid}; + let _ = self.do_request_payment(&mut req)?; } // Wait for new requests loop { match req_recv.recv() { Ok(resp) => { - let req = self.storage.get_request(resp)?.unwrap(); - let _ = self.do_request_payment(&req)?; + let mut req = self.storage.get_request(resp)?.unwrap(); + info! {"New request: {}", req.txid}; + let _ = self.do_request_payment(&mut req)?; } Err(RecvError) => { return Err(Error::from(CError::ReceiverDisconnected)); @@ -136,7 +163,10 @@ impl Payments { } } - /// TODO: add comments + /// Return new Payments instance that requires clientchain config for + /// various payment info and rpc calls to calculate payment fees and do the + /// payments as well as a thread-safe reference to a Storage instance for + /// getting request information and updating payment details pub fn new(clientchain_config: ClientChainConfig, storage: Arc) -> Result { let client = OceanClient::new( clientchain_config.host.clone(), @@ -144,6 +174,7 @@ impl Payments { Some(clientchain_config.pass.clone()), )?; + // Check if payment addr/key are set and import the key for payment funds let addr_params = get_chain_addr_params(&clientchain_config.chain); if let Some(addr) = &clientchain_config.payment_addr { let ocean_addr = Address::from_str(&addr)?; @@ -170,7 +201,8 @@ impl Payments { } } -/// TODO: add comments +/// Run payments daemon in a separate thread with a Payments instance receiving +/// information on finished requests via a Receiver channel pub fn run_payments( clientchain_config: ClientChainConfig, storage: Arc, diff --git a/src/util/testing.rs b/src/util/testing.rs index ff836e6..ef4594a 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -287,7 +287,7 @@ impl Storage for MockStorage { } /// update request in mock storage - fn update_request(&self, request_update: ServiceRequest) -> Result<()> { + fn update_request(&self, request_update: &ServiceRequest) -> Result<()> { for request in self.requests.borrow_mut().iter_mut() { if request.get("txid").unwrap().as_str().unwrap() == &request_update.txid.to_string() { *request = request_to_doc(&request_update); @@ -342,7 +342,7 @@ impl Storage for MockStorage { /// Get all the requests, with an optional flag to return payment complete /// only - fn get_requests(&self, complete: Option) -> Result> { + fn get_requests(&self, _complete: Option) -> Result> { let mut requests = vec![]; for doc in self.requests.borrow().to_vec().iter() { requests.push(doc_to_request(doc)) From d96953c690a7ffc947ce2b4b7d9c91dfa30807f9 Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Thu, 21 Nov 2019 14:30:14 +0000 Subject: [PATCH 37/40] Update bid storage method --- src/interfaces/storage.rs | 34 ++++++++++++++++++++++++++++++++-- src/payments.rs | 7 +++++-- src/util/testing.rs | 5 +++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/interfaces/storage.rs b/src/interfaces/storage.rs index 7dca229..7602b2e 100644 --- a/src/interfaces/storage.rs +++ b/src/interfaces/storage.rs @@ -14,7 +14,10 @@ use crate::challenger::{ChallengeResponseIds, ChallengeState}; use crate::config::StorageConfig; use crate::error::{Error::MongoDb, Result}; use crate::interfaces::response::Response; -use crate::interfaces::{bid::BidSet, request::Request}; +use crate::interfaces::{ + bid::{Bid, BidSet}, + request::Request, +}; /// Storage trait defining required functionality for objects that store request /// and challenge information @@ -23,6 +26,8 @@ pub trait Storage { fn save_challenge_state(&self, challenge: &ChallengeState) -> Result<()>; /// Update request in storage fn update_request(&self, request: &Request) -> Result<()>; + /// Update bid in storage + fn update_bid(&self, request_hash: sha256d::Hash, bid: &Bid) -> Result<()>; /// Store response for a specific challenge request fn save_response(&self, request_hash: sha256d::Hash, ids: &ChallengeResponseIds) -> Result<()>; /// Get challenge response for a specific request @@ -123,7 +128,7 @@ impl Storage for MongoStorage { Ok(()) } - /// Update entry in Request collection with given Request model + /// Update entry in Request collection with given Request object fn update_request(&self, request: &Request) -> Result<()> { let db_locked = self.db.lock().unwrap(); self.auth(&db_locked)?; @@ -134,6 +139,31 @@ impl Storage for MongoStorage { Ok(()) } + /// Update entry in Bid collection with given Bid object + fn update_bid(&self, request_hash: sha256d::Hash, bid: &Bid) -> Result<()> { + let db_locked = self.db.lock().unwrap(); + self.auth(&db_locked)?; + + let request_id = db_locked + .collection("Request") + .find_one( + Some(doc! { + "txid": request_hash.to_string(), + }), + None, + )? + .unwrap() + .get("_id") + .unwrap() + .clone(); + + let coll = db_locked.collection("Bid"); + let filter = doc! {"request_id": request_id.clone()}; + let update = doc! {"$set" => bid_to_doc(&request_id, &bid)}; + let _ = coll.update_one(filter, update, None)?; + Ok(()) + } + /// Store response for a specific challenge request fn save_response(&self, request_hash: sha256d::Hash, ids: &ChallengeResponseIds) -> Result<()> { let db_locked = self.db.lock().unwrap(); diff --git a/src/payments.rs b/src/payments.rs index 707348d..7173618 100644 --- a/src/payments.rs +++ b/src/payments.rs @@ -74,7 +74,6 @@ impl Payments { fn complete_bid_payments(&self, _bids: &mut Vec) -> Result<()> { // pay // set bid txid - // update bid Ok(()) } @@ -101,7 +100,6 @@ impl Payments { address: bid_pay_to_addr, txid: None, }); - // update bid } } Ok(()) @@ -130,6 +128,11 @@ impl Payments { self.process_bid_payments(&mut bids, &bid_payment_amount, &resp)?; self.complete_bid_payments(&mut bids)?; } + + // update bids with payment information + for bid in bids { + self.storage.update_bid(request.txid, &bid)?; + } } // update request with payment complete diff --git a/src/util/testing.rs b/src/util/testing.rs index ef4594a..77c059c 100644 --- a/src/util/testing.rs +++ b/src/util/testing.rs @@ -296,6 +296,11 @@ impl Storage for MockStorage { Ok(()) } + /// update bid in mock storage + fn update_bid(&self, _request_hash: sha256d::Hash, _bid: &Bid) -> Result<()> { + Ok(()) + } + /// Store response for a specific challenge request fn save_response(&self, request_hash: sha256d::Hash, ids: &ChallengeResponseIds) -> Result<()> { if self.return_err { From 79d28639eaadce9f7c4be7d0ed52b848c4899c8e Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Thu, 21 Nov 2019 14:49:27 +0000 Subject: [PATCH 38/40] Complete fee calculation logic --- src/payments.rs | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/payments.rs b/src/payments.rs index 7173618..238317b 100644 --- a/src/payments.rs +++ b/src/payments.rs @@ -32,33 +32,34 @@ pub fn get_chain_addr_params(chain: &String) -> &'static AddressParams { } } -/// TODO: add comments +/// Function that calculates all the fees accumulated in the duration of a +/// service request in the clientchain fn calculate_fees(request: &Request, client: &OceanClient) -> Result { let mut fee_sum = Amount::ZERO; for i in request.start_blockheight_clientchain..request.end_blockheight_clientchain { let block = client.get_block_info(&client.get_block_hash(i.into())?)?; - // using raw rpc to get asset label - // check also coinbase destination ? - // check is coinbase - // check is correct label - // check ownership - let tx = client.get_raw_transaction_verbose(&block.tx[0], None)?; + let tx = client.get_raw_transaction_verbose(&block.tx[0], None)?; // coinbase tx + assert!(tx.is_coinbase() == true); for txout in tx.vout { - // do label check :) - fee_sum += txout.value; + match txout.assetlabel { + Some(label) => { + // any other label is a policy asset + if label == "CBT" { + fee_sum += txout.value; + } + } + None => fee_sum += txout.value, + } } } Ok(fee_sum) } -/// TODO -fn calculate_bid_payment(fee_amount: &Amount, fee_percentage: u64, num_bids: u64) -> Result { - info!("amount: {}", fee_amount); - let gn_amount = *fee_amount * fee_percentage / 100; - info!("gn_amount: {}", gn_amount); - let gn_amount_per_gn = gn_amount / num_bids; - info!("gn_amount_per_gn: {}", gn_amount_per_gn); - Ok(gn_amount_per_gn) +/// Function that calculates the fee amount to be received per bid given total +/// fees, fee percentage and bid number +fn calculate_bid_payment(fees_amount: &Amount, fee_percentage: u64, num_bids: u64) -> Result { + let total_amount = *fees_amount * fee_percentage / 100; + Ok(total_amount / num_bids) // amount per bid } /// TODO: add comments @@ -70,7 +71,7 @@ pub struct Payments { } impl Payments { - /// TODO + /// TODO: implement payments fn complete_bid_payments(&self, _bids: &mut Vec) -> Result<()> { // pay // set bid txid From 50d10d4d6fde9d6d7ab6eaef33370af2dccbc91c Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Thu, 21 Nov 2019 15:33:02 +0000 Subject: [PATCH 39/40] Complete Payments documentation --- src/payments.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/payments.rs b/src/payments.rs index 238317b..27befe8 100644 --- a/src/payments.rs +++ b/src/payments.rs @@ -62,12 +62,17 @@ fn calculate_bid_payment(fees_amount: &Amount, fee_percentage: u64, num_bids: u6 Ok(total_amount / num_bids) // amount per bid } -/// TODO: add comments +/// Payment Struct holding data and logic required to pay bids at the end of the +/// service request pub struct Payments { - storage: Arc, - config: ClientChainConfig, - client: OceanClient, - addr_params: &'static AddressParams, + /// Thread safe storage instance + pub storage: Arc, + /// Client config required for fee payments + pub config: ClientChainConfig, + /// Ocean rpc connectivity to client chain + pub client: OceanClient, + /// Clientchain address params required for fee payments + pub addr_params: &'static AddressParams, } impl Payments { From aeb5518c79ecbd909aa239a999c32eed47495a4b Mon Sep 17 00:00:00 2001 From: nkostoulas Date: Thu, 21 Nov 2019 15:48:15 +0000 Subject: [PATCH 40/40] Some first tests for Payments --- src/payments.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/payments.rs b/src/payments.rs index 27befe8..7d9ba3e 100644 --- a/src/payments.rs +++ b/src/payments.rs @@ -224,3 +224,55 @@ pub fn run_payments( } })) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn calculate_bid_payment_test() { + assert_eq!( + 1.125, + calculate_bid_payment(&Amount::from_btc(6.0).unwrap(), 75, 4) + .unwrap() + .as_btc() + ); + assert_eq!( + 0.24, + calculate_bid_payment(&Amount::from_btc(4.0).unwrap(), 30, 5) + .unwrap() + .as_btc() + ); + assert_eq!( + 1.0, + calculate_bid_payment(&Amount::from_btc(100.0).unwrap(), 1, 1) + .unwrap() + .as_btc() + ); + assert_eq!( + 0.0, + calculate_bid_payment(&Amount::from_btc(0.0).unwrap(), 1, 1) + .unwrap() + .as_btc() + ); + assert_eq!( + 0.0, + calculate_bid_payment(&Amount::from_btc(4.0).unwrap(), 0, 5) + .unwrap() + .as_btc() + ); + } + + #[test] + fn get_chain_addr_params_test() { + assert_eq!( + &AddressParams::OCEAN, + get_chain_addr_params(&String::from("ocean_main")) + ); + assert_eq!(&AddressParams::GOLD, get_chain_addr_params(&String::from("gold_main"))); + assert_eq!( + &AddressParams::ELEMENTS, + get_chain_addr_params(&String::from("supersilverhazechain")) + ); + } +}