1use bytes::{BufMut, Bytes, BytesMut};
2use commonware_consensus::types::{Height, View};
3use commonware_cryptography::Digest;
4use exoware_sdk::keys::Key;
5
6pub const FORMAT_VERSION: u8 = 0;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9#[repr(u8)]
10pub enum RecordKind {
11 HeaderByDigest = 0x10,
12 BlockByDigest = 0x11,
13 NotarizationByView = 0x20,
14 FinalizationByView = 0x30,
15 FinalizedByHeight = 0x31,
16}
17
18impl RecordKind {
19 pub const fn as_u8(self) -> u8 {
20 self as u8
21 }
22
23 pub const fn prefix(self) -> [u8; 2] {
24 [FORMAT_VERSION, self.as_u8()]
25 }
26}
27
28fn key_from_parts(kind: RecordKind, suffix: &[u8]) -> Key {
29 let mut key = BytesMut::with_capacity(2 + suffix.len());
30 key.put_u8(FORMAT_VERSION);
31 key.put_u8(kind.as_u8());
32 key.put_slice(suffix);
33 key.freeze()
34}
35
36fn u64_suffix(value: u64) -> [u8; 8] {
37 value.to_be_bytes()
38}
39
40pub fn header_by_digest<D: Digest>(digest: &D) -> Key {
41 key_from_parts(RecordKind::HeaderByDigest, digest.as_ref())
42}
43
44pub fn block_by_digest<D: Digest>(digest: &D) -> Key {
45 key_from_parts(RecordKind::BlockByDigest, digest.as_ref())
46}
47
48pub fn notarization_by_view(view: View) -> Key {
49 key_from_parts(RecordKind::NotarizationByView, &u64_suffix(view.get()))
50}
51
52pub fn finalization_by_view(view: View) -> Key {
53 key_from_parts(RecordKind::FinalizationByView, &u64_suffix(view.get()))
54}
55
56pub fn finalized_by_height(height: Height) -> Key {
57 key_from_parts(RecordKind::FinalizedByHeight, &u64_suffix(height.get()))
58}
59
60pub fn range_for_kind(kind: RecordKind) -> (Key, Key) {
61 let start = Bytes::copy_from_slice(&kind.prefix());
62 let end = Bytes::copy_from_slice(&[FORMAT_VERSION, kind.as_u8() + 1]);
63 (start, end)
64}