Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,225 changes: 202 additions & 1,023 deletions Cargo.lock

Large diffs are not rendered by default.

23 changes: 13 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["crates/*"]
members = ["crates/*", "packages/sdk-rs"]
resolver = "3"

[workspace.package]
Expand Down Expand Up @@ -28,6 +28,7 @@ unnecessary-box-returns = "warn"
unnecessary-debug-formatting = "warn"

[workspace.dependencies]
allocator-api2 = "0.4"
alloy = "1"
alloy-chains = "0.2"
alloy-contract = "1.7"
Expand All @@ -43,9 +44,9 @@ alloy-transport-ws = "1.7"
auto_impl = "1.3"
axum = { version = "0.8", default-features = false }
axum-extra = "0.12"
backon = "1.6"
bitcode = "0.6"
bump-scope = { version = "2.2", features = ["nightly"] }
bytemuck = "1"
bump-scope = { version = "2.2", features = ["allocator-api2-04"] }
bytes = "1.11"
cfg-if = "1.0"
clap = { version = "4.5", features = ["derive"] }
Expand All @@ -58,6 +59,8 @@ dyn-clone = "1.0"
eyre = "0.6"
futures = "0.3"
hex = "0.4"
http = "1.4"
http-body-util = "0.1.3"
itoa = "1.0"
jiff = "0.2"
once_cell = { version = "1.21", default-features = false }
Expand All @@ -83,19 +86,19 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
url = "2.5"


crypto-common = "0.2.0-rc.5"
digest = "0.11.0-rc.4"
hybrid-array = "0.4.5"
ripemd = "0.2.0-rc.3"
sha1 = "0.11.0-rc.3"
sha2 = "0.11.0-rc.3"
sha3 = "0.11.0-rc.3"
crypto-common = "0.1"
digest = "0.10"
ripemd = "0.1"
sha1 = "0.10"
sha2 = "0.10"
sha3 = "0.10"

tempfile = "3"
uts-bmt = { version = "0.1.1", path = "crates/bmt" }
uts-contracts = { version = "=0.1.0-alpha.0", path = "crates/contracts" }
uts-core = { version = "=0.1.0-alpha.0", path = "crates/core" }
uts-journal = { version = "0.1.0", path = "crates/journal" }
uts-sdk = { version = "=0.1.0-alpha.0", path = "packages/sdk-rs" }
uts-sql = { version = "=0.1.0-alpha.0", path = "crates/sql" }
uts-stamper = { version = "=0.1.0-alpha.0", path = "crates/stamper" }

Expand Down
9 changes: 0 additions & 9 deletions crates/bmt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,13 @@ repository.workspace = true
version = "0.1.1"

[dependencies]
bytemuck = { workspace = true }
digest.workspace = true
hybrid-array = { workspace = true, features = ["bytemuck"] }

[dev-dependencies]
alloy-primitives.workspace = true
alloy-sol-types.workspace = true
commonware-cryptography = "0.0.63" # for benchmarks
commonware-storage = "0.0.63" # for benchmarks
criterion.workspace = true
sha2.workspace = true
sha3.workspace = true

[[bench]]
harness = false
name = "tree_construction"

[lints]
workspace = true
96 changes: 0 additions & 96 deletions crates/bmt/benches/tree_construction.rs

This file was deleted.

45 changes: 27 additions & 18 deletions crates/bmt/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
#![feature(maybe_uninit_fill)]
#![feature(likely_unlikely)]
//! High performance binary Merkle tree implementation in Rust.

use bytemuck::Pod;
use digest::{Digest, FixedOutputReset, Output};
use std::hint::unlikely;
use digest::{Digest, FixedOutputReset, Output, typenum::Unsigned};

/// Prefix byte to distinguish internal nodes from leaves when hashing.
pub const INNER_NODE_PREFIX: u8 = 0x01;
Expand All @@ -28,7 +24,7 @@ pub struct UnhashedMerkleTree<D: Digest> {

impl<D: Digest + FixedOutputReset> MerkleTree<D>
where
Output<D>: Pod + Copy,
Output<D>: Copy,
{
/// Constructs a new Merkle tree from the given hash leaves.
pub fn new(data: &[Output<D>]) -> Self {
Expand Down Expand Up @@ -62,9 +58,9 @@ where
std::ptr::copy_nonoverlapping(src, dst, raw_len);

// SAFETY: capacity + len is within the allocated size of `tree`
maybe_uninit
.get_unchecked_mut(len + raw_len..)
.write_filled(Output::<D>::default());
for e in maybe_uninit.get_unchecked_mut(len + raw_len..) {
e.write(Output::<D>::default());
}
}

UnhashedMerkleTree { buffer: nodes, len }
Expand Down Expand Up @@ -100,8 +96,12 @@ where

/// Returns the raw bytes of the Merkle tree nodes
#[inline]
pub fn as_raw_bytes(&self) -> &[u8] {
bytemuck::cast_slice(&self.nodes)
pub fn to_raw_bytes(&self) -> Vec<u8> {
self.nodes
.iter()
.flat_map(|node| node.as_slice())
.copied()
.collect()
}

/// From raw bytes, reconstruct the Merkle tree
Expand All @@ -113,8 +113,17 @@ where
/// Merkle tree structure.
#[inline]
pub fn from_raw_bytes(bytes: &[u8]) -> Self {
let nodes: &[Output<D>] = bytemuck::cast_slice(bytes);
assert!(nodes.len().is_multiple_of(2));
assert!(
bytes.len().is_multiple_of(D::OutputSize::USIZE),
"Invalid raw bytes length"
);
let len = bytes.len() / D::OutputSize::USIZE;
assert!(len.is_multiple_of(2));
let mut nodes: Vec<Output<D>> = Vec::with_capacity(len);
for chunk in bytes.chunks_exact(D::OutputSize::USIZE) {
let node = Output::<D>::from_slice(chunk);
nodes.push(*node);
}
assert_eq!(nodes[0], Output::<D>::default());
let len = nodes.len() / 2;
Self {
Expand All @@ -126,7 +135,7 @@ where

impl<D: Digest + FixedOutputReset> UnhashedMerkleTree<D>
where
Output<D>: Pod + Copy,
Output<D>: Copy,
{
/// Finalizes the Merkle tree by hashing internal nodes
pub fn finalize(self) -> MerkleTree<D> {
Expand Down Expand Up @@ -181,7 +190,7 @@ impl<'a, D: Digest> Iterator for SiblingIter<'a, D> {
type Item = (NodePosition, &'a Output<D>);

fn next(&mut self) -> Option<Self::Item> {
if unlikely(self.current <= 1) {
if self.current <= 1 {
return None;
}
let side = if (self.current & 1) == 0 {
Expand Down Expand Up @@ -229,7 +238,7 @@ mod tests {

fn test_merkle_tree<D: Digest + FixedOutputReset>()
where
Output<D>: Pod + Copy,
Output<D>: Copy,
{
let leaves = vec![
D::digest(b"leaf1"),
Expand Down Expand Up @@ -262,7 +271,7 @@ mod tests {

fn test_proof<D: Digest + FixedOutputReset>()
where
Output<D>: Pod + Copy,
Output<D>: Copy,
{
let leaves = vec![
D::digest(b"apple"),
Expand Down Expand Up @@ -313,7 +322,7 @@ mod tests {

for i in 0..=10u32 {
let tree = MerkleTree::<Keccak256>::new(&leaves[..2usize.pow(i)]);
let root = B256::new(tree.root().0);
let root = B256::from_slice(tree.root());
println!("bytes32({root}),");
}
}
Expand Down
4 changes: 0 additions & 4 deletions crates/calendar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ axum = { workspace = true, default-features = false, features = [
"json",
] } # http2 only
bump-scope.workspace = true
bytemuck = { workspace = true }
bytes = { workspace = true }
config = { workspace = true }
digest = { workspace = true }
Expand All @@ -48,9 +47,6 @@ uts-core = { workspace = true, features = ["bytes"] }
uts-journal = { workspace = true }
uts-stamper = { workspace = true }

hashbrown_15 = { package = "hashbrown", version = "0.15", features = ["nightly"] } # why?
hashbrown_16 = { package = "hashbrown", version = "0.16", features = ["nightly"] } # why?

[dev-dependencies]
criterion.workspace = true

Expand Down
3 changes: 0 additions & 3 deletions crates/calendar/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#![feature(thread_sleep_until)]
#![feature(allocator_api)]

//! Calendar server library.

#[macro_use]
Expand Down
21 changes: 13 additions & 8 deletions crates/calendar/src/routes/ots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ use axum::{
};
use bump_scope::Bump;
use bytes::BytesMut;
use digest::Digest;
use digest::{Digest, Output};
use sha3::Keccak256;
use std::{cell::RefCell, sync::Arc};
use uts_core::codec::{
Encode,
v1::{EASTimestamped, PendingAttestation, Timestamp},
use uts_core::{
alloc::SliceExt,
codec::{
Encode,
v1::{EASTimestamped, PendingAttestation, Timestamp},
},
};
use uts_journal::Error;
use uts_stamper::{kv::DbExt, sql, sql::AttestationResult};
Expand Down Expand Up @@ -80,7 +83,8 @@ pub fn submit_digest_inner(
hasher.finalize_reset()
});

let undeniable_sig = signer.sign_hash_sync(&hash.0.into()).unwrap();
let hash = B256::from_slice(&hash);
let undeniable_sig = signer.sign_hash_sync(&hash).unwrap();
undeniable_sig.as_erc2098()
};

Expand All @@ -97,8 +101,8 @@ pub fn submit_digest_inner(

let mut builder = Timestamp::builder_in(&*bump);
builder
.prepend(recv_timestamp.to_vec_in(&bump))
.append(undeniable_sig.to_vec_in(&bump))
.prepend(SliceExt::to_vec_in(recv_timestamp.as_slice(), &bump))
.append(SliceExt::to_vec_in(undeniable_sig.as_slice(), &bump))
.keccak256();

let mut commitment = [0u8; 32];
Expand Down Expand Up @@ -152,8 +156,9 @@ pub async fn get_timestamp(
.expect("DB error")
.expect("bug: entry not found");

let commitment = Output::<Keccak256>::from_slice(commitment.as_slice());
let proof = trie
.get_proof_iter(bytemuck::cast_ref(&*commitment))
.get_proof_iter(commitment)
.expect("bug: proof not found");

let mut builder = Timestamp::builder();
Expand Down
6 changes: 5 additions & 1 deletion crates/calendar/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ pub fn updater() {
// Note: This behavior is different from the async version, which skips missed ticks.
let now_instant = Instant::now();
if next_tick > now_instant {
std::thread::sleep_until(next_tick);
let now = Instant::now();

if let Some(delay) = next_tick.checked_duration_since(now) {
std::thread::sleep(delay);
}
} else {
// If we've fallen behind, resynchronize to avoid accumulating drift.
next_tick = now_instant;
Expand Down
Loading