diff options
-rw-r--r-- | src/handlers.rs | 48 | ||||
-rw-r--r-- | src/schema.rs | 7 | ||||
-rw-r--r-- | tests/route_tests.rs | 10 |
3 files changed, 46 insertions, 19 deletions
diff --git a/src/handlers.rs b/src/handlers.rs index c2c8aca..9be9764 100644 --- a/src/handlers.rs +++ b/src/handlers.rs | |||
@@ -19,7 +19,8 @@ use warp::{http::StatusCode, reply}; | |||
19 | 19 | ||
20 | use crate::PRIVATE_KEY; | 20 | use crate::PRIVATE_KEY; |
21 | const BLOCK_TRANSACTION_COUNT: u8 = 10; | 21 | const BLOCK_TRANSACTION_COUNT: u8 = 10; |
22 | const BLOCK_REWARD: u8 = 3; | 22 | const BLOCK_REWARD: u16 = 3; |
23 | const TX_UPPER_LIMIT: u16 = 2; | ||
23 | 24 | ||
24 | // Encryption primitive | 25 | // Encryption primitive |
25 | type Aes128Cbc = Cbc<Aes128, Pkcs7>; | 26 | type Aes128Cbc = Cbc<Aes128, Pkcs7>; |
@@ -341,7 +342,7 @@ pub async fn authorized_propose_block( | |||
341 | 342 | ||
342 | warn!("{:?}", &new_block); | 343 | warn!("{:?}", &new_block); |
343 | 344 | ||
344 | if new_block.transaction_list.is_empty() { | 345 | if new_block.transaction_list.len() != BLOCK_TRANSACTION_COUNT as usize { |
345 | let res_json = warp::reply::json(&GradeCoinResponse { | 346 | let res_json = warp::reply::json(&GradeCoinResponse { |
346 | res: ResponseType::Error, | 347 | res: ResponseType::Error, |
347 | message: format!( | 348 | message: format!( |
@@ -480,7 +481,7 @@ pub async fn authorized_propose_block( | |||
480 | } | 481 | } |
481 | 482 | ||
482 | if let Some(coinbase_user) = users_store.get_mut(coinbase_fingerprint) { | 483 | if let Some(coinbase_user) = users_store.get_mut(coinbase_fingerprint) { |
483 | coinbase_user.balance += BLOCK_REWARD as i32; | 484 | coinbase_user.balance += BLOCK_REWARD; |
484 | } | 485 | } |
485 | } | 486 | } |
486 | 487 | ||
@@ -565,11 +566,10 @@ pub async fn authorized_propose_transaction( | |||
565 | StatusCode::BAD_REQUEST, | 566 | StatusCode::BAD_REQUEST, |
566 | )); | 567 | )); |
567 | } | 568 | } |
568 | } else if new_transaction.by == new_transaction.target | 569 | } |
569 | && new_transaction.source | 570 | |
570 | != "31415926535897932384626433832795028841971693993751058209749445923" | 571 | // Is transaction amount within bounds |
571 | { | 572 | if new_transaction.amount > TX_UPPER_LIMIT { |
572 | // Propose to transact with the bank | ||
573 | return Ok(warp::reply::with_status( | 573 | return Ok(warp::reply::with_status( |
574 | warp::reply::json(&GradeCoinResponse { | 574 | warp::reply::json(&GradeCoinResponse { |
575 | res: ResponseType::Error, | 575 | res: ResponseType::Error, |
@@ -577,6 +577,36 @@ pub async fn authorized_propose_transaction( | |||
577 | }), | 577 | }), |
578 | StatusCode::BAD_REQUEST, | 578 | StatusCode::BAD_REQUEST, |
579 | )); | 579 | )); |
580 | } | ||
581 | |||
582 | if new_transaction.by == new_transaction.source { | ||
583 | // check if user can afford the transaction | ||
584 | if internal_user.balance < new_transaction.amount { | ||
585 | return Ok(warp::reply::with_status( | ||
586 | warp::reply::json(&GradeCoinResponse { | ||
587 | res: ResponseType::Error, | ||
588 | message: | ||
589 | "User does not have enough balance in their account for this transaction" | ||
590 | .to_owned(), | ||
591 | }), | ||
592 | StatusCode::BAD_REQUEST, | ||
593 | )); | ||
594 | } | ||
595 | } else if new_transaction.by == new_transaction.target { | ||
596 | // Only transactions FROM bank could appear here | ||
597 | |||
598 | if new_transaction.source | ||
599 | != "31415926535897932384626433832795028841971693993751058209749445923" | ||
600 | { | ||
601 | return Ok(warp::reply::with_status( | ||
602 | warp::reply::json(&GradeCoinResponse { | ||
603 | res: ResponseType::Error, | ||
604 | message: "Transactions cannot extort Gradecoin from unsuspecting users" | ||
605 | .to_owned(), | ||
606 | }), | ||
607 | StatusCode::BAD_REQUEST, | ||
608 | )); | ||
609 | } | ||
580 | } else { | 610 | } else { |
581 | return Ok(warp::reply::with_status( | 611 | return Ok(warp::reply::with_status( |
582 | warp::reply::json(&GradeCoinResponse { | 612 | warp::reply::json(&GradeCoinResponse { |
@@ -719,7 +749,7 @@ struct UserTemplate<'a> { | |||
719 | 749 | ||
720 | struct DisplayUsers { | 750 | struct DisplayUsers { |
721 | fingerprint: String, | 751 | fingerprint: String, |
722 | balance: i32, | 752 | balance: u16, |
723 | } | 753 | } |
724 | 754 | ||
725 | pub async fn user_list_handler(db: Db) -> Result<impl warp::Reply, warp::Rejection> { | 755 | pub async fn user_list_handler(db: Db) -> Result<impl warp::Reply, warp::Rejection> { |
diff --git a/src/schema.rs b/src/schema.rs index df7b14a..957f0a9 100644 --- a/src/schema.rs +++ b/src/schema.rs | |||
@@ -27,7 +27,7 @@ pub type Fingerprint = String; | |||
27 | fn block_parser(path: String) -> u64 { | 27 | fn block_parser(path: String) -> u64 { |
28 | let end_pos = path.find(".block").unwrap(); | 28 | let end_pos = path.find(".block").unwrap(); |
29 | let block_str = path[9..end_pos].to_string(); | 29 | let block_str = path[9..end_pos].to_string(); |
30 | let block_u64 : u64 = block_str.parse().unwrap(); | 30 | let block_u64: u64 = block_str.parse().unwrap(); |
31 | block_u64 | 31 | block_u64 |
32 | } | 32 | } |
33 | 33 | ||
@@ -51,7 +51,6 @@ fn last_block_content() -> Option<String> { | |||
51 | } | 51 | } |
52 | } | 52 | } |
53 | return Some(blocks[last_block_index].to_str().unwrap().parse().unwrap()); | 53 | return Some(blocks[last_block_index].to_str().unwrap().parse().unwrap()); |
54 | |||
55 | } | 54 | } |
56 | 55 | ||
57 | fn read_block_name() -> io::Result<Vec<PathBuf>> { | 56 | fn read_block_name() -> io::Result<Vec<PathBuf>> { |
@@ -180,7 +179,7 @@ pub struct Transaction { | |||
180 | pub by: Fingerprint, | 179 | pub by: Fingerprint, |
181 | pub source: Fingerprint, | 180 | pub source: Fingerprint, |
182 | pub target: Fingerprint, | 181 | pub target: Fingerprint, |
183 | pub amount: i32, | 182 | pub amount: u16, |
184 | pub timestamp: NaiveDateTime, | 183 | pub timestamp: NaiveDateTime, |
185 | } | 184 | } |
186 | 185 | ||
@@ -238,7 +237,7 @@ impl Default for Block { | |||
238 | pub struct User { | 237 | pub struct User { |
239 | pub user_id: MetuId, | 238 | pub user_id: MetuId, |
240 | pub public_key: String, | 239 | pub public_key: String, |
241 | pub balance: i32, | 240 | pub balance: u16, |
242 | } | 241 | } |
243 | 242 | ||
244 | /// The values are hard coded in [`OUR_STUDENTS`] so MetuId::new() can accept/reject values based on that | 243 | /// The values are hard coded in [`OUR_STUDENTS`] so MetuId::new() can accept/reject values based on that |
diff --git a/tests/route_tests.rs b/tests/route_tests.rs index 3d8b7f4..3125bc8 100644 --- a/tests/route_tests.rs +++ b/tests/route_tests.rs | |||
@@ -80,7 +80,7 @@ FQIDAQAB | |||
80 | source: "31415926535897932384626433832795028841971693993751058209749445923" | 80 | source: "31415926535897932384626433832795028841971693993751058209749445923" |
81 | .to_owned(), | 81 | .to_owned(), |
82 | target: "mock_transaction_source".to_owned(), | 82 | target: "mock_transaction_source".to_owned(), |
83 | amount: 3, | 83 | amount: 2, |
84 | timestamp: chrono::NaiveDate::from_ymd(2021, 04, 13).and_hms(20, 55, 30), | 84 | timestamp: chrono::NaiveDate::from_ymd(2021, 04, 13).and_hms(20, 55, 30), |
85 | }, | 85 | }, |
86 | ); | 86 | ); |
@@ -105,7 +105,7 @@ FQIDAQAB | |||
105 | by: "mock_transaction_source".to_owned(), | 105 | by: "mock_transaction_source".to_owned(), |
106 | source: "mock_transaction_source".to_owned(), | 106 | source: "mock_transaction_source".to_owned(), |
107 | target: "mock_transaction_target".to_owned(), | 107 | target: "mock_transaction_target".to_owned(), |
108 | amount: 25, | 108 | amount: 2, |
109 | timestamp: chrono::NaiveDate::from_ymd(2021, 04, 09).and_hms(14, 30, 00), | 109 | timestamp: chrono::NaiveDate::from_ymd(2021, 04, 09).and_hms(14, 30, 00), |
110 | } | 110 | } |
111 | } | 111 | } |
@@ -114,11 +114,10 @@ FQIDAQAB | |||
114 | by: "mock_transaction_source2".to_owned(), | 114 | by: "mock_transaction_source2".to_owned(), |
115 | source: "mock_transaction_source2".to_owned(), | 115 | source: "mock_transaction_source2".to_owned(), |
116 | target: "mock_transaction_target".to_owned(), | 116 | target: "mock_transaction_target".to_owned(), |
117 | amount: 25, | 117 | amount: 2, |
118 | timestamp: chrono::NaiveDate::from_ymd(2021, 04, 09).and_hms(14, 30, 00), | 118 | timestamp: chrono::NaiveDate::from_ymd(2021, 04, 09).and_hms(14, 30, 00), |
119 | } | 119 | } |
120 | } | 120 | } |
121 | // r#"{"by":"mock_transaction_source","source":"mock_transaction_source","target":"mock_transaction_target","amount":25,"timestamp":"2021-04-09T14:30:00"}"# | ||
122 | 121 | ||
123 | /// Test simple GET request to /transaction, an endpoint that exists | 122 | /// Test simple GET request to /transaction, an endpoint that exists |
124 | /// https://tools.ietf.org/html/rfc7231#section-6.3.1 | 123 | /// https://tools.ietf.org/html/rfc7231#section-6.3.1 |
@@ -137,7 +136,7 @@ FQIDAQAB | |||
137 | 136 | ||
138 | assert_eq!(res.status(), StatusCode::OK); | 137 | assert_eq!(res.status(), StatusCode::OK); |
139 | 138 | ||
140 | let expected_json_body = r#"{"mock_transaction_source":{"by":"mock_transaction_source","source":"31415926535897932384626433832795028841971693993751058209749445923","target":"mock_transaction_source","amount":3,"timestamp":"2021-04-13T20:55:30"}}"#; | 139 | let expected_json_body = r#"{"mock_transaction_source":{"by":"mock_transaction_source","source":"31415926535897932384626433832795028841971693993751058209749445923","target":"mock_transaction_source","amount":2,"timestamp":"2021-04-13T20:55:30"}}"#; |
141 | 140 | ||
142 | assert_eq!(res.body(), expected_json_body); | 141 | assert_eq!(res.body(), expected_json_body); |
143 | } | 142 | } |
@@ -242,7 +241,6 @@ FQIDAQAB | |||
242 | /// the block | 241 | /// the block |
243 | #[tokio::test] | 242 | #[tokio::test] |
244 | async fn post_block_auth_201() { | 243 | async fn post_block_auth_201() { |
245 | println!("Wtf"); | ||
246 | let db = mocked_db(); | 244 | let db = mocked_db(); |
247 | let filter = consensus_routes(db.clone()); | 245 | let filter = consensus_routes(db.clone()); |
248 | 246 | ||