validatord: state storage moved from jsonfile to sled

This commit is contained in:
aggstam
2022-04-05 22:23:00 +03:00
parent a2e6917f3c
commit 267e1d2016
24 changed files with 93 additions and 591 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)
}
}

View File

@@ -1,28 +1,7 @@
use std::{fs::File, io::BufReader, path::Path};
use chrono::{NaiveDateTime, Utc};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde::{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);
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)]