Преглед изворни кода

validatord: state storage moved from jsonfile to sled

aggstam пре 4 година
родитељ
комит
267e1d2016
24 измењених фајлова са 93 додато и 591 уклоњено
  1. 3 0
      script/research/validatord/Cargo.toml
  2. 3 4
      script/research/validatord/simulation.sh
  3. 0 53
      script/research/validatord/simulation/sim10/simulation.sh
  4. 0 34
      script/research/validatord/simulation/sim10/validatord_state_0
  5. 0 34
      script/research/validatord/simulation/sim10/validatord_state_1
  6. 0 34
      script/research/validatord/simulation/sim10/validatord_state_2
  7. 0 34
      script/research/validatord/simulation/sim10/validatord_state_3
  8. 0 34
      script/research/validatord/simulation/sim10/validatord_state_4
  9. 0 34
      script/research/validatord/simulation/sim10/validatord_state_5
  10. 0 34
      script/research/validatord/simulation/sim10/validatord_state_6
  11. 0 34
      script/research/validatord/simulation/sim10/validatord_state_7
  12. 0 34
      script/research/validatord/simulation/sim10/validatord_state_8
  13. 0 34
      script/research/validatord/simulation/sim10/validatord_state_9
  14. 0 34
      script/research/validatord/simulation/validatord_state_0
  15. 0 34
      script/research/validatord/simulation/validatord_state_1
  16. 0 34
      script/research/validatord/simulation/validatord_state_2
  17. 0 34
      script/research/validatord/simulation/validatord_state_3
  18. 13 8
      script/research/validatord/src/main.rs
  19. 5 2
      script/research/validatord/validatord_config.toml
  20. 10 4
      src/consensus/block.rs
  21. 9 2
      src/consensus/blockchain.rs
  22. 24 1
      src/consensus/participant.rs
  23. 24 18
      src/consensus/state.rs
  24. 2 23
      src/consensus/util.rs

+ 3 - 0
script/research/validatord/Cargo.toml

@@ -20,6 +20,9 @@ easy-parallel = "3.2.0"
 # Crypto
 rand = "0.8.5"
 
+# Storage
+sled = "0.34.7"
+
 # Structopt dependencies for arguments parsing
 serde = "1.0.136"
 serde_derive = "1.0.136"

+ 3 - 4
script/research/validatord/simulation/simulation.sh → script/research/validatord/simulation.sh

@@ -1,7 +1,6 @@
 #!/bin/bash
 
 # Simulation of the consensus network for n validator nodes.
-# Note: state files should be generated before executing.
 
 nodes=4
 
@@ -9,7 +8,7 @@ nodes=4
 bound=$(($nodes - 1))
 for i in $(eval echo "{0..$bound}")
 do
-  cp validatord_state_$i ~/.config/darkfi/validatord_state_$i
+  rmdir ~/.config/darkfi/validatord_db_$i
 done
 
 # PIDs array
@@ -26,7 +25,7 @@ sleep 2
 bound=$(($nodes-2))
 for i in $(eval echo "{1..$bound}")
 do
-  cargo run -- --accept 0.0.0.0:1100$i --seeds 127.0.0.1:11000 --rpc 127.0.0.1:666$i --external 127.0.0.1:1100$i --id $i --state ~/.config/darkfi/validatord_state_$i &
+  cargo run -- --accept 0.0.0.0:1100$i --seeds 127.0.0.1:11000 --rpc 127.0.0.1:666$i --external 127.0.0.1:1100$i --id $i --database ~/.config/darkfi/validatord_db_$i &
   pids[${#pids[@]}]=$!
   # waiting for node to setup
   sleep 2
@@ -45,7 +44,7 @@ function ctrl_c() {
 
 bound=$(($nodes-1))
 # Starting last node
-cargo run -- --accept 0.0.0.0:1100$bound --seeds 127.0.0.1:11000 --rpc 127.0.0.1:666$bound --external 127.0.0.1:1100$bound --id $bound --state ~/.config/darkfi/validatord_state_$bound
+cargo run -- --accept 0.0.0.0:1100$bound --seeds 127.0.0.1:11000 --rpc 127.0.0.1:666$bound --external 127.0.0.1:1100$bound --id $bound --database ~/.config/darkfi/validatord_db_$bound
 
 # Node states are flushed on each node state file at epoch end (every 2 minutes).
 # To sugmit a TX, telnet to a node and push the json as per following example:

+ 0 - 53
script/research/validatord/simulation/sim10/simulation.sh

@@ -1,53 +0,0 @@
-#!/bin/bash
-
-# Simulation of the consensus network for n validator nodes.
-# Note: state files should be generated before executing.
-
-nodes=10
-
-# Copying the node state files with a blockchain containing only the genesis block.
-bound=$(($nodes - 1))
-for i in $(eval echo "{0..$bound}")
-do
-  cp validatord_state_$i ~/.config/darkfi/validatord_state_$i
-done
-
-# PIDs array
-pids=()
-
-# Starting node 0 (seed) in background
-cargo run -- &
-pids[${#pids[@]}]=$!
-
-# Waiting for seed to setup
-sleep 2
-
-# Starting nodes 1 till second to last node in background
-bound=$(($nodes-2))
-for i in $(eval echo "{1..$bound}")
-do
-  cargo run -- --accept 0.0.0.0:1100$i --seeds 127.0.0.1:11000 --rpc 127.0.0.1:666$i --external 127.0.0.1:1100$i --id $i --state ~/.config/darkfi/validatord_state_$i &
-  pids[${#pids[@]}]=$!
-  # waiting for node to setup
-  sleep 2
-done
-
-# Trap kill signal
-trap ctrl_c INT
-
-# On kill signal, terminate background node processes
-function ctrl_c() {
-    for pid in ${pids[@]}
-    do
-      kill $pid
-    done
-}
-
-bound=$(($nodes-1))
-# Starting last node
-cargo run -- --accept 0.0.0.0:1100$bound --seeds 127.0.0.1:11000 --rpc 127.0.0.1:666$bound --external 127.0.0.1:1100$bound --id $bound --state ~/.config/darkfi/validatord_state_$bound
-
-# Node states are flushed on each node state file at epoch end (every 2 minutes).
-# To sugmit a TX, telnet to a node and push the json as per following example:
-# telnet 127.0.0.1 6661
-# {"jsonrpc": "2.0", "method": "receive_tx", "params": ["tx"], "id": 42}

+ 0 - 34
script/research/validatord/simulation/sim10/validatord_state_0

@@ -1,34 +0,0 @@
-{
-  "id": 0,
-  "genesis_time": 1648383795,
-  "secret_key": "22c1a9eae232ec84096c90896e763087a36b3eb55f3de599d5d3f7bba280a11e",
-  "public_key": "ad50d94b531da6864b32bed5001fde813e745841202b45d9f892e05d57593d19",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/sim10/validatord_state_1

@@ -1,34 +0,0 @@
-{
-  "id": 1,
-  "genesis_time": 1648383795,
-  "secret_key": "22c1a9eae232ec84096c90896e763087a36b3eb55f3de599d5d3f7bba280a11e",
-  "public_key": "ad50d94b531da6864b32bed5001fde813e745841202b45d9f892e05d57593d19",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/sim10/validatord_state_2

@@ -1,34 +0,0 @@
-{
-  "id": 2,
-  "genesis_time": 1648383795,
-  "secret_key": "22c1a9eae232ec84096c90896e763087a36b3eb55f3de599d5d3f7bba280a11e",
-  "public_key": "ad50d94b531da6864b32bed5001fde813e745841202b45d9f892e05d57593d19",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/sim10/validatord_state_3

@@ -1,34 +0,0 @@
-{
-  "id": 3,
-  "genesis_time": 1648383795,
-  "secret_key": "22c1a9eae232ec84096c90896e763087a36b3eb55f3de599d5d3f7bba280a11e",
-  "public_key": "ad50d94b531da6864b32bed5001fde813e745841202b45d9f892e05d57593d19",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/sim10/validatord_state_4

@@ -1,34 +0,0 @@
-{
-  "id": 4,
-  "genesis_time": 1648383795,
-  "secret_key": "22c1a9eae232ec84096c90896e763087a36b3eb55f3de599d5d3f7bba280a11e",
-  "public_key": "ad50d94b531da6864b32bed5001fde813e745841202b45d9f892e05d57593d19",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/sim10/validatord_state_5

@@ -1,34 +0,0 @@
-{
-  "id": 5,
-  "genesis_time": 1648383795,
-  "secret_key": "22c1a9eae232ec84096c90896e763087a36b3eb55f3de599d5d3f7bba280a11e",
-  "public_key": "ad50d94b531da6864b32bed5001fde813e745841202b45d9f892e05d57593d19",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/sim10/validatord_state_6

@@ -1,34 +0,0 @@
-{
-  "id": 6,
-  "genesis_time": 1648383795,
-  "secret_key": "22c1a9eae232ec84096c90896e763087a36b3eb55f3de599d5d3f7bba280a11e",
-  "public_key": "ad50d94b531da6864b32bed5001fde813e745841202b45d9f892e05d57593d19",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/sim10/validatord_state_7

@@ -1,34 +0,0 @@
-{
-  "id": 7,
-  "genesis_time": 1648383795,
-  "secret_key": "22c1a9eae232ec84096c90896e763087a36b3eb55f3de599d5d3f7bba280a11e",
-  "public_key": "ad50d94b531da6864b32bed5001fde813e745841202b45d9f892e05d57593d19",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/sim10/validatord_state_8

@@ -1,34 +0,0 @@
-{
-  "id": 8,
-  "genesis_time": 1648383795,
-  "secret_key": "22c1a9eae232ec84096c90896e763087a36b3eb55f3de599d5d3f7bba280a11e",
-  "public_key": "ad50d94b531da6864b32bed5001fde813e745841202b45d9f892e05d57593d19",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/sim10/validatord_state_9

@@ -1,34 +0,0 @@
-{
-  "id": 9,
-  "genesis_time": 1648383795,
-  "secret_key": "22c1a9eae232ec84096c90896e763087a36b3eb55f3de599d5d3f7bba280a11e",
-  "public_key": "ad50d94b531da6864b32bed5001fde813e745841202b45d9f892e05d57593d19",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/validatord_state_0

@@ -1,34 +0,0 @@
-{
-  "id": 0,
-  "genesis_time": 1648383795,
-  "secret_key": "22c1a9eae232ec84096c90896e763087a36b3eb55f3de599d5d3f7bba280a11e",
-  "public_key": "ad50d94b531da6864b32bed5001fde813e745841202b45d9f892e05d57593d19",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/validatord_state_1

@@ -1,34 +0,0 @@
-{
-  "id": 1,
-  "genesis_time": 1648383795,
-  "secret_key": "56d954a063168d30e93e3c1afc16d12af3e8c048fca87b930146efb02f7f4c26",
-  "public_key": "4537911dc67e1dc828fe507d3fd25dcaf0b5c10a4b8dce5cee9aef8c91057fab",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/validatord_state_2

@@ -1,34 +0,0 @@
-{
-  "id": 2,
-  "genesis_time": 1648383795,
-  "secret_key": "840a0e56c7bf4fa88e677244e3a3a8bd7c7cc9b0f591bb1ab6a5c9ac95d2f015",
-  "public_key": "469e7cdf2b72c2a6be5cfcec4a7694137660bc8d57f6f961b630c397b07bbf14",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 0 - 34
script/research/validatord/simulation/validatord_state_3

@@ -1,34 +0,0 @@
-{
-  "id": 3,
-  "genesis_time": 1648383795,
-  "secret_key": "8403caeceb6b91284363ed3074af5a565bd9eeb75a5ad46b7522d3ac4074c400",
-  "public_key": "6e487af2f92f37b29b5bf05f75670c0f6b5813fd7d16a6f7b8bed6325370a5af",
-  "canonical_blockchain": {
-    "blocks": [
-      {
-        "st": "⊥",
-        "sl": 0,
-        "txs": [],
-        "metadata": {
-          "om": {
-            "proof": "proof",
-            "r": "r",
-            "s": "s"
-          },
-          "sm": {
-            "votes": [],
-            "notarized": true,
-            "finalized": true,
-            "participants": []
-          },
-          "timestamp": 1648383795
-        }
-      }
-    ]
-  },
-  "node_blockchains": [],
-  "unconfirmed_txs": [],
-  "orphan_votes": [],
-  "participants": {},
-  "pending_participants": []
-}

+ 13 - 8
script/research/validatord/src/main.rs

@@ -79,9 +79,12 @@ struct Opt {
     #[structopt(long, default_value = "FOOBAR")]
     /// Password for the created TLS identity
     password: String,
-    #[structopt(long, default_value = "~/.config/darkfi/validatord_state_0")]
-    /// Path to the state file
-    state: String,
+    #[structopt(long, default_value = "1648383795")]
+    /// Timestamp of the genesis block creation
+    genesis: i64,
+    #[structopt(long, default_value = "~/.config/darkfi/validatord_db_0")]
+    /// Path to the sled database folder
+    database: String,
     #[structopt(long, default_value = "0")]
     /// Node ID, used only for testing
     id: u64,
@@ -93,7 +96,7 @@ struct Opt {
     verbose: u8,
 }
 
-async fn proposal_task(p2p: net::P2pPtr, state: StatePtr, state_path: &PathBuf) {
+async fn proposal_task(p2p: net::P2pPtr, state: StatePtr, database: &sled::Db) {
     // Node signals the network that it starts participating
     let participant =
         Participant::new(state.read().unwrap().id, state.read().unwrap().get_current_epoch());
@@ -155,7 +158,7 @@ async fn proposal_task(p2p: net::P2pPtr, state: StatePtr, state_path: &PathBuf)
             Err(e) => error!("Broadcast failed. Error: {:?}", e),
         }
 
-        let result = state.read().unwrap().save(state_path);
+        let result = state.read().unwrap().save(database);
         match result {
             Ok(()) => (),
             Err(e) => {
@@ -186,9 +189,11 @@ async fn start(executor: Arc<Executor<'_>>, opts: &Opt) -> Result<()> {
     };
 
     // State setup
-    let state_path = expand_path(&opts.state).unwrap();
+    let genesis = opts.genesis;
+    let database_path = expand_path(&opts.database).unwrap();
+    let database = sled::open(database_path).unwrap();
     let id = opts.id.clone();
-    let state = State::load_current_state(id, &state_path).unwrap();
+    let state = State::load_current_state(genesis, id, &database).unwrap();
 
     // P2P registry setup
     let p2p = net::P2p::new(network_settings).await;
@@ -255,7 +260,7 @@ async fn start(executor: Arc<Executor<'_>>, opts: &Opt) -> Result<()> {
         .spawn(async move { listen_and_serve(rpc_server_config, rpc_interface, ex3).await })
         .detach();
 
-    proposal_task(p2p, state, &state_path).await;
+    proposal_task(p2p, state, &database).await;
 
     Ok(())
 }

+ 5 - 2
script/research/validatord/validatord_config.toml

@@ -38,8 +38,11 @@ identity = "~/.config/darkfi/validatord_identity.pfx"
 # Password for the created TLS identity. (Unused if serve_tls=false)
 password = "FOOBAR"
 
-# Path to the state file 
-state = "~/.config/darkfi/validatord_state_0"
+# Timestamp of the genesis block creation
+genesis = 1648383795
+
+# Path to the sled database folder 
+database = "~/.config/darkfi/validatord_db_0"
 
 # Node ID, used only for testing
 id = 0

+ 10 - 4
src/consensus/block.rs

@@ -1,17 +1,21 @@
 use serde::{Deserialize, Serialize};
-use std::hash::{Hash, Hasher};
+use std::{
+    hash::{Hash, Hasher},
+    io,
+};
 
 use super::{metadata::Metadata, participant::Participant, tx::Tx};
 
 use crate::{
     crypto::{keypair::PublicKey, schnorr::Signature},
-    net,
-    util::serial::{SerialDecodable, SerialEncodable},
+    impl_vec, net,
+    util::serial::{Decodable, Encodable, SerialDecodable, SerialEncodable, VarInt},
+    Result,
 };
 
 /// This struct represents a tuple of the form (st, sl, txs, metadata).
 /// Each blocks parent hash h may be computed simply as a hash of the parent block.
-#[derive(Debug, Clone, Deserialize, Serialize)]
+#[derive(Debug, Clone, Deserialize, Serialize, SerialEncodable, SerialDecodable)]
 pub struct Block {
     /// Previous block hash
     pub st: String, // Change this to a proper hash type
@@ -87,3 +91,5 @@ impl net::Message for BlockProposal {
 pub fn proposal_eq_block(proposal: &BlockProposal, block: &Block) -> bool {
     proposal.st == block.st && proposal.sl == block.sl && proposal.txs == block.txs
 }
+
+impl_vec!(Block);

+ 9 - 2
src/consensus/blockchain.rs

@@ -1,14 +1,19 @@
 use std::{
     collections::hash_map::DefaultHasher,
     hash::{Hash, Hasher},
+    io,
 };
 
-use serde::{Deserialize, Serialize};
+use crate::{
+    impl_vec,
+    util::serial::{Decodable, Encodable, SerialDecodable, SerialEncodable, VarInt},
+    Result,
+};
 
 use super::block::Block;
 
 /// This struct represents a sequence of blocks starting with the genesis block.
-#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
+#[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)]
 pub struct Blockchain {
     pub blocks: Vec<Block>,
 }
@@ -54,3 +59,5 @@ impl Blockchain {
         true
     }
 }
+
+impl_vec!(Blockchain);

+ 24 - 1
src/consensus/participant.rs

@@ -1,5 +1,5 @@
 use serde::{Deserialize, Serialize};
-use std::io;
+use std::{collections::BTreeMap, io};
 
 use crate::{
     impl_vec, net,
@@ -30,4 +30,27 @@ impl net::Message for Participant {
     }
 }
 
+impl Encodable for BTreeMap<u64, Participant> {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        let mut len = 0;
+        len += VarInt(self.len() as u64).encode(&mut s)?;
+        for c in self.iter() {
+            len += c.1.encode(&mut s)?;
+        }
+        Ok(len)
+    }
+}
+
+impl Decodable for BTreeMap<u64, Participant> {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        let len = VarInt::decode(&mut d)?.0;
+        let mut ret = BTreeMap::new();
+        for _ in 0..len {
+            let participant: Participant = Decodable::decode(&mut d)?;
+            ret.insert(participant.id, participant);
+        }
+        Ok(ret)
+    }
+}
+
 impl_vec!(Participant);

+ 24 - 18
src/consensus/state.rs

@@ -1,10 +1,8 @@
 use chrono::{NaiveDateTime, Utc};
 use log::{debug, error};
-use serde::{Deserialize, Serialize};
 use std::{
     collections::{hash_map::DefaultHasher, BTreeMap},
     hash::{Hash, Hasher},
-    path::Path,
     sync::{Arc, RwLock},
     time::Duration,
 };
@@ -14,8 +12,8 @@ use crate::{
         keypair::{PublicKey, SecretKey},
         schnorr::{SchnorrPublic, SchnorrSecret},
     },
-    util::serial::Encodable,
-    Result,
+    util::serial::{deserialize, serialize, Encodable, SerialDecodable, SerialEncodable},
+    Error, Result,
 };
 use rand::rngs::OsRng;
 
@@ -24,11 +22,12 @@ use super::{
     blockchain::Blockchain,
     participant::Participant,
     tx::Tx,
-    util::{get_current_time, load, save, Timestamp},
+    util::Timestamp,
     vote::Vote,
 };
 
 const DELTA: u64 = 60;
+const SLED_STATE_TREE: &[u8] = b"_state";
 
 /// Atomic pointer to state.
 pub type StatePtr = Arc<RwLock<State>>;
@@ -37,7 +36,7 @@ pub type StatePtr = Arc<RwLock<State>>;
 /// Each node is numbered and has a secret-public keys pair, to sign messages.
 /// Nodes hold a set of Blockchains(some of which are not notarized)
 /// and a set of unconfirmed pending transactions.
-#[derive(Deserialize, Serialize)]
+#[derive(SerialEncodable, SerialDecodable)]
 pub struct State {
     pub id: u64,
     pub genesis_time: Timestamp,
@@ -464,27 +463,34 @@ impl State {
     }
 
     /// Util function to save the current node state to provided file path.
-    pub fn save(&self, path: &Path) -> Result<()> {
-        save::<Self>(path, self)
+    pub fn save(&self, db: &sled::Db) -> Result<()> {
+        let tree = db.open_tree(SLED_STATE_TREE).unwrap();
+        let serialized = serialize(self);
+        match tree.insert(self.id.to_ne_bytes(), serialized) {
+            Err(_) => Err(Error::OperationFailed),
+            _ => Ok(()),
+        }
     }
 
     /// Util function to load current node state by the provided file path.
     //  If file is not found, node state is reset.
-    pub fn load_or_create(id: u64, path: &Path) -> Result<Self> {
-        match load::<Self>(path) {
-            Ok(state) => Ok(state),
-            Err(_) => Self::reset(id, path),
+    pub fn load_or_create(genesis: i64, id: u64, db: &sled::Db) -> Result<State> {
+        let tree = db.open_tree(SLED_STATE_TREE).unwrap();
+        if let Some(found) = tree.get(id.to_ne_bytes()).unwrap() {
+            Ok(deserialize(&found).unwrap())
+        } else {
+            Self::reset(genesis, id, db)
         }
     }
 
-    /// Util function to load the current node state by the provided file path.
-    pub fn load_current_state(id: u64, path: &Path) -> Result<StatePtr> {
-        let state = Self::load_or_create(id, path)?;
+    /// Util function to load the current node state by the provided folder path.
+    pub fn load_current_state(genesis: i64, id: u64, db: &sled::Db) -> Result<StatePtr> {
+        let state = Self::load_or_create(genesis, id, db)?;
         Ok(Arc::new(RwLock::new(state)))
     }
 
     /// Util function to reset node state.
-    pub fn reset(id: u64, path: &Path) -> Result<State> {
+    pub fn reset(genesis: i64, id: u64, db: &sled::Db) -> Result<State> {
         // Genesis block is generated.
         let mut genesis_block = Block::new(
             String::from("⊥"),
@@ -498,10 +504,10 @@ impl State {
         genesis_block.metadata.sm.notarized = true;
         genesis_block.metadata.sm.finalized = true;
 
-        let genesis_time = get_current_time();
+        let genesis_time = Timestamp(genesis);
 
         let state = Self::new(id, genesis_time, genesis_block);
-        state.save(path)?;
+        state.save(db)?;
         Ok(state)
     }
 }

+ 2 - 23
src/consensus/util.rs

@@ -1,28 +1,7 @@
-use std::{fs::File, io::BufReader, path::Path};
-
 use chrono::{NaiveDateTime, Utc};
-use serde::{de::DeserializeOwned, Deserialize, Serialize};
-
-use crate::{
-    util::serial::{SerialDecodable, SerialEncodable},
-    Result,
-};
-
-/// Util function to load a structure saved as a JSON in the provided path file, using serde crate.
-pub fn load<T: DeserializeOwned>(path: &Path) -> Result<T> {
-    let file = File::open(path)?;
-    let reader = BufReader::new(file);
+use serde::{Deserialize, Serialize};
 
-    let value: T = serde_json::from_reader(reader)?;
-    Ok(value)
-}
-
-/// Util function to save a structure as a JSON in the provided path file, using serde crate.
-pub fn save<T: Serialize>(path: &Path, value: &T) -> Result<()> {
-    let file = File::create(path)?;
-    serde_json::to_writer_pretty(file, value)?;
-    Ok(())
-}
+use crate::util::serial::{SerialDecodable, SerialEncodable};
 
 /// Util structure to represend chrono UTC timestamps.
 #[derive(Debug, Clone, Serialize, Deserialize, SerialDecodable, SerialEncodable)]