Serialization of SignedOp now works; adding to the CRDT doesn't
This commit is contained in:
43
Cargo.lock
generated
43
Cargo.lock
generated
@@ -264,6 +264,12 @@ version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
@@ -298,6 +304,7 @@ dependencies = [
|
||||
"random_color",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with 3.8.1",
|
||||
"sha2 0.10.8",
|
||||
"time 0.1.45",
|
||||
]
|
||||
@@ -803,7 +810,7 @@ dependencies = [
|
||||
"secp256k1",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"serde_with 2.3.3",
|
||||
"sha2 0.10.8",
|
||||
"sha3",
|
||||
"signature",
|
||||
@@ -1177,6 +1184,7 @@ checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.5",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1995,7 +2003,25 @@ dependencies = [
|
||||
"indexmap 1.9.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with_macros",
|
||||
"serde_with_macros 2.3.3",
|
||||
"time 0.3.36",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.2.6",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_with_macros 3.8.1",
|
||||
"time 0.3.36",
|
||||
]
|
||||
|
||||
@@ -2011,6 +2037,18 @@ dependencies = [
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.9.8"
|
||||
@@ -2078,6 +2116,7 @@ dependencies = [
|
||||
"clap",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with 3.8.1",
|
||||
"tokio",
|
||||
"websockets",
|
||||
]
|
||||
|
||||
@@ -22,6 +22,7 @@ rand = "0.8.5"
|
||||
random_color = "0.6.1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.85"
|
||||
serde_with = "3.8.1"
|
||||
sha2 = "0.10.6"
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -17,6 +17,8 @@ use fastcrypto::{
|
||||
traits::{KeyPair, ToFromBytes},
|
||||
// Verifier,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::{serde_as, Bytes};
|
||||
|
||||
/// Anything that can be nested in a JSON CRDT
|
||||
pub trait CrdtNode: CrdtNodeFromValue + Hashable + Clone {
|
||||
@@ -106,15 +108,18 @@ pub struct BaseCrdt<T: CrdtNode> {
|
||||
}
|
||||
|
||||
/// An [`Op<Value>`] with a few bits of extra metadata
|
||||
#[derive(Clone)]
|
||||
#[serde_as]
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct SignedOp {
|
||||
// Note that this can be different from the author of the inner op as the inner op could have been created
|
||||
// by a different person
|
||||
author: AuthorId,
|
||||
/// Signed hash using priv key of author. Effectively [`OpID`] Use this as the ID to figure out what has been delivered already
|
||||
#[serde_as(as = "Bytes")]
|
||||
pub signed_digest: SignedDigest,
|
||||
pub inner: Op<JsonValue>,
|
||||
/// List of causal dependencies
|
||||
#[serde_as(as = "Vec<Bytes>")]
|
||||
pub depends_on: Vec<SignedDigest>,
|
||||
}
|
||||
|
||||
@@ -244,7 +249,7 @@ impl<T: CrdtNode + DebugView> BaseCrdt<T> {
|
||||
}
|
||||
|
||||
/// An enum representing a JSON value
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum JsonValue {
|
||||
Null,
|
||||
Bool(bool),
|
||||
|
||||
@@ -81,7 +81,7 @@ pub fn parse_field(path: Vec<PathSegment>) -> Option<String> {
|
||||
}
|
||||
|
||||
/// Represents a single node in a CRDT
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct Op<T>
|
||||
where
|
||||
T: CrdtNode,
|
||||
|
||||
@@ -14,6 +14,7 @@ bft-crdt-derive = { path = "../crates/bft-json-crdt/bft-crdt-derive" }
|
||||
# serde_cbor = "0.11.2" # move to this once we need to pack things in CBOR
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.117"
|
||||
serde_with = "3.8.1"
|
||||
|
||||
[features]
|
||||
default = ["bft", "logging-list", "logging-json"]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use bft_crdt_derive::add_crdt_fields;
|
||||
use bft_json_crdt::json_crdt::SignedOp;
|
||||
use bft_json_crdt::keypair::KeyPair;
|
||||
use bft_json_crdt::{
|
||||
json_crdt::{BaseCrdt, CrdtNode, IntoCrdtNode},
|
||||
@@ -15,27 +16,38 @@ pub(crate) async fn start() -> Result<(), websockets::WebSocketError> {
|
||||
println!("connecting to websocket at ws://127.0.0.1:8080/");
|
||||
let mut ws = WebSocket::connect("ws://127.0.0.1:8080/").await?;
|
||||
|
||||
// generate a placeholder transaction
|
||||
let json = generate_transaction().unwrap();
|
||||
|
||||
// set up a new BFT-CRDT
|
||||
let keys = make_keypair();
|
||||
let mut bft_crdt = BaseCrdt::<ListExample>::new(&keys);
|
||||
println!("Generated a new CRDT with public key: {}", keys.public());
|
||||
|
||||
// generate a placeholder transaction
|
||||
let transaction = generate_transaction();
|
||||
|
||||
let json = convert_to_json(&transaction).unwrap();
|
||||
|
||||
// next job is to keep adding to this guy
|
||||
let _a = bft_crdt.doc.list.insert(ROOT_ID, 'a').sign(&keys);
|
||||
let signed_op = bft_crdt.doc.list.insert(ROOT_ID, json.clone()).sign(&keys);
|
||||
println!("SignedOp before send is: {:?}", signed_op);
|
||||
|
||||
let mut interval = every_two_seconds();
|
||||
loop {
|
||||
interval.tick().await;
|
||||
println!("Sending: {}", json);
|
||||
ws.send_text(json.clone()).await?;
|
||||
println!("Sending: {:?}", signed_op);
|
||||
ws.send_text(serde_json::to_string(&signed_op).unwrap())
|
||||
.await?;
|
||||
|
||||
let msg = ws.receive().await?;
|
||||
println!("Received: {:?}", msg);
|
||||
|
||||
// deserialize the received Frame into a string
|
||||
let msg = msg.into_text().unwrap().0;
|
||||
|
||||
// deserialize the message into a Transaction struct
|
||||
let operation: SignedOp = serde_json::from_str(&msg).unwrap();
|
||||
|
||||
// TODO: bft_crdt.apply() changes in here when we receive socket input from other nodes
|
||||
bft_crdt.apply(msg);
|
||||
bft_crdt.apply(operation);
|
||||
println!("New crdt state is: {}", bft_crdt.doc.view())
|
||||
}
|
||||
}
|
||||
@@ -59,15 +71,17 @@ struct Transaction {
|
||||
amount: f64,
|
||||
}
|
||||
|
||||
fn generate_transaction() -> serde_json::Result<String> {
|
||||
let transaction = Transaction {
|
||||
fn generate_transaction() -> Transaction {
|
||||
Transaction {
|
||||
from: "Alice".to_string(),
|
||||
to: "Bob".to_string(),
|
||||
amount: 100.0,
|
||||
path: vec![],
|
||||
id: [0; ED25519_PUBLIC_KEY_LENGTH],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_to_json(transaction: &Transaction) -> serde_json::Result<String> {
|
||||
let json = serde_json::to_string(&transaction).unwrap();
|
||||
Ok(json)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user