mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 22:57:59 -05:00
src/consensus: blake3 hashes used insted of String, removed serde Deserialize/Serialize (finally)
This commit is contained in:
@@ -17,9 +17,6 @@ async-channel = "1.6.1"
|
||||
async-executor = "1.4.1"
|
||||
easy-parallel = "3.2.0"
|
||||
|
||||
# Crypto
|
||||
rand = "0.8.5"
|
||||
|
||||
# Storage
|
||||
sled = "0.34.7"
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ use async_executor::Executor;
|
||||
use async_trait::async_trait;
|
||||
use easy_parallel::Parallel;
|
||||
use log::{debug, error, info};
|
||||
use rand::{rngs::OsRng, RngCore};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use simplelog::{ColorChoice, TermLogger, TerminalMode};
|
||||
@@ -314,10 +313,8 @@ impl JsonRpcInterface {
|
||||
return Err(InvalidParams)
|
||||
}
|
||||
|
||||
// TODO: add proper tx hash here
|
||||
let random_id = OsRng.next_u32();
|
||||
let payload = String::from(args[0].as_str().unwrap());
|
||||
let tx = Tx { hash: random_id, payload };
|
||||
let tx = Tx { payload };
|
||||
|
||||
self.state.write().unwrap().append_tx(tx.clone());
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
hash::{Hash, Hasher},
|
||||
io,
|
||||
@@ -15,10 +14,10 @@ use crate::{
|
||||
|
||||
/// 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, SerialEncodable, SerialDecodable)]
|
||||
#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
|
||||
pub struct Block {
|
||||
/// Previous block hash
|
||||
pub st: String, // Change this to a proper hash type
|
||||
pub st: blake3::Hash,
|
||||
/// Slot uid, generated by the beacon
|
||||
pub sl: u64,
|
||||
/// Transactions payload
|
||||
@@ -29,7 +28,7 @@ pub struct Block {
|
||||
|
||||
impl Block {
|
||||
pub fn new(
|
||||
st: String,
|
||||
st: blake3::Hash,
|
||||
sl: u64,
|
||||
txs: Vec<Tx>,
|
||||
proof: String,
|
||||
@@ -53,7 +52,7 @@ impl Hash for Block {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, SerialEncodable, SerialDecodable)]
|
||||
#[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)]
|
||||
pub struct BlockProposal {
|
||||
/// leader public key
|
||||
pub public_key: PublicKey,
|
||||
@@ -62,7 +61,7 @@ pub struct BlockProposal {
|
||||
/// leader id
|
||||
pub id: u64,
|
||||
/// Previous block hash
|
||||
pub st: String, // Change this to a proper hash type
|
||||
pub st: blake3::Hash,
|
||||
/// Slot uid, generated by the beacon
|
||||
pub sl: u64,
|
||||
/// Transactions payload
|
||||
@@ -74,7 +73,7 @@ impl BlockProposal {
|
||||
public_key: PublicKey,
|
||||
signature: Signature,
|
||||
id: u64,
|
||||
st: String,
|
||||
st: blake3::Hash,
|
||||
sl: u64,
|
||||
txs: Vec<Tx>,
|
||||
) -> BlockProposal {
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
use std::{
|
||||
collections::hash_map::DefaultHasher,
|
||||
hash::{Hash, Hasher},
|
||||
io,
|
||||
};
|
||||
use std::io;
|
||||
|
||||
use crate::{
|
||||
impl_vec,
|
||||
util::serial::{Decodable, Encodable, SerialDecodable, SerialEncodable, VarInt},
|
||||
util::serial::{serialize, Decodable, Encodable, SerialDecodable, SerialEncodable, VarInt},
|
||||
Result,
|
||||
};
|
||||
|
||||
use super::block::Block;
|
||||
use super::{block::Block, util::GENESIS_HASH_BYTES};
|
||||
|
||||
/// This struct represents a sequence of blocks starting with the genesis block.
|
||||
#[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)]
|
||||
@@ -27,11 +23,11 @@ impl Blockchain {
|
||||
/// previous block and their epochs are incremental, exluding genesis.
|
||||
/// Additional validity rules can be applied.
|
||||
pub fn check_block_validity(&self, block: &Block, previous_block: &Block) {
|
||||
assert!(block.st != "⊥", "Genesis block provided.");
|
||||
let mut hasher = DefaultHasher::new();
|
||||
previous_block.hash(&mut hasher);
|
||||
assert!(block.st.as_bytes() != &GENESIS_HASH_BYTES, "Genesis block provided.");
|
||||
let serialized = serialize(previous_block);
|
||||
let previous_block_hash = blake3::hash(&serialized);
|
||||
assert!(
|
||||
block.st == hasher.finish().to_string() && block.sl > previous_block.sl,
|
||||
block.st == previous_block_hash && block.sl > previous_block.sl,
|
||||
"Provided block is invalid."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::util::serial::{SerialDecodable, SerialEncodable};
|
||||
|
||||
use super::{
|
||||
participant::Participant,
|
||||
@@ -6,10 +6,8 @@ use super::{
|
||||
vote::Vote,
|
||||
};
|
||||
|
||||
use crate::util::serial::{SerialDecodable, SerialEncodable};
|
||||
|
||||
/// This struct represents additional Block information used by the consensus protocol.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, SerialEncodable, SerialDecodable)]
|
||||
#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
|
||||
pub struct Metadata {
|
||||
/// Block information used by Ouroboros consensus
|
||||
pub om: OuroborosMetadata,
|
||||
@@ -30,7 +28,7 @@ impl Metadata {
|
||||
}
|
||||
|
||||
/// This struct represents Block information used by Ouroboros consensus protocol.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, SerialEncodable, SerialDecodable)]
|
||||
#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
|
||||
pub struct OuroborosMetadata {
|
||||
/// Proof the stakeholder is the block owner
|
||||
pub proof: String,
|
||||
@@ -47,7 +45,7 @@ impl OuroborosMetadata {
|
||||
}
|
||||
|
||||
/// This struct represents Block information used by Streamlet consensus protocol.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, SerialEncodable, SerialDecodable)]
|
||||
#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
|
||||
pub struct StreamletMetadata {
|
||||
/// Epoch votes
|
||||
pub votes: Vec<Vote>,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::BTreeMap, io};
|
||||
|
||||
use crate::{
|
||||
@@ -8,7 +7,7 @@ use crate::{
|
||||
};
|
||||
|
||||
/// This struct represents a tuple of the form (node_id, epoch_joined, last_epoch_voted).
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, SerialEncodable, SerialDecodable)]
|
||||
#[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)]
|
||||
pub struct Participant {
|
||||
/// Node id
|
||||
pub id: u64,
|
||||
|
||||
@@ -22,7 +22,7 @@ use super::{
|
||||
blockchain::Blockchain,
|
||||
participant::Participant,
|
||||
tx::Tx,
|
||||
util::Timestamp,
|
||||
util::{Timestamp, GENESIS_HASH_BYTES},
|
||||
vote::Vote,
|
||||
};
|
||||
|
||||
@@ -36,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(SerialEncodable, SerialDecodable)]
|
||||
#[derive(Debug, SerialEncodable, SerialDecodable)]
|
||||
pub struct State {
|
||||
pub id: u64,
|
||||
pub genesis_time: Timestamp,
|
||||
@@ -121,9 +121,8 @@ impl State {
|
||||
pub fn propose_block(&self) -> Result<Option<BlockProposal>> {
|
||||
let epoch = self.get_current_epoch();
|
||||
let longest_notarized_chain = self.find_longest_notarized_chain();
|
||||
let mut hasher = DefaultHasher::new();
|
||||
longest_notarized_chain.blocks.last().unwrap().hash(&mut hasher);
|
||||
let hash = hasher.finish().to_string();
|
||||
let serialized = serialize(longest_notarized_chain.blocks.last().unwrap());
|
||||
let hash = blake3::hash(&serialized);
|
||||
let unproposed_txs = self.get_unproposed_txs();
|
||||
let mut encoded_block = vec![];
|
||||
hash.encode(&mut encoded_block)?;
|
||||
@@ -249,21 +248,20 @@ impl State {
|
||||
|
||||
/// Given a block, node finds the index of the blockchain it extends.
|
||||
pub fn find_extended_blockchain_index(&self, block: &Block, leader: bool) -> i64 {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
for (index, blockchain) in self.node_blockchains.iter().enumerate() {
|
||||
let last_block = blockchain.blocks.last().unwrap();
|
||||
last_block.hash(&mut hasher);
|
||||
if (leader && block.st == hasher.finish().to_string() && block.sl >= last_block.sl) ||
|
||||
(!leader && block.st == hasher.finish().to_string() && block.sl > last_block.sl)
|
||||
let last_block_hash = blake3::hash(&serialize(last_block));
|
||||
if (leader && block.st == last_block_hash && block.sl >= last_block.sl) ||
|
||||
(!leader && block.st == last_block_hash && block.sl > last_block.sl)
|
||||
{
|
||||
return index as i64
|
||||
}
|
||||
}
|
||||
|
||||
let last_block = self.canonical_blockchain.blocks.last().unwrap();
|
||||
last_block.hash(&mut hasher);
|
||||
if (leader && block.st != hasher.finish().to_string() || block.sl < last_block.sl) ||
|
||||
(!leader && block.st != hasher.finish().to_string() || block.sl <= last_block.sl)
|
||||
let last_block_hash = blake3::hash(&serialize(last_block));
|
||||
if (leader && block.st != last_block_hash || block.sl < last_block.sl) ||
|
||||
(!leader && block.st != last_block_hash || block.sl <= last_block.sl)
|
||||
{
|
||||
debug!("Proposed block doesn't extend any known chains.");
|
||||
return -2
|
||||
@@ -381,10 +379,8 @@ impl State {
|
||||
self.canonical_blockchain.blocks.push(block.clone());
|
||||
}
|
||||
|
||||
let mut hasher = DefaultHasher::new();
|
||||
let last_finalized_block = self.canonical_blockchain.blocks.last().unwrap();
|
||||
last_finalized_block.hash(&mut hasher);
|
||||
let last_finalized_block_hash = hasher.finish().to_string();
|
||||
let last_finalized_block_hash = blake3::hash(&serialize(last_finalized_block));
|
||||
let mut dropped_blockchains = Vec::new();
|
||||
for (index, blockchain) in self.node_blockchains.iter().enumerate() {
|
||||
let first_block = blockchain.blocks.first().unwrap();
|
||||
@@ -493,7 +489,7 @@ impl 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("⊥"),
|
||||
blake3::Hash::from(GENESIS_HASH_BYTES),
|
||||
0,
|
||||
vec![],
|
||||
String::from("proof"),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
|
||||
use crate::{
|
||||
@@ -7,9 +6,8 @@ use crate::{
|
||||
Result,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, SerialEncodable, SerialDecodable)]
|
||||
#[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)]
|
||||
pub struct Tx {
|
||||
pub hash: u32, // Change this to a proper hash type
|
||||
pub payload: String,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
use chrono::{NaiveDateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
|
||||
use crate::util::serial::{SerialDecodable, SerialEncodable};
|
||||
use crate::{
|
||||
util::serial::{Decodable, Encodable, ReadExt, SerialDecodable, SerialEncodable, WriteExt},
|
||||
Result,
|
||||
};
|
||||
|
||||
// Serialized blake3 hash bytes for character "⊥"
|
||||
pub const GENESIS_HASH_BYTES: [u8; 32] = [
|
||||
254, 233, 82, 102, 23, 208, 153, 87, 96, 165, 163, 194, 238, 7, 1, 88, 14, 1, 249, 118, 197,
|
||||
29, 180, 211, 87, 66, 59, 38, 86, 54, 12, 39,
|
||||
];
|
||||
|
||||
/// Util structure to represend chrono UTC timestamps.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, SerialDecodable, SerialEncodable)]
|
||||
#[derive(Debug, Clone, SerialDecodable, SerialEncodable)]
|
||||
pub struct Timestamp(pub i64);
|
||||
|
||||
impl Timestamp {
|
||||
@@ -21,3 +30,18 @@ impl Timestamp {
|
||||
pub fn get_current_time() -> Timestamp {
|
||||
Timestamp(Utc::now().timestamp())
|
||||
}
|
||||
|
||||
impl Encodable for blake3::Hash {
|
||||
fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
|
||||
s.write_slice(self.as_bytes())?;
|
||||
Ok(32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for blake3::Hash {
|
||||
fn decode<D: io::Read>(mut d: D) -> Result<Self> {
|
||||
let mut bytes = [0u8; 32];
|
||||
d.read_slice(&mut bytes)?;
|
||||
Ok(bytes.into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
|
||||
use super::block::BlockProposal;
|
||||
@@ -11,13 +10,13 @@ use crate::{
|
||||
};
|
||||
|
||||
/// This struct represents a tuple of the form (vote, B, id).
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, SerialDecodable, SerialEncodable)]
|
||||
#[derive(Debug, Clone, PartialEq, SerialDecodable, SerialEncodable)]
|
||||
pub struct Vote {
|
||||
/// Node public key
|
||||
pub node_public_key: PublicKey,
|
||||
/// signed block
|
||||
pub vote: Signature,
|
||||
/// block hash to vote on
|
||||
/// block proposal to vote on
|
||||
pub block: BlockProposal,
|
||||
/// node id
|
||||
pub id: u64,
|
||||
|
||||
Reference in New Issue
Block a user