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 |
