diff options
Diffstat (limited to 'src/schema.rs')
| -rw-r--r-- | src/schema.rs | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/src/schema.rs b/src/schema.rs index 39921b8..4eb2f0a 100644 --- a/src/schema.rs +++ b/src/schema.rs | |||
| @@ -1,3 +1,12 @@ | |||
| 1 | //! # Data Representations | ||
| 2 | //! | ||
| 3 | //! We need persistence for [`Block`]s and [`User`]s, not so much for [`Transaction`]s | ||
| 4 | //! | ||
| 5 | //! There are around 30 students, a full fledged database would be an overkill (for next year?) | ||
| 6 | //! | ||
| 7 | //! Pending transactions are held in memory, these are cleared with every new block | ||
| 8 | //! Only the last block is held in memory, every block is written to a file | ||
| 9 | //! Users are held in memory and they're also backed up to text files | ||
| 1 | use chrono::{NaiveDate, NaiveDateTime}; | 10 | use chrono::{NaiveDate, NaiveDateTime}; |
| 2 | use lazy_static::lazy_static; | 11 | use lazy_static::lazy_static; |
| 3 | use parking_lot::RwLock; | 12 | use parking_lot::RwLock; |
| @@ -9,24 +18,45 @@ use std::sync::Arc; | |||
| 9 | 18 | ||
| 10 | // use crate::validators; | 19 | // use crate::validators; |
| 11 | 20 | ||
| 12 | /// We need persistence for blocks and users, not so much for transactions | 21 | pub type PublicKeySignature = String; |
| 13 | /// There are around 30 students, a full fledged database would be an overkill (for next year?) | ||
| 14 | /// Pending transactions are held in memory, these are cleared with every new block | ||
| 15 | /// Only the last block is held in memory, every block is written to a file | ||
| 16 | /// Users are held in memory and they're also backed up to text files | ||
| 17 | 22 | ||
| 18 | /// Creates a new database connection | 23 | /// Creates a new database |
| 19 | pub fn create_database() -> Db { | 24 | pub fn create_database() -> Db { |
| 20 | fs::create_dir_all("blocks").unwrap(); | 25 | fs::create_dir_all("blocks").unwrap(); |
| 21 | fs::create_dir_all("users").unwrap(); | 26 | fs::create_dir_all("users").unwrap(); |
| 22 | Db::new() | 27 | Db::new() |
| 23 | } | 28 | } |
| 24 | 29 | ||
| 30 | /// A JWT Payload/Claims representation | ||
| 31 | /// | ||
| 32 | /// https://tools.ietf.org/html/rfc7519#section-4.1 | ||
| 33 | /// | ||
| 34 | /// - `tha`: Transaction Hash, String (custom field) | ||
| 35 | /// - `iat`: Issued At, Unix Time, epoch | ||
| 36 | /// - `exp`: Expiration Time, epoch | ||
| 37 | #[derive(Debug, Serialize, Deserialize)] | ||
| 38 | pub struct Claims { | ||
| 39 | pub tha: String, | ||
| 40 | pub iat: usize, | ||
| 41 | pub exp: usize, | ||
| 42 | } | ||
| 43 | |||
| 44 | /// Global Database representation | ||
| 45 | /// | ||
| 46 | /// [`blockchain`] is just the last block that was mined. All the blocks are written to disk as text | ||
| 47 | /// files whenever they are accepted. | ||
| 48 | /// | ||
| 49 | /// [`pending_transactions`] is the in memory representation of the waiting transactions. Every | ||
| 50 | /// user can have only one outstanding transaction at any given time. | ||
| 51 | /// | ||
| 52 | /// [`users`] is the in memory representation of the users, with their public keys, metu_ids and | ||
| 53 | /// gradecoin balances. | ||
| 54 | /// | ||
| 55 | /// TODO: Replace the pending_transactions HashMap<String, Transaction> with | ||
| 56 | /// HashMap<PublicKeySignature, Transaction> | ||
| 25 | #[derive(Debug, Clone)] | 57 | #[derive(Debug, Clone)] |
| 26 | pub struct Db { | 58 | pub struct Db { |
| 27 | // heh. also https://doc.rust-lang.org/std/collections/struct.LinkedList.html says Vec is generally faster | ||
| 28 | pub blockchain: Arc<RwLock<Block>>, | 59 | pub blockchain: Arc<RwLock<Block>>, |
| 29 | // every proposer can have _one_ pending transaction, a way to enforce this, String is proposer identifier | ||
| 30 | pub pending_transactions: Arc<RwLock<HashMap<String, Transaction>>>, | 60 | pub pending_transactions: Arc<RwLock<HashMap<String, Transaction>>>, |
| 31 | pub users: Arc<RwLock<HashMap<String, User>>>, | 61 | pub users: Arc<RwLock<HashMap<String, User>>>, |
| 32 | } | 62 | } |
| @@ -41,8 +71,6 @@ impl Db { | |||
| 41 | } | 71 | } |
| 42 | } | 72 | } |
| 43 | 73 | ||
| 44 | pub type PublicKeySignature = String; | ||
| 45 | |||
| 46 | /// A transaction between `source` and `target` that moves `amount` | 74 | /// A transaction between `source` and `target` that moves `amount` |
| 47 | #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] | 75 | #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] |
| 48 | pub struct Transaction { | 76 | pub struct Transaction { |
| @@ -53,20 +81,21 @@ pub struct Transaction { | |||
| 53 | pub timestamp: NaiveDateTime, | 81 | pub timestamp: NaiveDateTime, |
| 54 | } | 82 | } |
| 55 | 83 | ||
| 56 | /// A block that was proposed with `transaction_list` and `nonce` that made `hash` valid | 84 | /// A block that was proposed with `transaction_list` and `nonce` that made `hash` valid, 6 zeroes |
| 85 | /// at the right hand side of the hash (24 bytes) | ||
| 86 | /// | ||
| 87 | /// We are mining using blake2s algorithm, which produces 256 bit hashes. Hash/second is roughly | ||
| 88 | /// 20x10^3. | ||
| 89 | /// | ||
| 57 | /// https://serde.rs/container-attrs.html might be valuable to normalize the serialize/deserialize | 90 | /// https://serde.rs/container-attrs.html might be valuable to normalize the serialize/deserialize |
| 58 | /// conventions as these will be hashed | 91 | /// conventions as these will be hashed |
| 92 | /// | ||
| 59 | #[derive(Serialize, Deserialize, Debug)] | 93 | #[derive(Serialize, Deserialize, Debug)] |
| 60 | pub struct Block { | 94 | pub struct Block { |
| 61 | // TODO: transaction list should hold transaction hash values <09-04-21, yigit> // | 95 | pub transaction_list: Vec<PublicKeySignature>, |
| 62 | // but do we link them somehow? (like a log of old transactions?) | ||
| 63 | // we can leave this as is and whenever we have a new block we _could_ just log it to file | ||
| 64 | // somewhere | ||
| 65 | // I want to keep this as a String vector because it makes things easier elsewhere | ||
| 66 | pub transaction_list: Vec<PublicKeySignature>, // hashes of the transactions (or just "source" for now) | ||
| 67 | pub nonce: u32, | 96 | pub nonce: u32, |
| 68 | pub timestamp: NaiveDateTime, | 97 | pub timestamp: NaiveDateTime, |
| 69 | pub hash: String, // future proof'd baby | 98 | pub hash: String, |
| 70 | } | 99 | } |
| 71 | 100 | ||
| 72 | /// For prototyping and letting serde handle everything json | 101 | /// For prototyping and letting serde handle everything json |
| @@ -89,7 +118,7 @@ impl Block { | |||
| 89 | } | 118 | } |
| 90 | } | 119 | } |
| 91 | 120 | ||
| 92 | /// Or simply a Student | 121 | /// Simply a Student |
| 93 | #[derive(Serialize, Deserialize, Debug)] | 122 | #[derive(Serialize, Deserialize, Debug)] |
| 94 | pub struct User { | 123 | pub struct User { |
| 95 | pub user_id: MetuId, | 124 | pub user_id: MetuId, |
| @@ -103,6 +132,7 @@ pub struct MetuId { | |||
| 103 | id: String, | 132 | id: String, |
| 104 | } | 133 | } |
| 105 | 134 | ||
| 135 | // TODO: this will arrive encrypted <13-04-21, yigit> // | ||
| 106 | #[derive(Serialize, Deserialize, Debug)] | 136 | #[derive(Serialize, Deserialize, Debug)] |
| 107 | pub struct AuthRequest { | 137 | pub struct AuthRequest { |
| 108 | pub student_id: String, | 138 | pub student_id: String, |
