#[cfg(feature = "async-std")]
use async_std::main as async_main;
use hypercore::{Hypercore, HypercoreBuilder, HypercoreError, PartialKeypair, Storage};
use hypercore_schema::{RequestBlock, RequestUpgrade};
use tempfile::Builder;
#[cfg(feature = "tokio")]
use tokio::main as async_main;
#[async_main]
async fn main() {
let dir = Builder::new()
.prefix("examples_replication")
.tempdir()
.unwrap()
.keep();
let overwrite = true;
let storage = Storage::new_disk(&dir, overwrite)
.await
.expect("Could not create disk storage");
let mut origin_hypercore = HypercoreBuilder::new(storage)
.build()
.await
.expect("Could not create disk hypercore");
let batch: &[&[u8]] = &[b"Hello, ", b"from ", b"replicated ", b"hypercore!"];
origin_hypercore.append_batch(batch).await.unwrap();
let origin_public_key = origin_hypercore.key_pair().public;
let mut replicated_hypercore = HypercoreBuilder::new(
Storage::new_memory()
.await
.expect("Could not create memory storage"),
)
.key_pair(PartialKeypair {
public: origin_public_key,
secret: None,
})
.build()
.await
.expect("Could not create memory hypercore");
replicate_index(&mut origin_hypercore, &mut replicated_hypercore, 3).await;
replicate_index(&mut origin_hypercore, &mut replicated_hypercore, 0).await;
replicate_index(&mut origin_hypercore, &mut replicated_hypercore, 2).await;
replicate_index(&mut origin_hypercore, &mut replicated_hypercore, 1).await;
println!(
"{}{}{}{}",
format_res(replicated_hypercore.get(0).await),
format_res(replicated_hypercore.get(1).await),
format_res(replicated_hypercore.get(2).await),
format_res(replicated_hypercore.get(3).await)
); }
async fn replicate_index(
origin_hypercore: &mut Hypercore,
replicated_hypercore: &mut Hypercore,
request_index: u64,
) {
let missing_nodes = origin_hypercore
.missing_nodes(request_index)
.await
.expect("Could not get missing nodes");
let upgrade_start = replicated_hypercore.info().contiguous_length;
let upgrade_length = origin_hypercore.info().contiguous_length - upgrade_start;
let proof = origin_hypercore
.create_proof(
Some(RequestBlock {
index: request_index,
nodes: missing_nodes,
}),
None,
None,
Some(RequestUpgrade {
start: upgrade_start,
length: upgrade_length,
}),
)
.await
.expect("Creating proof error")
.expect("Could not get proof");
assert!(
replicated_hypercore
.verify_and_apply_proof(&proof)
.await
.expect("Verifying and applying proof failed")
);
}
fn format_res(res: Result<Option<Vec<u8>>, HypercoreError>) -> String {
match res {
Ok(Some(bytes)) => String::from_utf8(bytes).expect("Shouldn't fail in example"),
Ok(None) => "Got None in feed".to_string(),
Err(e) => format!("Error getting value from feed, reason = {e:?}"),
}
}