Create an entry
We'll now create a new Entry and all its constituent fields.
Prerequisites
A basic knowledge of the Rust programming language and executing commands in the terminal will be helpful for completing this tutorial. Some of the steps below also require cargo to be installed.
Additionally, knowledge of the Path API would be helpful. If you're not yet familiar, please see our dedicated tutorial for paths.
Setup
- Create a new directory on your filesystem and name it something like
entry. - Using your terminal, run
cargo initwithin the newly created directory. - After than, run
cargo add willow_25.
Create an entry
Open src/main.rs, delete its contents, and enter the following:
use std::time::{SystemTime, UNIX_EPOCH};
use willow_25::{Component, Entry, NamespaceId25, Path, PayloadDigest25, SubspaceId25};
fn main() {
let namespace_id = NamespaceId25::new_communal();
let (subspace_id, _key) = SubspaceId25::new();
let path_component = Component::new(b"blog").unwrap();
let path = Path::new_singleton(path_component).unwrap();
let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let timestamp = duration.as_micros();
let payload = b"hello";
let digest = PayloadDigest25::new_from_slice(payload);
let entry = Entry::new(
namespace_id,
subspace_id,
path,
timestamp as u64,
payload.len() as u64,
digest,
);
println!("An entry: {:?}", entry);
}
In your terminal, run cargo run, and you should see the following output:
An entry: Entry { namespace_id: NamespaceId25(VerifyingKey(CompressedEdwardsY: [58, 201, 45, 13, 175, 191, 11, 28, 73, 49, 60, 190, 9, 158, 246, 26, 101, 207, 43, 28, 168, 36, 63, 119, 3, 227, 110, 216, 118, 15, 7, 254]), EdwardsPoint{
X: FieldElement51([673775377204752, 1687576133411338, 1460558585376021, 1267680291689903, 536305151824157]),
Y: FieldElement51([226586031971318, 1307247315751625, 18493065931223, 1435453376454164, 1073175921009958]),
Z: FieldElement51([848058597170382, 1415746105881890, 330513674268485, 1543466013865212, 1236432826371107]),
T: FieldElement51([1896093938592885, 1037901781905685, 296713486533008, 988735422203083, 793700961884063])
})), subspace_id: SubspaceId25([198, 22, 67, 255, 23, 99, 21, 212, 200, 107, 196, 41, 12, 202, 226, 38, 211, 60, 42, 249, 180, 58, 122, 226, 68, 198, 65, 132, 196, 142, 196, 158]), path: Path([Component([98, 108, 111, 103])]), timestamp: 1749919349328976, payload_digest: PayloadDigest25(Hash("ea8f163db38682925e4491c5e58d4bb3506ef8c14eb78a86e908c5624a67200f")), payload_length: 5 }Compare with another entry
Next, we'll compare two Entries using Entry::is_newer_than.
Add the following tosrc/main.rs:
use std::time::{SystemTime, UNIX_EPOCH};
use willow_25::{Component, Entry, NamespaceId25, Path, PayloadDigest25, SubspaceId25};
fn main() {
let namespace_id = NamespaceId25::new_communal();
let (subspace_id, _key) = SubspaceId25::new();
let path_component = Component::new(b"blog").unwrap();
let path = Path::new_singleton(path_component).unwrap();
let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let timestamp = duration.as_micros();
let payload = b"hello";
let digest = PayloadDigest25::new_from_slice(payload);
let entry = Entry::new(
namespace_id,
subspace_id,
path,
timestamp as u64,
payload.len() as u64,
digest,
);
let payload2 = b"bye-bye";
let digest2 = PayloadDigest25::new_from_slice(payload2);
let entry2 = Entry::new(
entry.namespace_id().clone(),
entry.subspace_id().clone(),
entry.path().clone(),
entry.timestamp() + 1,
payload2.len() as u64,
digest2,
);
if entry2.is_newer_than(&entry) {
println!("entry2 is newer than entry!")
} else {
panic!("entry is newer than entry2?!")
}
}
In your terminal, run cargo run, and you should see the following output:
An entry: Entry { namespace_id: NamespaceId25(VerifyingKey(CompressedEdwardsY: [58, 201, 45, 13, 175, 191, 11, 28, 73, 49, 60, 190, 9, 158, 246, 26, 101, 207, 43, 28, 168, 36, 63, 119, 3, 227, 110, 216, 118, 15, 7, 254]), EdwardsPoint{
X: FieldElement51([673775377204752, 1687576133411338, 1460558585376021, 1267680291689903, 536305151824157]),
Y: FieldElement51([226586031971318, 1307247315751625, 18493065931223, 1435453376454164, 1073175921009958]),
Z: FieldElement51([848058597170382, 1415746105881890, 330513674268485, 1543466013865212, 1236432826371107]),
T: FieldElement51([1896093938592885, 1037901781905685, 296713486533008, 988735422203083, 793700961884063])
})), subspace_id: SubspaceId25([198, 22, 67, 255, 23, 99, 21, 212, 200, 107, 196, 41, 12, 202, 226, 38, 211, 60, 42, 249, 180, 58, 122, 226, 68, 198, 65, 132, 196, 142, 196, 158]), path: Path([Component([98, 108, 111, 103])]), timestamp: 1749919349328976, payload_digest: PayloadDigest25(Hash("ea8f163db38682925e4491c5e58d4bb3506ef8c14eb78a86e908c5624a67200f")), payload_length: 5 }
entry2 is newer than entry!Check if this entry would be pruned by another
Next, we'll compare two Entries using Entry::is_pruned_by.
Add the following tosrc/main.rs:
use std::time::{SystemTime, UNIX_EPOCH};
use willow_25::{Component, Entry, NamespaceId25, Path, PayloadDigest25, SubspaceId25};
fn main() {
let namespace_id = NamespaceId25::new_communal();
let (subspace_id, _key) = SubspaceId25::new();
let path_component = Component::new(b"blog").unwrap();
let path = Path::new_singleton(path_component).unwrap();
let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let timestamp = duration.as_micros();
let payload = b"hello";
let digest = PayloadDigest25::new_from_slice(payload);
let entry = Entry::new(
namespace_id,
subspace_id,
path,
timestamp as u64,
payload.len() as u64,
digest,
);
let payload2 = b"bye-bye";
let digest2 = PayloadDigest25::new_from_slice(payload2);
let entry2 = Entry::new(
entry.namespace_id().clone(),
entry.subspace_id().clone(),
entry.path().clone(),
entry.timestamp() + 1,
payload2.len() as u64,
digest2,
);
if entry2.is_newer_than(&entry) {
println!("entry2 is newer than entry!")
} else {
panic!("entry is newer than entry2?!")
}
let payload3 = b"ahem!";
let digest3 = PayloadDigest25::new_from_slice(payload3);
let path3 = Path::new_empty();
let entry3 = Entry::new(
entry.namespace_id().clone(),
entry.subspace_id().clone(),
path3,
entry2.timestamp() + 1,
payload3.len() as u64,
digest3,
);
if entry2.is_pruned_by(&entry3) {
println!("entry2 would be pruned by entry3!")
} else {
panic!("entry2 would not be pruned by entry3?!")
}
}
In your terminal, run cargo run, and you should see the following output:
An entry: Entry { namespace_id: NamespaceId25(VerifyingKey(CompressedEdwardsY: [238, 200, 114, 117, 26, 29, 136, 170, 234, 104, 126, 222, 236, 79, 209, 42, 75, 92, 148, 1, 107, 146, 229, 65, 85, 173, 141, 16, 79, 46, 123, 255]), EdwardsPoint{
X: FieldElement51([553439976806818, 1945865133345110, 1313476417278051, 1102478961591250, 2222267068905665]),
Y: FieldElement51([401547046410818, 1641954355329621, 1087392381391398, 1058071421824121, 2073330594693493]),
Z: FieldElement51([372645249848720, 2021845941972242, 2108114938331079, 335834792169594, 2249724189577241]),
T: FieldElement51([792488924576799, 962708462999171, 720586698282066, 1214604921646343, 1623414282094433])
})), subspace_id: SubspaceId25([210, 108, 7, 93, 49, 196, 86, 76, 169, 227, 43, 224, 153, 208, 56, 114, 150, 161, 208, 83, 56, 194, 114, 156, 9, 133, 195, 215, 1, 147, 149, 233]), path: Path([Component([98, 108, 111, 103])]), timestamp: 1750067934614347, payload_digest: PayloadDigest25(Hash("ea8f163db38682925e4491c5e58d4bb3506ef8c14eb78a86e908c5624a67200f")), payload_length: 5 }
entry2 is newer than entry!
entry2 would be pruned by entry3!Summary
In this tutorial we used the Entry API to create and compare entries. We also used various APIs from the willow_25 crate, such as NamespaceId25 and PayloadDigest25, to provide the details we needed to create an Entry.
Entries come into their element when you have many of them. In the next tutorial, we will work with groupings.