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/schema.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/schema.rs')
| -rw-r--r-- | src/schema.rs | 65 |
1 files changed, 45 insertions, 20 deletions
diff --git a/src/schema.rs b/src/schema.rs index ea36a70..57210a3 100644 --- a/src/schema.rs +++ b/src/schema.rs | |||
| @@ -1,31 +1,46 @@ | |||
| 1 | // Common types used across API | 1 | use chrono::NaiveDateTime; |
| 2 | 2 | use parking_lot::RwLock; | |
| 3 | use chrono::{NaiveDate, NaiveDateTime}; | ||
| 4 | use serde::{Deserialize, Serialize}; | 3 | use serde::{Deserialize, Serialize}; |
| 4 | use std::collections::HashMap; | ||
| 5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
| 6 | use tokio::sync::Mutex; | ||
| 7 | 6 | ||
| 8 | // use crate::validators; | 7 | // use crate::validators; |
| 9 | 8 | ||
| 10 | pub fn ledger() -> Db { | 9 | // In memory data structure |
| 11 | // TODO: there was something simpler in one of the other tutorials? <07-04-21, yigit> // | 10 | |
| 12 | 11 | // Two approaches here | |
| 13 | Arc::new(Mutex::new(vec![ | 12 | // 1. Db is a type |
| 14 | Transaction { | 13 | // pub type Db = Arc<RwLock<Vec<Ledger>>>; |
| 15 | source: String::from("Myself"), | 14 | // Ledger is a struct, we wrap the ledger with arc + mutex in ledger() |
| 16 | target: String::from("Nobody"), | 15 | // to access transactions we need to unwrap blocks as well, vice versa |
| 17 | amount: 4, | 16 | // |
| 18 | timestamp: NaiveDate::from_ymd(2021, 4, 7).and_hms(00, 17, 00), | 17 | // 2. Db is a struct, attributes are wrapped |
| 19 | }, | 18 | // we can offload ::new() to it's member method |
| 20 | ])) | 19 | // blocks and transactions are accessible separately, which is the biggest pro |
| 20 | |||
| 21 | /// Creates a new database | ||
| 22 | pub fn create_database() -> Db { | ||
| 23 | Db::new() | ||
| 21 | } | 24 | } |
| 22 | 25 | ||
| 26 | #[derive(Debug, Clone)] | ||
| 27 | pub struct Db { | ||
| 28 | // heh. also https://doc.rust-lang.org/std/collections/struct.LinkedList.html says Vec is generally faster | ||
| 29 | pub blockchain: Arc<RwLock<Vec<Block>>>, | ||
| 30 | // every proposer can have _one_ pending transaction, a way to enforce this, String is proposer identifier | ||
| 31 | pub pending_transactions: Arc<RwLock<HashMap<String, Transaction>>>, | ||
| 32 | } | ||
| 23 | 33 | ||
| 24 | // For presentation purposes keep mocked data in in-memory structure | 34 | impl Db { |
| 25 | // In real life scenario connection with regular database would be established | 35 | fn new() -> Self { |
| 26 | 36 | Db { | |
| 27 | pub type Db = Arc<Mutex<Vec<Transaction>>>; | 37 | blockchain: Arc::new(RwLock::new(Vec::new())), |
| 38 | pending_transactions: Arc::new(RwLock::new(HashMap::new())), | ||
| 39 | } | ||
| 40 | } | ||
| 41 | } | ||
| 28 | 42 | ||
| 43 | /// A transaction between `source` and `target` that moves `amount` | ||
| 29 | #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] | 44 | #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] |
| 30 | pub struct Transaction { | 45 | pub struct Transaction { |
| 31 | pub source: String, | 46 | pub source: String, |
| @@ -34,14 +49,22 @@ pub struct Transaction { | |||
| 34 | pub timestamp: NaiveDateTime, | 49 | pub timestamp: NaiveDateTime, |
| 35 | } | 50 | } |
| 36 | 51 | ||
| 52 | /// A block that was proposed with `transaction_list` and `nonce` that made `hash` valid | ||
| 37 | #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] | 53 | #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] |
| 38 | pub struct Block { | 54 | pub struct Block { |
| 39 | pub transaction_list: Vec<Transaction>, // [Transaction; N] | 55 | pub transaction_list: Vec<String>, // hashes of the transactions (or just "source" for now) |
| 40 | pub nonce: i32, | 56 | pub nonce: i32, |
| 41 | pub timestamp: NaiveDateTime, | 57 | pub timestamp: NaiveDateTime, |
| 42 | pub hash: String, // future proof'd baby | 58 | pub hash: String, // future proof'd baby |
| 43 | } | 59 | } |
| 44 | 60 | ||
| 61 | // pub struct Ledger { | ||
| 62 | // // heh. also https://doc.rust-lang.org/std/collections/struct.LinkedList.html says Vec is generally faster | ||
| 63 | // blockchain: Vec<Block>, | ||
| 64 | // // every proposer can have _one_ pending transaction, a way to enforce this, String is proposer identifier | ||
| 65 | // pending_transactions: HashMap<String, Transaction>, | ||
| 66 | // } | ||
| 67 | |||
| 45 | // #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] | 68 | // #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] |
| 46 | // #[serde(rename_all = "camelCase")] | 69 | // #[serde(rename_all = "camelCase")] |
| 47 | // pub struct Game { | 70 | // pub struct Game { |
| @@ -99,6 +122,8 @@ pub struct Block { | |||
| 99 | // )) | 122 | // )) |
| 100 | // } | 123 | // } |
| 101 | 124 | ||
| 125 | // TODO: these tests are amazing, we should write some when schema is decided upon <07-04-21, yigit> // | ||
| 126 | |||
| 102 | // #[cfg(test)] | 127 | // #[cfg(test)] |
| 103 | // mod tests { | 128 | // mod tests { |
| 104 | // use super::*; | 129 | // use super::*; |
