Skip to content

Commit bf47109

Browse files
committed
WIP refactor with generic tlog-tiles
1 parent c5388c9 commit bf47109

File tree

12 files changed

+260
-120
lines changed

12 files changed

+260
-120
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ct_worker/src/batcher_do.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::{
1414
collections::{HashMap, HashSet},
1515
time::Duration,
1616
};
17+
use tlog_tiles::PendingLogEntryTrait;
1718
use tokio::sync::watch::{self, Sender};
1819
#[allow(clippy::wildcard_imports)]
1920
use worker::*;

crates/ct_worker/src/ctlog.rs

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,18 @@ use log::{debug, error, info, trace, warn};
3030
use p256::ecdsa::SigningKey as EcdsaSigningKey;
3131
use serde::{Deserialize, Serialize};
3232
use sha2::{Digest, Sha256};
33-
use static_ct_api::{LogEntry, PendingLogEntry, TileIterator, TreeWithTimestamp};
33+
use static_ct_api::{PendingLogEntry, TileIterator, TreeWithTimestamp};
3434
use std::collections::HashMap;
3535
use std::time::Duration;
3636
use std::{
3737
cmp::{Ord, Ordering},
3838
sync::LazyLock,
3939
};
4040
use thiserror::Error;
41-
use tlog_tiles::{Hash, HashReader, PathElem, Tile, TlogError, TlogTile, HASH_SIZE};
41+
use tlog_tiles::{
42+
Hash, HashReader, LogEntryTrait, PathElem, PendingLogEntryTrait, Tile, TlogError,
43+
TlogIteratorTrait, TlogTile, HASH_SIZE,
44+
};
4245
use tokio::sync::watch::{channel, Receiver, Sender};
4346

4447
/// The maximum tile level is 63 (<c2sp.org/static-ct-api>), so safe to use [`u8::MAX`] as
@@ -354,6 +357,7 @@ impl SequenceState {
354357
edge_tiles.get(&DATA_TILE_KEY).unwrap().b.clone(),
355358
data_tile.tile.width() as usize,
356359
)
360+
.into_entry_iter()
357361
.enumerate()
358362
{
359363
let got = tlog_tiles::record_hash(&entry?.merkle_tree_leaf());
@@ -596,17 +600,18 @@ async fn sequence_entries(
596600
}
597601
let mut overlay = HashMap::new();
598602
let mut n = old_size;
599-
let mut sequenced_entries: Vec<LogEntry> = Vec::with_capacity(entries.len());
600603
let mut sequenced_metadata = Vec::with_capacity(entries.len());
604+
let mut cache_metadata = Vec::with_capacity(entries.len());
601605

602606
for (entry, sender) in entries {
603-
let sequenced_entry = LogEntry {
604-
inner: entry,
605-
leaf_index: n,
606-
timestamp,
607-
};
607+
let metadata = (n, timestamp);
608+
cache_metadata.push((entry.lookup_key(), metadata));
609+
sequenced_metadata.push((sender, metadata));
610+
611+
let sequenced_entry = entry.into_log_entry(metadata);
608612
let tile_leaf = sequenced_entry.tile_leaf();
609613
let merkle_tree_leaf = sequenced_entry.merkle_tree_leaf();
614+
610615
metrics.seq_leaf_size.observe(tile_leaf.len().as_f64());
611616
data_tile.extend(tile_leaf);
612617

@@ -623,7 +628,7 @@ async fn sequence_entries(
623628
)
624629
.map_err(|e| {
625630
SequenceError::NonFatal(format!(
626-
"couldn't compute new hashes for leaf {sequenced_entry:?}: {e}",
631+
"couldn't compute new hashes for leaf at index {n}: {e}",
627632
))
628633
})?;
629634
for (i, h) in hashes.iter().enumerate() {
@@ -639,12 +644,6 @@ async fn sequence_entries(
639644
metrics.seq_data_tile_size.observe(data_tile.len().as_f64());
640645
data_tile.clear();
641646
}
642-
643-
sequenced_metadata.push((
644-
sender,
645-
(sequenced_entry.leaf_index, sequenced_entry.timestamp),
646-
));
647-
sequenced_entries.push(sequenced_entry);
648647
}
649648

650649
// Stage leftover partial data tile, if any.
@@ -768,23 +767,10 @@ async fn sequence_entries(
768767
// only consequence of cache false negatives are duplicated leaves anyway. In fact, an
769768
// error might cause the clients to resubmit, producing more cache false negatives and
770769
// duplicates.
771-
if let Err(e) = cache
772-
.put_entries(
773-
&sequenced_entries
774-
.iter()
775-
.map(|entry| {
776-
(
777-
entry.inner.lookup_key(),
778-
(entry.leaf_index, entry.timestamp),
779-
)
780-
})
781-
.collect::<Vec<_>>(),
782-
)
783-
.await
784-
{
770+
if let Err(e) = cache.put_entries(&cache_metadata).await {
785771
warn!(
786772
"{name}: Cache put failed (entries={}): {e}",
787-
sequenced_entries.len()
773+
cache_metadata.len()
788774
);
789775
}
790776

@@ -2097,23 +2083,24 @@ mod tests {
20972083
{
20982084
let entry = entry.unwrap();
20992085
let idx = n * u64::from(TlogTile::FULL_WIDTH) + i as u64;
2100-
assert_eq!(entry.leaf_index, idx);
2101-
assert!(entry.timestamp <= sth_timestamp);
2086+
let (leaf_index, timestamp) = entry.metadata();
2087+
assert_eq!(leaf_index, idx);
2088+
assert!(timestamp <= sth_timestamp);
21022089
assert_eq!(
21032090
leaf_hashes[usize::try_from(idx).unwrap()],
21042091
tlog_tiles::record_hash(&entry.merkle_tree_leaf())
21052092
);
21062093

2107-
assert!(!entry.inner.certificate.is_empty());
2108-
if entry.inner.is_precert {
2109-
assert!(!entry.inner.pre_certificate.is_empty());
2110-
assert_ne!(entry.inner.issuer_key_hash, [0; 32]);
2094+
assert!(!entry.as_pending_entry().certificate.is_empty());
2095+
if entry.as_pending_entry().is_precert {
2096+
assert!(!entry.as_pending_entry().pre_certificate.is_empty());
2097+
assert_ne!(entry.as_pending_entry().issuer_key_hash, [0; 32]);
21112098
} else {
2112-
assert!(entry.inner.pre_certificate.is_empty());
2113-
assert_eq!(entry.inner.issuer_key_hash, [0; 32]);
2099+
assert!(entry.as_pending_entry().pre_certificate.is_empty());
2100+
assert_eq!(entry.as_pending_entry().issuer_key_hash, [0; 32]);
21142101
}
21152102

2116-
for fp in entry.inner.chain_fingerprints {
2103+
for fp in &entry.as_pending_entry().chain_fingerprints {
21172104
let b = block_on(self.object.fetch(&format!("issuer/{}", hex::encode(fp))))
21182105
.unwrap()
21192106
.unwrap();

crates/ct_worker/src/frontend_worker.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ use p256::pkcs8::EncodePublicKey;
1414
use serde::Serialize;
1515
use serde_with::{base64::Base64, serde_as};
1616
use sha2::{Digest, Sha256};
17-
use static_ct_api::{AddChainRequest, GetRootsResponse, LogEntry, PendingLogEntry, UnixTimestamp};
17+
use static_ct_api::{AddChainRequest, GetRootsResponse, PendingLogEntry};
1818
use std::str::FromStr;
19+
use tlog_tiles::PendingLogEntryTrait;
1920
#[allow(clippy::wildcard_imports)]
2021
use worker::*;
2122

@@ -207,18 +208,14 @@ async fn add_chain_or_pre_chain(
207208

208209
// Check if entry is cached and return right away if so.
209210
let kv = load_cache_kv(env, name)?;
210-
if let Some((leaf_index, timestamp)) = kv
211+
if let Some(metadata) = kv
211212
.get(&BASE64_STANDARD.encode(lookup_key))
212213
.bytes_with_metadata::<SequenceMetadata>()
213214
.await?
214215
.1
215216
{
216217
debug!("{name}: Entry is cached");
217-
let entry = LogEntry {
218-
inner: pending_entry,
219-
leaf_index,
220-
timestamp,
221-
};
218+
let entry = pending_entry.into_log_entry(metadata);
222219
let sct = static_ct_api::signed_certificate_timestamp(signing_key, &entry)
223220
.map_err(|e| e.to_string())?;
224221
return Response::from_json(&sct);
@@ -261,12 +258,8 @@ async fn add_chain_or_pre_chain(
261258
// Return the response from the Batcher directly to the client.
262259
return Ok(response);
263260
}
264-
let (leaf_index, timestamp) = response.json::<(u64, UnixTimestamp)>().await?;
265-
let entry = LogEntry {
266-
inner: pending_entry,
267-
leaf_index,
268-
timestamp,
269-
};
261+
let metadata = response.json::<SequenceMetadata>().await?;
262+
let entry = pending_entry.into_log_entry(metadata);
270263
let sct = static_ct_api::signed_certificate_timestamp(signing_key, &entry)
271264
.map_err(|e| e.to_string())?;
272265
Response::from_json(&sct)

crates/ct_worker/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ use p256::{ecdsa::SigningKey as EcdsaSigningKey, pkcs8::DecodePrivateKey};
1919
use serde::Deserialize;
2020
use serde_bytes::ByteBuf;
2121
use sha2::{Digest, Sha256};
22-
use static_ct_api::{LookupKey, UnixTimestamp};
22+
use static_ct_api::LookupKey;
2323
use std::collections::{HashMap, VecDeque};
2424
use std::io::Write;
2525
use std::sync::{LazyLock, OnceLock};
26+
use tlog_tiles::SequenceMetadata;
2627
use util::now_millis;
2728
#[allow(clippy::wildcard_imports)]
2829
use worker::*;
@@ -114,8 +115,6 @@ struct QueryParams {
114115
name: String,
115116
}
116117

117-
type SequenceMetadata = (u64, UnixTimestamp);
118-
119118
trait CacheWrite {
120119
/// Put the provided sequenced entries into the cache. This does NOT overwrite existing entries.
121120
async fn put_entries(&mut self, entries: &[(LookupKey, SequenceMetadata)]) -> Result<()>;

crates/ct_worker/src/sequencer_do.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use log::{info, warn, Level};
1515
use static_ct_api::PendingLogEntry;
1616
use std::str::FromStr;
1717
use std::time::Duration;
18+
use tlog_tiles::PendingLogEntryTrait;
1819
use tokio::sync::Mutex;
1920
#[allow(clippy::wildcard_imports)]
2021
use worker::*;

crates/static_ct_api/src/rfc6962.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
//! - [cert_checker_test.go](https://github.com/google/certificate-transparency-go/blob/74d106d3a25205b16d571354c64147c5f1f7dbc1/trillian/ctfe/cert_checker_test.go)
2222
2323
use crate::StaticCTError;
24-
use crate::{UnixTimestamp, ValidatedChain};
2524
use der::{
2625
asn1::{Null, OctetString},
2726
oid::{
@@ -33,6 +32,7 @@ use der::{
3332
use serde::{Deserialize, Serialize};
3433
use serde_with::{base64::Base64, serde_as};
3534
use sha2::{Digest, Sha256};
35+
use tlog_tiles::UnixTimestamp;
3636
use x509_util::CertPool;
3737
use x509_verify::{
3838
x509_cert::{
@@ -79,6 +79,15 @@ pub struct GetRootsResponse {
7979
pub certificates: Vec<Vec<u8>>,
8080
}
8181

82+
/// A chain that has been parsed and validated.
83+
pub struct ValidatedChain {
84+
pub certificate: Vec<u8>,
85+
pub is_precert: bool,
86+
pub issuer_key_hash: [u8; 32],
87+
pub issuers: Vec<Vec<u8>>,
88+
pub pre_certificate: Vec<u8>,
89+
}
90+
8291
/// Validates a certificate chain and returns a [`ValidatedChain`].
8392
///
8493
/// # Errors

0 commit comments

Comments
 (0)