aboutsummaryrefslogtreecommitdiffstats
path: root/src/schema.rs
blob: c4917ab8c302b8e1cbdc9072c6a820d2d3817c8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use chrono::NaiveDateTime;
use parking_lot::RwLock;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;

// use crate::validators;

// In memory data structure
// Two approaches here
// 1. Db is a type pub type Db = Arc<RwLock<Vec<Ledger>>>; Ledger is a struct, we wrap the ledger
//    with arc + mutex in ledger() to access transactions we need to unwrap blocks as well, vice
//    versa
//
// 2. Db is a struct attributes are wrapped we can offload ::new() to it's member method blocks and
//    transactions are accessible separately, which is the biggest pro
//
// 3. use an actual database (for blockchain and users this makes the most sense tbh but pending
//    transactions are perfectly fine in memory)

/// Creates a new database
pub fn create_database() -> Db {
    Db::new()
}

#[derive(Debug, Clone)]
pub struct Db {
    // heh. also https://doc.rust-lang.org/std/collections/struct.LinkedList.html says Vec is generally faster
    pub blockchain: Arc<RwLock<Vec<Block>>>,
    // every proposer can have _one_ pending transaction, a way to enforce this, String is proposer identifier
    pub pending_transactions: Arc<RwLock<HashMap<String, Transaction>>>,
    // this was bound to happen eventually
    pub users: Arc<RwLock<HashMap<String, User>>>,
}

impl Db {
    fn new() -> Self {
        Db {
            blockchain: Arc::new(RwLock::new(Vec::new())),
            pending_transactions: Arc::new(RwLock::new(HashMap::new())),
            users: Arc::new(RwLock::new(HashMap::new())),
        }
    }
}

/// A transaction between `source` and `target` that moves `amount` Note:
/// https://serde.rs/container-attrs.html might be valueable to normalize the serialize/deserialize
/// conventions as these will be hashed
#[derive(Serialize, Deserialize, Debug)]
pub struct Transaction {
    pub source: String,
    pub target: String,
    pub amount: i32,
    pub timestamp: NaiveDateTime,
}

/// A block that was proposed with `transaction_list` and `nonce` that made `hash` valid
/// https://serde.rs/container-attrs.html might be valueable to normalize the serialize/deserialize
/// conventions as these will be hashed
#[derive(Serialize, Deserialize, Debug)]
pub struct Block {
    // TODO: transaction list should hold transaction hash values <09-04-21, yigit> //
    // but do we link them somehow? (like a log of old transactions?)
    // we can leave this as is and whenever we have a new block we _could_ just log it to file
    // somewhere
    // I want to keep this as a String vector because it makes things easier elsewhere
    pub transaction_list: Vec<String>, // hashes of the transactions (or just "source" for now)
    pub nonce: String,
    pub timestamp: NaiveDateTime,
    pub hash: String, // future proof'd baby
}

#[derive(Serialize, Deserialize, Debug)]
pub struct User {
    username: String,
    token: String
}

// TODO: write schema tests using the original repo <09-04-21, yigit> //