aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/mining.rs2
-rw-r--r--src/handlers.rs13
-rw-r--r--tests/route_tests.rs138
3 files changed, 84 insertions, 69 deletions
diff --git a/examples/mining.rs b/examples/mining.rs
index 1d86a20..e3d1487 100644
--- a/examples/mining.rs
+++ b/examples/mining.rs
@@ -20,7 +20,7 @@ pub fn main() {
20 let counter = Arc::clone(&counter); 20 let counter = Arc::clone(&counter);
21 threads.push(thread::spawn(move || { 21 threads.push(thread::spawn(move || {
22 let mut b = NakedBlock { 22 let mut b = NakedBlock {
23 transaction_list: vec!["e254275".to_owned()], 23 transaction_list: vec!["fingerprint_of_some_guy".to_owned()],
24 nonce: 0, 24 nonce: 0,
25 timestamp: NaiveDate::from_ymd(2021, 04, 13).and_hms(23, 38, 00), 25 timestamp: NaiveDate::from_ymd(2021, 04, 13).and_hms(23, 38, 00),
26 }; 26 };
diff --git a/src/handlers.rs b/src/handlers.rs
index 6305560..bf554ab 100644
--- a/src/handlers.rs
+++ b/src/handlers.rs
@@ -18,7 +18,7 @@ use std::fs;
18use warp::{http::StatusCode, reply}; 18use warp::{http::StatusCode, reply};
19 19
20use crate::PRIVATE_KEY; 20use crate::PRIVATE_KEY;
21const BLOCK_TRANSACTION_COUNT: u8 = 5; 21const BLOCK_TRANSACTION_COUNT: u8 = 1;
22const BLOCK_REWARD: u16 = 3; 22const BLOCK_REWARD: u16 = 3;
23const TX_UPPER_LIMIT: u16 = 2; 23const TX_UPPER_LIMIT: u16 = 2;
24 24
@@ -181,7 +181,7 @@ pub async fn authenticate_user(
181 let auth_plaintext = match cipher.decrypt(&mut buf) { 181 let auth_plaintext = match cipher.decrypt(&mut buf) {
182 Ok(p) => p, 182 Ok(p) => p,
183 Err(err) => { 183 Err(err) => {
184 println!( 184 debug!(
185 "Base64 decoded auth request did not decrypt correctly {:?} {}", 185 "Base64 decoded auth request did not decrypt correctly {:?} {}",
186 &auth_packet, err 186 &auth_packet, err
187 ); 187 );
@@ -342,11 +342,12 @@ pub async fn propose_block(
342 342
343 warn!("New block proposal: {:?}", &new_block); 343 warn!("New block proposal: {:?}", &new_block);
344 344
345 if new_block.transaction_list.len() != BLOCK_TRANSACTION_COUNT as usize { 345 if new_block.transaction_list.len() < BLOCK_TRANSACTION_COUNT as usize {
346 debug!("{} transactions offered, needed {}", new_block.transaction_list.len(), BLOCK_TRANSACTION_COUNT);
346 let res_json = warp::reply::json(&GradeCoinResponse { 347 let res_json = warp::reply::json(&GradeCoinResponse {
347 res: ResponseType::Error, 348 res: ResponseType::Error,
348 message: format!( 349 message: format!(
349 "There should be {} transactions in the block", 350 "There should be at least {} transaction in the block",
350 BLOCK_TRANSACTION_COUNT 351 BLOCK_TRANSACTION_COUNT
351 ), 352 ),
352 }); 353 });
@@ -411,11 +412,11 @@ pub async fn propose_block(
411 proposed_transactions.insert(tx); 412 proposed_transactions.insert(tx);
412 } 413 }
413 414
414 if proposed_transactions.len() != BLOCK_TRANSACTION_COUNT as usize { 415 if proposed_transactions.len() < BLOCK_TRANSACTION_COUNT as usize {
415 let res_json = warp::reply::json(&GradeCoinResponse { 416 let res_json = warp::reply::json(&GradeCoinResponse {
416 res: ResponseType::Error, 417 res: ResponseType::Error,
417 message: format!( 418 message: format!(
418 "Block cannot contain less than {} unique transactions.", 419 "Block cannot contain less than {} unique transaction(s).",
419 BLOCK_TRANSACTION_COUNT 420 BLOCK_TRANSACTION_COUNT
420 ), 421 ),
421 }); 422 });
diff --git a/tests/route_tests.rs b/tests/route_tests.rs
index 6d17368..decc712 100644
--- a/tests/route_tests.rs
+++ b/tests/route_tests.rs
@@ -27,41 +27,52 @@ FQIDAQAB
27 }, 27 },
28 ); 28 );
29 29
30 /*-----BEGIN RSA PRIVATE KEY----- 30 db.users.write().insert(
31 MIIEpAIBAAKCAQEA5yWTMeFqr2nvOC9oR5Wq/nzcNlwCIaziojt7rJ4BBvuwkT0t 31 "fingerprint_of_foo".to_owned(),
32 ERDz8AgvUsaewiB+Fz5OXTeb3WAB1FEXnBXGekrGzvC8jHQMKHyNoWzUlpQJ9UMt 32 User {
33 dQIWPOCuMyLpc+rNPL3428U8UpldjbTHHyq2/ef6abkdj+XWg/slYtrFeOf3ktc1 33 user_id: MetuId::new("e223715".to_owned(), "1H5QuOYI1b2r9ET".to_owned()).unwrap(),
34 l50R4k8VO8L6kQuh2+YIjXGPLShRaqnUQPtH8LFPX4bO9lJ9mAoMZFec6XVwumn/ 34 public_key: "NOT_USED_FOR_THIS_USER".to_owned(),
35 uqu9jyWQL6qh6gtwQHgN+A9wGvzVvltJ9h8sshSHWWtBD0M19ilbXhKyBsHSSZkp 35 balance: 0,
36 x+TAvFhfQ8JURw7KqahUPVlCwJ5OIKccJ/6FFQIDAQABAoIBADTZGnZlG4dPqSon 36 },
37 bKgxSA83bQHgt3wLkyWUhApLdeCq2wvZ+NvWDG/s7yT11IZ991ZJIJGfjTtoIALz 37 );
38 J3rAX8jGH/5gfDuArOb000z9HP3wivZQjawa9gqlNC7s5INkQ9iHdsaIqeoYtpMX 38
39 qg8uLPiQeWiCsoeb/Rff7ARWEKA7udoZ2uZcZFMHTKx+mBpk8IiepQAJPBRVwmXk 39 /*
40 x/3LTaezi6Tkvp/k/gf4IeSICiRGFRmm2Vxciduj11/CrdTHPQLz/Rh5/IN8Bkry 40-----BEGIN RSA PRIVATE KEY-----
41 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
56 -----END RSA PRIVATE KEY-----*/ 56I0+kA1nV1EI+ROegV+b6gs2YaUmMJzI1yLqMqGDgHFxFvhkDsZaI+/V+G9eOLEt4
575ic5tImfZITLE/GSC8b+C16gxMGUN4t9gHq2okMCgYAKyNedaDDFzl3y2wwpP9mo
582sReP3Mm2Tm6lhRUdDt8y/impOZ8kw9E8p8HskP6HncBzoNR98KnhmbIswfrNvfM
59ipVkWOg1IoH6QKUIqfLQM9OfA290Xd+ML89t2Fzq9XnLL3sFDQtwCvIM/YLSQ/jS
60gu7yRkwttzA2NapCQ1h6mQKBgQClwBwn8Qyd01y2mCKkNzsP+2/cqTAbeSNAXFe8
61pMfDowx1+hBu7/7CF+/kPwmQuTa5kSB9PgWsWzYjwNm4OX1j+mbL9lEDLf7tRVWQ
62lydJyz7tmRYzWj6j4V/l/u90M3QgyiqTbCf73GG0AkjaRwHn3dG1gl9A0lZqDvK3
63iQXouwKBgQCrx6SCnEkhLISSZpzdDehtWmyCQJIwcdlRQlAmFLVn+TJHTXR7xUm2
64VpTrPTfaYWx83OQUn/OZqY5gIQ+jlfwqnVg+PDQQ/P09/4xygRCLvjL6NCSvtkj1
65MRArEl4y68+jZLRu74TVG0lXi6ht6KhNHF6GiWKU9FHZ4B+btLicsg==
66-----END RSA PRIVATE KEY-----
67*/
57 68
58 db.pending_transactions.write().insert( 69 db.pending_transactions.write().insert(
59 "mock_transaction_source".to_owned(), 70 "fingerprint_of_foo".to_owned(),
60 Transaction { 71 Transaction {
61 by: "mock_transaction_source".to_owned(), 72 by: "fingerprint_of_foo".to_owned(),
62 source: "31415926535897932384626433832795028841971693993751058209749445923" 73 source: "31415926535897932384626433832795028841971693993751058209749445923"
63 .to_owned(), 74 .to_owned(),
64 target: "mock_transaction_source".to_owned(), 75 target: "fingerprint_of_foo".to_owned(),
65 amount: 2, 76 amount: 2,
66 timestamp: chrono::NaiveDate::from_ymd(2021, 04, 13).and_hms(20, 55, 30), 77 timestamp: chrono::NaiveDate::from_ymd(2021, 04, 13).and_hms(20, 55, 30),
67 }, 78 },
@@ -81,27 +92,6 @@ FQIDAQAB
81 db 92 db
82 } 93 }
83 94
84 /// Create a mock transaction to be used in tests
85 fn mocked_transaction() -> Transaction {
86 Transaction {
87 by: "mock_transaction_source".to_owned(),
88 source: "mock_transaction_source".to_owned(),
89 target: "mock_transaction_target".to_owned(),
90 amount: 2,
91 timestamp: chrono::NaiveDate::from_ymd(2021, 04, 09).and_hms(14, 30, 00),
92 }
93 }
94
95 fn mocked_transaction2() -> Transaction {
96 Transaction {
97 by: "fingerprint_of_some_guy".to_owned(),
98 source: "31415926535897932384626433832795028841971693993751058209749445923".to_owned(),
99 target: "fingerprint_of_some_guy".to_owned(),
100 amount: 2,
101 timestamp: chrono::NaiveDate::from_ymd(2021, 04, 13).and_hms(20, 55, 30),
102 }
103 }
104
105 /// Test simple GET request to /transaction, an endpoint that exists 95 /// Test simple GET request to /transaction, an endpoint that exists
106 /// https://tools.ietf.org/html/rfc7231#section-6.3.1 96 /// https://tools.ietf.org/html/rfc7231#section-6.3.1
107 /// We should get the only pending transaction available in the database as json 97 /// We should get the only pending transaction available in the database as json
@@ -119,7 +109,7 @@ FQIDAQAB
119 109
120 assert_eq!(res.status(), StatusCode::OK); 110 assert_eq!(res.status(), StatusCode::OK);
121 111
122 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"}}"#; 112 let expected_json_body = r#"{"fingerprint_of_foo":{"by":"fingerprint_of_foo","source":"31415926535897932384626433832795028841971693993751058209749445923","target":"fingerprint_of_foo","amount":2,"timestamp":"2021-04-13T20:55:30"}}"#;
123 113
124 assert_eq!(res.body(), expected_json_body); 114 assert_eq!(res.body(), expected_json_body);
125 } 115 }
@@ -176,7 +166,13 @@ FQIDAQAB
176 166
177 let res = warp::test::request() 167 let res = warp::test::request()
178 .method("POST") 168 .method("POST")
179 .json(&mocked_transaction2()) 169 .json(&Transaction {
170 by: "fingerprint_of_some_guy".to_owned(),
171 source: "31415926535897932384626433832795028841971693993751058209749445923".to_owned(),
172 target: "fingerprint_of_some_guy".to_owned(),
173 amount: 2,
174 timestamp: chrono::NaiveDate::from_ymd(2021, 04, 13).and_hms(20, 55, 30),
175 })
180 .header("Authorization", "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGEiOiJiODI4ZmYwNzM5NjFmMDA2YjU3ZmNkZWMwNmEwZTY1YSIsImV4cCI6MjAwMDAwMDAwMCwiaWF0IjoyNTE2MjM5MDIyfQ.Zwr2BPYzxvdAy8ZjCWSA3dp96KKVHjRDu9imHKCJ0NUeD5fM4D678B6pRZk9ev8PvbEI88MgYVW9akj_IsFwrsho7Tpsh7ym593ZOMwtSWSxxzxuKuGhAuKHDiQlXMFfv6kl8-eXIxa7xbV_0m81vAz6_vYQnVnlhjRQ26LogJRixWpUKV7-mPdRHhrK6dUxi9CwVuc9fdYhd6n2FMKT2AlAnk472fDa3G1oPsFLkp56eJ6_rKWrALHFWItfNvY4zFvwXXyNjMu-0EYJiaQIXFVNnipsy5Sy2HckdY3UiYS2lFUwHIczNrdrLM7NQhJQmbJLD6XRAMifH6bA1ZxH8A") 176 .header("Authorization", "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGEiOiJiODI4ZmYwNzM5NjFmMDA2YjU3ZmNkZWMwNmEwZTY1YSIsImV4cCI6MjAwMDAwMDAwMCwiaWF0IjoyNTE2MjM5MDIyfQ.Zwr2BPYzxvdAy8ZjCWSA3dp96KKVHjRDu9imHKCJ0NUeD5fM4D678B6pRZk9ev8PvbEI88MgYVW9akj_IsFwrsho7Tpsh7ym593ZOMwtSWSxxzxuKuGhAuKHDiQlXMFfv6kl8-eXIxa7xbV_0m81vAz6_vYQnVnlhjRQ26LogJRixWpUKV7-mPdRHhrK6dUxi9CwVuc9fdYhd6n2FMKT2AlAnk472fDa3G1oPsFLkp56eJ6_rKWrALHFWItfNvY4zFvwXXyNjMu-0EYJiaQIXFVNnipsy5Sy2HckdY3UiYS2lFUwHIczNrdrLM7NQhJQmbJLD6XRAMifH6bA1ZxH8A")
181 .path("/transaction") 177 .path("/transaction")
182 .reply(&filter) 178 .reply(&filter)
@@ -203,7 +199,13 @@ FQIDAQAB
203 199
204 let res = warp::test::request() 200 let res = warp::test::request()
205 .method("POST") 201 .method("POST")
206 .json(&mocked_transaction()) 202 .json(&Transaction {
203 by: "some_fingerprint".to_owned(),
204 source: "some_fingerprint".to_owned(),
205 target: "some_other_fingerprint".to_owned(),
206 amount: 2,
207 timestamp: chrono::NaiveDate::from_ymd(2021, 04, 09).and_hms(14, 30, 00),
208 })
207 .header( 209 .header(
208 "Authorization", 210 "Authorization",
209 "Bearer aaaaaaaasdlkjaldkasljdaskjlaaaaaaaaaaaaaa", 211 "Bearer aaaaaaaasdlkjaldkasljdaskjlaaaaaaaaaaaaaa",
@@ -227,25 +229,37 @@ FQIDAQAB
227 let db = mocked_db(); 229 let db = mocked_db();
228 let filter = consensus_routes(db.clone()); 230 let filter = consensus_routes(db.clone());
229 231
232 db.pending_transactions.write().insert(
233 "fingerprint_of_some_guy".to_owned(),
234 Transaction {
235 by: "fingerprint_of_some_guy".to_owned(),
236 source: "31415926535897932384626433832795028841971693993751058209749445923"
237 .to_owned(),
238 target: "fingerprint_of_some_guy".to_owned(),
239 amount: 2,
240 timestamp: chrono::NaiveDate::from_ymd(2021, 04, 13).and_hms(20, 55, 30),
241 },
242 );
243
230 let res = warp::test::request() 244 let res = warp::test::request()
231 .method("POST") 245 .method("POST")
232 .json(&Block { 246 .json(&Block {
233 transaction_list: vec!["fingerprint_of_some_guy".to_owned(),"mock_transaction_source2".to_owned(), "mock_transaction_source3".to_owned(), "mock_transaction_source".to_owned(), "mock_transaction_source".to_owned()], 247 transaction_list: vec!["fingerprint_of_some_guy".to_owned()],
234 nonce: 2686215, 248 nonce: 3222170950,
235 timestamp: chrono::NaiveDate::from_ymd(2021, 04, 13).and_hms(23, 38, 00), 249 timestamp: chrono::NaiveDate::from_ymd(2021, 04, 13).and_hms(23, 38, 00),
236 hash: "0000007c52e4486359f62b2d19781fafaf059bd691bc6d835b666f6eac1d01d9".to_owned(), 250 hash: "0000002149b72e0b348c32ac442a50ced4efbd1df7d48b377733d55dfe4f3577".to_owned(),
237 } ) 251 } )
238 .header("Authorization", "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGEiOiIwMDAwMDA3YzUyZTQ0ODYzNTlmNjJiMmQxOTc4MWZhZmFmMDU5YmQ2OTFiYzZkODM1YjY2NmY2ZWFjMWQwMWQ5IiwiaWF0IjoxMDAwMDAwMDAwMCwiZXhwIjoxMDkwMDAwMDAwMH0.JrzYlamBnT3qcjttzLTLXpiO5qfBu1e2HjQWueJ8l__aas6I1xq77UO8kCWn2Sm-zwUOI_155Pbd4xAqL6pokjLHZSFnAi9ZJ8cpqgw4ZXdI-Z3tDpZMUSiI018CGMZQZ_BwdGDIBbjEy0P-MX590DW9ofLVZckJKoXU5fFYi47OBegh4-8cchco_Z4wDPVamyhZXo8YmIN_ioSQNBQT2gNJnWsVvsXAQ7IdX9fhwS19t1kdnyk_WlezGbkrQ5xW-XAs4qMCgybbW9ErRwIruxI0PLlILFw2-m-UtH7fGdSIAaG-q6gKy79rPQLEE2kI9I39SVdIfMTadfnu6bduag") 252 .header("Authorization", "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0aGEiOiIwMDAwMDAyMTQ5YjcyZTBiMzQ4YzMyYWM0NDJhNTBjZWQ0ZWZiZDFkZjdkNDhiMzc3NzMzZDU1ZGZlNGYzNTc3IiwiZXhwIjoxMDAwMDAwMDAwMCwiaWF0IjoxNTE2MjM5MDAyMn0.2hZkIZiOJ9DpHwzL_rTCHGkTxs0S_-KD58a2bXuICogjrW6Z3o9LaJ95d8kpXSrAUCaFWN_-TNbk26LczDFSAhtTxpPh6ELXyLN82wAOCjsp8qLgXJQCnqNY7VFZdRUW0HDwHBLY2PVH40wprPkF7mLLonUPKcJUg9TLnmqHGriSECgv2-XZt2mD9XdTkofqIR-JRR3qoErb4G4xemMNYlWMuJK8I66Vj8kNytSt4wSCzkrWfmk5yyi7q1N3beo4nkP0DKzVstXZzWjn_qMZNZulfOdrNiKwHpwqX_bL66LB0rVpKcI5f6N6w5GZBKsdeUly7dCtKbxwYX3mV-7I_g")
239 .path("/block") 253 .path("/block")
240 .reply(&filter) 254 .reply(&filter)
241 .await; 255 .await;
242 256
243 println!("ISSUE: {:?}", res.body()); 257 println!("RESPONSE: {:?}", res.body());
244 258
245 // should be reflectled on the db as well 259 // should be reflectled on the db as well
246 assert_eq!( 260 assert_eq!(
247 db.blockchain.read().hash, 261 db.blockchain.read().hash,
248 "0000007c52e4486359f62b2d19781fafaf059bd691bc6d835b666f6eac1d01d9".to_owned() 262 "0000002149b72e0b348c32ac442a50ced4efbd1df7d48b377733d55dfe4f3577".to_owned()
249 ); 263 );
250 assert_eq!(res.status(), StatusCode::CREATED); 264 assert_eq!(res.status(), StatusCode::CREATED);
251 } 265 }