From 9ead8e1ffa7bc8619aa7a1fd5802538ed927581e Mon Sep 17 00:00:00 2001 From: Yigit Sever Date: Sat, 17 Apr 2021 19:47:39 +0300 Subject: Implement block/tx bounds --- src/handlers.rs | 48 +++++++++++++++++++++++++++++++++++++++--------- src/schema.rs | 7 +++---- 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}; use crate::PRIVATE_KEY; const BLOCK_TRANSACTION_COUNT: u8 = 10; -const BLOCK_REWARD: u8 = 3; +const BLOCK_REWARD: u16 = 3; +const TX_UPPER_LIMIT: u16 = 2; // Encryption primitive type Aes128Cbc = Cbc; @@ -341,7 +342,7 @@ pub async fn authorized_propose_block( warn!("{:?}", &new_block); - if new_block.transaction_list.is_empty() { + if new_block.transaction_list.len() != BLOCK_TRANSACTION_COUNT as usize { let res_json = warp::reply::json(&GradeCoinResponse { res: ResponseType::Error, message: format!( @@ -480,7 +481,7 @@ pub async fn authorized_propose_block( } if let Some(coinbase_user) = users_store.get_mut(coinbase_fingerprint) { - coinbase_user.balance += BLOCK_REWARD as i32; + coinbase_user.balance += BLOCK_REWARD; } } @@ -565,11 +566,10 @@ pub async fn authorized_propose_transaction( StatusCode::BAD_REQUEST, )); } - } else if new_transaction.by == new_transaction.target - && new_transaction.source - != "31415926535897932384626433832795028841971693993751058209749445923" - { - // Propose to transact with the bank + } + + // Is transaction amount within bounds + if new_transaction.amount > TX_UPPER_LIMIT { return Ok(warp::reply::with_status( warp::reply::json(&GradeCoinResponse { res: ResponseType::Error, @@ -577,6 +577,36 @@ pub async fn authorized_propose_transaction( }), StatusCode::BAD_REQUEST, )); + } + + if new_transaction.by == new_transaction.source { + // check if user can afford the transaction + if internal_user.balance < new_transaction.amount { + return Ok(warp::reply::with_status( + warp::reply::json(&GradeCoinResponse { + res: ResponseType::Error, + message: + "User does not have enough balance in their account for this transaction" + .to_owned(), + }), + StatusCode::BAD_REQUEST, + )); + } + } else if new_transaction.by == new_transaction.target { + // Only transactions FROM bank could appear here + + if new_transaction.source + != "31415926535897932384626433832795028841971693993751058209749445923" + { + return Ok(warp::reply::with_status( + warp::reply::json(&GradeCoinResponse { + res: ResponseType::Error, + message: "Transactions cannot extort Gradecoin from unsuspecting users" + .to_owned(), + }), + StatusCode::BAD_REQUEST, + )); + } } else { return Ok(warp::reply::with_status( warp::reply::json(&GradeCoinResponse { @@ -719,7 +749,7 @@ struct UserTemplate<'a> { struct DisplayUsers { fingerprint: String, - balance: i32, + balance: u16, } pub async fn user_list_handler(db: Db) -> Result { 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; fn block_parser(path: String) -> u64 { let end_pos = path.find(".block").unwrap(); let block_str = path[9..end_pos].to_string(); - let block_u64 : u64 = block_str.parse().unwrap(); + let block_u64: u64 = block_str.parse().unwrap(); block_u64 } @@ -51,7 +51,6 @@ fn last_block_content() -> Option { } } return Some(blocks[last_block_index].to_str().unwrap().parse().unwrap()); - } fn read_block_name() -> io::Result> { @@ -180,7 +179,7 @@ pub struct Transaction { pub by: Fingerprint, pub source: Fingerprint, pub target: Fingerprint, - pub amount: i32, + pub amount: u16, pub timestamp: NaiveDateTime, } @@ -238,7 +237,7 @@ impl Default for Block { pub struct User { pub user_id: MetuId, pub public_key: String, - pub balance: i32, + pub balance: u16, } /// 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 source: "31415926535897932384626433832795028841971693993751058209749445923" .to_owned(), target: "mock_transaction_source".to_owned(), - amount: 3, + amount: 2, timestamp: chrono::NaiveDate::from_ymd(2021, 04, 13).and_hms(20, 55, 30), }, ); @@ -105,7 +105,7 @@ FQIDAQAB by: "mock_transaction_source".to_owned(), source: "mock_transaction_source".to_owned(), target: "mock_transaction_target".to_owned(), - amount: 25, + amount: 2, timestamp: chrono::NaiveDate::from_ymd(2021, 04, 09).and_hms(14, 30, 00), } } @@ -114,11 +114,10 @@ FQIDAQAB by: "mock_transaction_source2".to_owned(), source: "mock_transaction_source2".to_owned(), target: "mock_transaction_target".to_owned(), - amount: 25, + amount: 2, timestamp: chrono::NaiveDate::from_ymd(2021, 04, 09).and_hms(14, 30, 00), } } - // r#"{"by":"mock_transaction_source","source":"mock_transaction_source","target":"mock_transaction_target","amount":25,"timestamp":"2021-04-09T14:30:00"}"# /// Test simple GET request to /transaction, an endpoint that exists /// https://tools.ietf.org/html/rfc7231#section-6.3.1 @@ -137,7 +136,7 @@ FQIDAQAB assert_eq!(res.status(), StatusCode::OK); - 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"}}"#; + 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"}}"#; assert_eq!(res.body(), expected_json_body); } @@ -242,7 +241,6 @@ FQIDAQAB /// the block #[tokio::test] async fn post_block_auth_201() { - println!("Wtf"); let db = mocked_db(); let filter = consensus_routes(db.clone()); -- cgit v1.2.3-70-g09d2