diff options
author | Yigit Sever | 2021-04-07 04:33:45 +0300 |
---|---|---|
committer | Yigit Sever | 2021-04-07 04:35:44 +0300 |
commit | 20dad7d4290f2c98583168cd4b9afcdec4802944 (patch) | |
tree | b761b56e8b629d8a295b4dd7ca55a5d7745fd4c6 /src/handlers.rs | |
parent | 95ff6371303ac28d05b25fd9f6e436c5d0a58d4c (diff) | |
download | gradecoin-20dad7d4290f2c98583168cd4b9afcdec4802944.tar.gz gradecoin-20dad7d4290f2c98583168cd4b9afcdec4802944.tar.bz2 gradecoin-20dad7d4290f2c98583168cd4b9afcdec4802944.zip |
Implement Block GET/PUT with new schema
- `Arc`+`Mutex` is replaced by `parking_lot::RwLock,` decoupled
Read+Write and ability to upgrade read locks into write locks if
needed
- Schema has changed, `Db` is now a struct that implements `new()` to
return a new instance of itself, pros/cons listed in code but tl;dr
blockchain and pending transactions are separate now
- `custom_filters` now supports extracting Block json and Transaction
json in separate functions too
- /block GET and PUT implemented, `Blocks` currently have one check
(transactions appear in pending transaction)
- debug is working after something, dunno how I fixed it
Diffstat (limited to 'src/handlers.rs')
-rw-r--r-- | src/handlers.rs | 94 |
1 files changed, 71 insertions, 23 deletions
diff --git a/src/handlers.rs b/src/handlers.rs index 51c7b63..ecf5a92 100644 --- a/src/handlers.rs +++ b/src/handlers.rs | |||
@@ -1,45 +1,93 @@ | |||
1 | // API handlers, the ends of each filter chain | 1 | /// API handlers, the ends of each filter chain |
2 | 2 | use log::debug; // this is more useful than debug! learn how to use this | |
3 | use log::debug; | 3 | use parking_lot::RwLockUpgradableReadGuard; |
4 | use std::convert::Infallible; | 4 | use std::convert::Infallible; |
5 | use warp::{http::StatusCode, reply}; | 5 | use warp::{http::StatusCode, reply}; |
6 | 6 | ||
7 | use crate::schema::{Db, Transaction}; // `Block` coming later | 7 | use crate::schema::{Block, Db, Transaction}; |
8 | |||
9 | /// GET /transaction | ||
10 | /// Returns JSON array of transactions | ||
11 | /// Cannot fail | ||
12 | pub async fn list_transactions(db: Db) -> Result<impl warp::Reply, Infallible> { | ||
13 | debug!("list all transactions"); | ||
14 | let mut result = Vec::new(); | ||
15 | |||
16 | let transactions = db.pending_transactions.read(); | ||
17 | // let transactions = transactions.clone().into_iter().collect(); | ||
18 | |||
19 | for (_, value) in transactions.iter() { | ||
20 | result.push(value) | ||
21 | } | ||
22 | |||
23 | Ok(reply::with_status(reply::json(&result), StatusCode::OK)) | ||
24 | } | ||
25 | |||
26 | /// GET /block | ||
27 | /// Returns JSON array of blocks | ||
28 | /// Cannot fail | ||
29 | /// Mostly around for debug purposes | ||
30 | pub async fn list_blocks(db: Db) -> Result<impl warp::Reply, Infallible> { | ||
31 | debug!("list all blocks"); | ||
32 | |||
33 | let mut result = Vec::new(); | ||
34 | let blocks = db.blockchain.read(); | ||
35 | |||
36 | for block in blocks.iter() { | ||
37 | result.push(block); | ||
38 | } | ||
8 | 39 | ||
9 | // PROPOSE Transaction | 40 | Ok(reply::with_status(reply::json(&result), StatusCode::OK)) |
10 | // POST /transaction | 41 | } |
42 | |||
43 | /// POST /transaction | ||
44 | /// Pushes a new transaction for pending transaction pool | ||
45 | /// Can reject the transaction proposal | ||
46 | /// TODO: when is a new transaction rejected <07-04-21, yigit> // | ||
11 | pub async fn propose_transaction( | 47 | pub async fn propose_transaction( |
12 | new_transaction: Transaction, | 48 | new_transaction: Transaction, |
13 | db: Db, | 49 | db: Db, |
14 | ) -> Result<impl warp::Reply, warp::Rejection> { | 50 | ) -> Result<impl warp::Reply, warp::Rejection> { |
15 | debug!("new transaction request {:?}", new_transaction); | 51 | debug!("new transaction request {:?}", new_transaction); |
16 | 52 | ||
17 | let mut transactions = db.lock().await; | 53 | // let mut transactions = db.lock().await; |
54 | let mut transactions = db.pending_transactions.write(); | ||
18 | 55 | ||
19 | transactions.push(new_transaction); | 56 | transactions.insert(new_transaction.source.to_owned(), new_transaction); |
20 | 57 | ||
21 | Ok(StatusCode::CREATED) | 58 | Ok(StatusCode::CREATED) |
22 | } | 59 | } |
23 | 60 | ||
24 | // GET Transaction List | 61 | /// POST /block |
25 | // GET /transaction | 62 | /// Proposes a new block for the next round |
26 | // Returns JSON array of transactions | 63 | /// Can reject the block |
27 | // Cannot fail? | 64 | pub async fn propose_block(new_block: Block, db: Db) -> Result<impl warp::Reply, warp::Rejection> { |
28 | pub async fn list_transactions(db: Db) -> Result<impl warp::Reply, Infallible> { | 65 | debug!("new block request {:?}", new_block); |
29 | debug!("list all transactions"); | ||
30 | 66 | ||
31 | let transactions = db.lock().await; | 67 | // https://blog.logrocket.com/create-an-async-crud-web-service-in-rust-with-warp/ (this has |
68 | // error.rs, error struct, looks very clean) | ||
32 | 69 | ||
33 | let transactions: Vec<Transaction> = transactions.clone().into_iter().collect(); | 70 | let pending_transactions = db.pending_transactions.upgradable_read(); |
71 | let blockchain = db.blockchain.upgradable_read(); | ||
34 | 72 | ||
35 | Ok(reply::with_status( | 73 | // TODO: check 1, new_block.transaction_list from pending_transactions pool? <07-04-21, yigit> // |
36 | reply::json(&transactions), | 74 | for transaction_hash in new_block.transaction_list.iter() { |
37 | StatusCode::OK, | 75 | if !pending_transactions.contains_key(transaction_hash) { |
38 | )) | 76 | return Ok(StatusCode::BAD_REQUEST); |
39 | } | 77 | } |
78 | } | ||
40 | 79 | ||
41 | // PROPOSE Block | 80 | // TODO: check 2, block hash (\w nonce) asserts $hash_condition? <07-04-21, yigit> // |
42 | // POST /block | 81 | // assume it is for now |
82 | |||
83 | let mut blockchain = RwLockUpgradableReadGuard::upgrade(blockchain); | ||
84 | blockchain.push(new_block); | ||
85 | |||
86 | let mut pending_transactions = RwLockUpgradableReadGuard::upgrade(pending_transactions); | ||
87 | pending_transactions.clear(); | ||
88 | |||
89 | Ok(StatusCode::CREATED) | ||
90 | } | ||
43 | 91 | ||
44 | // `GET /games` | 92 | // `GET /games` |
45 | // Returns JSON array of todos | 93 | // Returns JSON array of todos |