Fixed serializiation determinacy problems.
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -310,6 +310,7 @@ checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445"
|
|||||||
name = "bft-crdt-derive"
|
name = "bft-crdt-derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"indexmap 2.2.6",
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -323,6 +324,7 @@ dependencies = [
|
|||||||
"bft-crdt-derive",
|
"bft-crdt-derive",
|
||||||
"colored",
|
"colored",
|
||||||
"fastcrypto",
|
"fastcrypto",
|
||||||
|
"indexmap 2.2.6",
|
||||||
"itertools",
|
"itertools",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"random_color",
|
"random_color",
|
||||||
@@ -1905,6 +1907,7 @@ version = "1.0.117"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"indexmap 2.2.6",
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -2056,6 +2059,7 @@ dependencies = [
|
|||||||
"dirs",
|
"dirs",
|
||||||
"ezsockets",
|
"ezsockets",
|
||||||
"fastcrypto",
|
"fastcrypto",
|
||||||
|
"indexmap 2.2.6",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_with 3.8.1",
|
"serde_with 3.8.1",
|
||||||
|
|||||||
@@ -17,15 +17,16 @@ bft = []
|
|||||||
bft-crdt-derive = { path = "bft-crdt-derive" }
|
bft-crdt-derive = { path = "bft-crdt-derive" }
|
||||||
colored = "2.0.0"
|
colored = "2.0.0"
|
||||||
fastcrypto = "0.1.8"
|
fastcrypto = "0.1.8"
|
||||||
|
indexmap = { version = "2.2.6", features = ["serde"] }
|
||||||
itertools = "0.10.5"
|
itertools = "0.10.5"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
random_color = "0.6.1"
|
random_color = "0.6.1"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0.85"
|
serde_json = { version = "1.0.85", features = ["preserve_order"] }
|
||||||
serde_with = "3.8.1"
|
serde_with = "3.8.1"
|
||||||
sha2 = "0.10.6"
|
sha2 = "0.10.6"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
serde_json = "1.0.85"
|
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = { version = "1.0.85", features = ["preserve_order"] }
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ publish = false
|
|||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
indexmap = { version = "2.2.6", features = ["serde"] }
|
||||||
proc-macro2 = "1.0.47"
|
proc-macro2 = "1.0.47"
|
||||||
proc-macro-crate = "1.2.1"
|
proc-macro-crate = "1.2.1"
|
||||||
quote = "1.0.21"
|
quote = "1.0.21"
|
||||||
|
|||||||
@@ -6,13 +6,12 @@ use syn::{
|
|||||||
parse::{self, Parser},
|
parse::{self, Parser},
|
||||||
parse_macro_input,
|
parse_macro_input,
|
||||||
spanned::Spanned,
|
spanned::Spanned,
|
||||||
Data, DeriveInput, Field, Fields, ItemStruct, LitStr, Type
|
Data, DeriveInput, Field, Fields, ItemStruct, LitStr, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Helper to get tokenstream representing the parent crate
|
/// Helper to get tokenstream representing the parent crate
|
||||||
fn get_crate_name() -> TokenStream {
|
fn get_crate_name() -> TokenStream {
|
||||||
let cr8 = crate_name("bft-json-crdt")
|
let cr8 = crate_name("bft-json-crdt").unwrap_or(FoundCrate::Itself);
|
||||||
.unwrap_or(FoundCrate::Itself);
|
|
||||||
match cr8 {
|
match cr8 {
|
||||||
FoundCrate::Itself => quote! { ::bft_json_crdt },
|
FoundCrate::Itself => quote! { ::bft_json_crdt },
|
||||||
FoundCrate::Name(name) => {
|
FoundCrate::Name(name) => {
|
||||||
@@ -144,7 +143,7 @@ pub fn derive_json_crdt(input: OgTokenStream) -> OgTokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> #crate_name::json_crdt::JsonValue {
|
fn view(&self) -> #crate_name::json_crdt::JsonValue {
|
||||||
let mut view_map = std::collections::HashMap::new();
|
let mut view_map = indexmap::IndexMap::new();
|
||||||
#(view_map.insert(#ident_strings.to_string(), self.#ident_literals.view().into());)*
|
#(view_map.insert(#ident_strings.to_string(), self.#ident_literals.view().into());)*
|
||||||
#crate_name::json_crdt::JsonValue::Object(view_map)
|
#crate_name::json_crdt::JsonValue::Object(view_map)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use fastcrypto::{
|
|||||||
traits::{KeyPair, ToFromBytes},
|
traits::{KeyPair, ToFromBytes},
|
||||||
// Verifier,
|
// Verifier,
|
||||||
};
|
};
|
||||||
|
use indexmap::IndexMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::{serde_as, Bytes};
|
use serde_with::{serde_as, Bytes};
|
||||||
|
|
||||||
@@ -256,7 +257,7 @@ pub enum JsonValue {
|
|||||||
Number(f64),
|
Number(f64),
|
||||||
String(String),
|
String(String),
|
||||||
Array(Vec<JsonValue>),
|
Array(Vec<JsonValue>),
|
||||||
Object(HashMap<String, JsonValue>),
|
Object(IndexMap<String, JsonValue>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for JsonValue {
|
impl Display for JsonValue {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ tracing = "0.1.32"
|
|||||||
tracing-subscriber = "0.3.9"
|
tracing-subscriber = "0.3.9"
|
||||||
toml = "0.8.14"
|
toml = "0.8.14"
|
||||||
url = "2.2.2"
|
url = "2.2.2"
|
||||||
|
indexmap = { version = "2.2.6", features = ["serde"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
uuid = { version = "1.8.0", features = ["v4"] }
|
uuid = { version = "1.8.0", features = ["v4"] }
|
||||||
|
|||||||
@@ -39,14 +39,14 @@ impl SideNode {
|
|||||||
let transaction = utils::fake_transaction_json(stdin);
|
let transaction = utils::fake_transaction_json(stdin);
|
||||||
let json = serde_json::to_value(transaction).unwrap();
|
let json = serde_json::to_value(transaction).unwrap();
|
||||||
let signed_op = self.add_transaction_local(json);
|
let signed_op = self.add_transaction_local(json);
|
||||||
println!("STDIN: {}", shappy(signed_op.clone()));
|
println!("STDIN: {}", utils::shappy(signed_op.clone()));
|
||||||
self.send_to_network(signed_op).await;
|
self.send_to_network(signed_op).await;
|
||||||
}
|
}
|
||||||
Err(_) => {} // ignore empty channel errors in this PoC
|
Err(_) => {} // ignore empty channel errors in this PoC
|
||||||
}
|
}
|
||||||
match self.incoming_receiver.try_recv() {
|
match self.incoming_receiver.try_recv() {
|
||||||
Ok(incoming) => {
|
Ok(incoming) => {
|
||||||
println!("INCOMING");
|
println!("INCOMING: {}", utils::shappy(incoming.clone()));
|
||||||
self.handle_incoming(incoming);
|
self.handle_incoming(incoming);
|
||||||
}
|
}
|
||||||
Err(_) => {} // ignore empty channel errors in this PoC
|
Err(_) => {} // ignore empty channel errors in this PoC
|
||||||
@@ -60,7 +60,6 @@ impl SideNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_incoming(&mut self, incoming: SignedOp) {
|
pub fn handle_incoming(&mut self, incoming: SignedOp) {
|
||||||
println!("handle_incoming: {}", shappy(incoming.clone()));
|
|
||||||
self.crdt.apply(incoming);
|
self.crdt.apply(incoming);
|
||||||
// self.trace_crdt();
|
// self.trace_crdt();
|
||||||
}
|
}
|
||||||
@@ -95,8 +94,3 @@ impl SideNode {
|
|||||||
self.crdt.doc.view_sha()
|
self.crdt.doc.view_sha()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shappy(op: SignedOp) -> String {
|
|
||||||
let b = serde_json::to_string(&op).unwrap().into_bytes();
|
|
||||||
sha256::digest(b).to_string()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use bft_json_crdt::json_crdt::SignedOp;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
pub(crate) const KEY_FILE: &str = "keys.pem";
|
pub(crate) const KEY_FILE: &str = "keys.pem";
|
||||||
@@ -31,3 +32,13 @@ pub fn fake_transaction_json(from: String) -> Value {
|
|||||||
"amount": 1
|
"amount": 1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shappy(op: SignedOp) -> String {
|
||||||
|
let b = serde_json::to_string(&op).unwrap().into_bytes();
|
||||||
|
sha256::digest(b).to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shassy(text: String) -> String {
|
||||||
|
let b = text.into_bytes();
|
||||||
|
sha256::digest(b).to_string()
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ use bft_json_crdt::json_crdt::SignedOp;
|
|||||||
use ezsockets::ClientConfig;
|
use ezsockets::ClientConfig;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
|
use crate::utils;
|
||||||
|
|
||||||
pub struct WebSocketClient {
|
pub struct WebSocketClient {
|
||||||
incoming_sender: mpsc::Sender<SignedOp>,
|
incoming_sender: mpsc::Sender<SignedOp>,
|
||||||
handle: ezsockets::Client<WebSocketClient>,
|
handle: ezsockets::Client<WebSocketClient>,
|
||||||
@@ -39,7 +41,16 @@ impl ezsockets::ClientExt for WebSocketClient {
|
|||||||
/// When we receive a text message, apply the crdt operation contained in it to our
|
/// When we receive a text message, apply the crdt operation contained in it to our
|
||||||
/// local crdt.
|
/// local crdt.
|
||||||
async fn on_text(&mut self, text: String) -> Result<(), ezsockets::Error> {
|
async fn on_text(&mut self, text: String) -> Result<(), ezsockets::Error> {
|
||||||
|
let string_sha = utils::shassy(text.clone());
|
||||||
|
println!("received text, sha: {string_sha}");
|
||||||
let incoming: bft_json_crdt::json_crdt::SignedOp = serde_json::from_str(&text).unwrap();
|
let incoming: bft_json_crdt::json_crdt::SignedOp = serde_json::from_str(&text).unwrap();
|
||||||
|
let object_sha = utils::shappy(incoming.clone());
|
||||||
|
println!("deserialized: {}", object_sha);
|
||||||
|
if string_sha != object_sha {
|
||||||
|
println!("SHA mismatch: {string_sha} != {object_sha}");
|
||||||
|
println!("text: {text}");
|
||||||
|
println!("incoming: {incoming:?}");
|
||||||
|
}
|
||||||
self.incoming_sender.send(incoming).await?;
|
self.incoming_sender.send(incoming).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user