mod habitat_record;
mod key_state_record;
use crate::cesr::counting::{ctr_dex_1_0, BaseCounter, Counter};
use crate::cesr::dater::Dater;
use crate::cesr::diger::Diger;
use crate::cesr::indexing::siger::Siger;
use crate::cesr::num_dex;
use crate::cesr::number::Number;
use crate::cesr::prefixer::Prefixer;
use crate::cesr::saider::Saider;
use crate::cesr::seqner::Seqner;
use crate::cesr::verfer::Verfer;
use crate::keri::core::eventing::Kever;
use crate::keri::core::filing::{BaseFiler, Filer, FilerDefaults};
use crate::keri::core::serdering::{Serder, SerderKERI};
use crate::keri::db::dbing::keys::dg_key;
use crate::keri::db::dbing::LMDBer;
use crate::keri::db::errors::DBError;
use crate::keri::db::koming::{Komer, SerialKind};
use crate::keri::db::subing::catcesr::CatCesrSuber;
use crate::keri::db::subing::catcesrioset::CatCesrIoSetSuber;
use crate::keri::db::subing::cesr::CesrSuber;
use crate::keri::db::subing::cesrioset::CesrIoSetSuber;
use crate::keri::db::subing::dup::DupSuber;
use crate::keri::db::subing::iodup::IoDupSuber;
use crate::keri::db::subing::on::OnSuber;
use crate::keri::db::subing::oniodup::OnIoDupSuber;
use crate::keri::db::subing::serder::SerderSuber;
use crate::keri::db::subing::{Suber, Utf8Codec};
use crate::keri::KERIError;
use crate::Matter;
use chrono::DateTime;
pub use habitat_record::HabitatRecord;
use indexmap::IndexSet;
pub use key_state_record::KeyStateRecord;
pub use key_state_record::StateEERecord;
use num_bigint::BigUint;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EventSourceRecord {
pub local: bool,
}
impl EventSourceRecord {
pub fn new() -> Self {
EventSourceRecord { local: true }
}
pub fn with_local(local: bool) -> Self {
EventSourceRecord { local }
}
pub fn to_map(&self) -> HashMap<String, bool> {
let mut map = HashMap::new();
map.insert("local".to_string(), self.local);
map
}
pub fn from_map(map: &HashMap<String, bool>) -> Option<Self> {
map.get("local").map(|&local| EventSourceRecord { local })
}
}
impl Default for EventSourceRecord {
fn default() -> Self {
Self::new()
}
}
impl IntoIterator for EventSourceRecord {
type Item = (String, bool);
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
vec![("local".to_string(), self.local)].into_iter()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LocationRecord {
pub url: String,
}
impl LocationRecord {
pub fn new(url: String) -> Self {
Self { url }
}
pub fn is_nullified(&self) -> bool {
self.url.is_empty()
}
pub fn to_map(&self) -> HashMap<String, String> {
let mut map = HashMap::new();
map.insert("url".to_string(), self.url.clone());
map
}
}
impl IntoIterator for LocationRecord {
type Item = (String, String);
type IntoIter = std::collections::hash_map::IntoIter<String, String>;
fn into_iter(self) -> Self::IntoIter {
self.to_map().into_iter()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EndpointRecord {
pub allowed: Option<bool>,
pub enabled: Option<bool>,
pub name: String,
}
impl EndpointRecord {
pub fn new() -> Self {
Self {
allowed: None,
enabled: None,
name: String::new(),
}
}
pub fn with_values(allowed: Option<bool>, enabled: Option<bool>, name: String) -> Self {
Self {
allowed,
enabled,
name,
}
}
pub fn is_allowed(&self) -> Option<bool> {
self.allowed
}
pub fn is_enabled(&self) -> Option<bool> {
self.enabled
}
pub fn set_allowed(&mut self, allowed: bool) {
self.allowed = Some(allowed);
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = Some(enabled);
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
pub fn to_map(&self) -> HashMap<String, serde_json::Value> {
let mut map = HashMap::new();
map.insert("allowed".to_string(), serde_json::Value::from(self.allowed));
map.insert("enabled".to_string(), serde_json::Value::from(self.enabled));
map.insert(
"name".to_string(),
serde_json::Value::String(self.name.clone()),
);
map
}
}
impl Default for EndpointRecord {
fn default() -> Self {
Self::new()
}
}
impl IntoIterator for EndpointRecord {
type Item = (String, serde_json::Value);
type IntoIter = std::collections::hash_map::IntoIter<String, serde_json::Value>;
fn into_iter(self) -> Self::IntoIter {
self.to_map().into_iter()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct LocationKey {
pub eid: String, pub scheme: String, }
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct EndpointKey {
pub cid: String, pub role: String, pub eid: String, }
impl LocationKey {
pub fn new(eid: String, scheme: String) -> Self {
Self { eid, scheme }
}
}
impl EndpointKey {
pub fn new(cid: String, role: String, eid: String) -> Self {
Self { cid, role, eid }
}
}
pub struct Baser<'db> {
lmdber: Arc<&'db LMDBer>,
pub prefixes: IndexSet<String>,
pub groups: IndexSet<String>,
pub kevers: HashMap<String, Kever<'db>>,
pub habs: Komer<'db, HabitatRecord>,
pub names: Suber<'db>,
pub evts: Suber<'db>,
pub fels: OnSuber<'db>,
pub kels: OnIoDupSuber<'db, Utf8Codec>,
pub fons: CesrSuber<'db, Number>,
pub esrs: Komer<'db, EventSourceRecord>,
pub dtss: DupSuber<'db>,
pub sdts: CesrSuber<'db, Dater>,
pub rpys: SerderSuber<'db, SerderKERI>,
pub ssgs: CatCesrIoSetSuber<'db, Siger>,
pub scgs: CatCesrIoSetSuber<'db, Verfer>,
pub rpes: CesrIoSetSuber<'db, Saider>,
pub aess: Suber<'db>,
pub sigs: DupSuber<'db>,
pub wigs: DupSuber<'db>,
pub wits: IoDupSuber<'db>,
pub rcts: DupSuber<'db>,
pub vrcs: DupSuber<'db>,
pub states: Komer<'db, KeyStateRecord>,
pub locs: Komer<'db, LocationRecord>,
pub ends: Komer<'db, EndpointRecord>,
pub eans: CesrSuber<'db, Saider>,
pub lans: CesrSuber<'db, Saider>,
pub pses: IoDupSuber<'db>,
}
impl<'db> Filer for Baser<'db> {
fn defaults() -> FilerDefaults {
BaseFiler::defaults()
}
#[cfg(target_os = "windows")]
const TAIL_DIR_PATH: &'static str = "keri\\db";
#[cfg(not(target_os = "windows"))]
const TAIL_DIR_PATH: &'static str = "keri/db";
#[cfg(target_os = "windows")]
const ALT_TAIL_DIR_PATH: &'static str = ".keri\\db";
#[cfg(not(target_os = "windows"))]
const ALT_TAIL_DIR_PATH: &'static str = ".keri/db";
const TEMP_PREFIX: &'static str = "keri_db_";
}
impl<'db> Baser<'db> {
pub const MAX_NAMED_DBS: u32 = 10;
pub fn new(lmdber: Arc<&'db LMDBer>) -> Result<Self, DBError> {
let baser = Baser {
lmdber: lmdber.clone(),
prefixes: IndexSet::new(),
groups: IndexSet::new(),
kevers: HashMap::new(),
evts: Suber::new(lmdber.clone(), "evts.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
fels: OnSuber::new(lmdber.clone(), "fels.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
kels: OnIoDupSuber::new(lmdber.clone(), "kels.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
fons: CesrSuber::<Number>::new(lmdber.clone(), "fons.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
esrs: Komer::new(lmdber.clone(), "esrs.", SerialKind::Json)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
dtss: DupSuber::new(lmdber.clone(), "dtss.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
rpys: SerderSuber::new(lmdber.clone(), "rpys", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
sdts: CesrSuber::new(lmdber.clone(), "sdts", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
ssgs: CatCesrIoSetSuber::new(
lmdber.clone(),
"ssgs.",
vec!["siger".to_string()],
None,
false,
)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
scgs: CatCesrIoSetSuber::new(
lmdber.clone(),
"scgs.",
vec!["verfer".to_string(), "cigar".to_string()],
None,
false,
)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
rpes: CesrIoSetSuber::new(lmdber.clone(), "rpes.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
aess: Suber::new(lmdber.clone(), "aess.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
sigs: DupSuber::new(lmdber.clone(), "sigs.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
wigs: DupSuber::new(lmdber.clone(), "wigs.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
wits: IoDupSuber::new(lmdber.clone(), "wits.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
rcts: DupSuber::new(lmdber.clone(), "rcts.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
vrcs: DupSuber::new(lmdber.clone(), "vrcs.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
states: Komer::new(lmdber.clone(), "stts.", SerialKind::Json)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
ends: Komer::new(lmdber.clone(), "stts.", SerialKind::Json)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
locs: Komer::new(lmdber.clone(), "stts.", SerialKind::Json)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
habs: Komer::new(lmdber.clone(), "habs.", SerialKind::Json)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
names: Suber::new(lmdber.clone(), "names.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
eans: CesrSuber::new(lmdber.clone(), "eans.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
lans: CesrSuber::new(lmdber.clone(), "lans.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
pses: IoDupSuber::new(lmdber.clone(), "pses.", None, false)
.map_err(|e| DBError::DatabaseError(format!("SuberError: {}", e)))?,
};
Ok(baser)
}
pub fn get_ke_last<K>(&self, key: K) -> Result<Option<String>, KERIError>
where
K: AsRef<[u8]>,
{
match self.kels.get_io_dup_val_last::<K, Vec<u8>>(&[key]) {
Ok(Some(val_bytes)) => {
match String::from_utf8(val_bytes) {
Ok(digest) => Ok(Some(digest)),
Err(e) => Err(KERIError::DeserializationError(format!(
"Failed to decode digest as UTF-8: {}",
e
))),
}
}
Ok(None) => Ok(None),
Err(e) => {
Err(KERIError::DatabaseError(format!("SuberError: {}", e)))
}
}
}
pub fn get_evt<K>(&self, key: K) -> Result<Option<Vec<u8>>, KERIError>
where
K: AsRef<[u8]>,
{
let db_key = self.evts.to_key(&[key], false);
self.lmdber
.get_val(&self.evts.base.sdb, &db_key)
.map_err(|e| KERIError::DatabaseError(format!("LMDBer error: {}", e)))
}
pub fn opened(&self) -> bool {
self.lmdber.opened()
}
pub fn name(&self) -> String {
self.lmdber.name()
}
pub fn path(&self) -> Option<PathBuf> {
self.lmdber.path()
}
pub fn temp(&self) -> bool {
self.lmdber.temp()
}
pub fn ri_key(pre: &str, ri: u64) -> String {
format!("{}.{:032x}", pre, ri)
}
pub fn fully_witnessed(&self, serder: &SerderKERI) -> bool {
let preb = serder.preb().unwrap_or_default();
let said = serder.said().unwrap_or_default();
let key = dg_key(preb, said);
match self.wigs.get::<_, Vec<u8>>(&[&key]) {
Ok(wigs) => {
let pre = serder.pre().unwrap();
let kever = &self.kevers[&pre];
let toad = kever.toader().unwrap().num();
!wigs.len() < toad as usize
}
Err(_) => false,
}
}
pub fn fetch_all_sealing_event_by_event_seal(
&self,
_pre: &str,
_anchor: &str,
) -> Result<bool, DBError> {
Ok(false)
}
pub fn clone_pre_iter(&self, pre: &str, fn_num: Option<u64>) -> Result<Vec<Vec<u8>>, DBError> {
let start_fn = fn_num.unwrap_or(0);
let mut msgs = Vec::new();
let key_prefix = pre.as_bytes();
let mut items = Vec::new();
let on_items: Vec<(Vec<Vec<u8>>, u64, Vec<u8>)> = self
.fels
.get_on_item_iter(&[&key_prefix], start_fn as u32)
.map_err(|e| DBError::DatabaseError(format!("Error getting items: {}", e)))?;
for (ckey, cn, cval) in on_items {
if ckey.starts_with(&[pre.as_bytes().to_vec()]) && cn >= start_fn {
let dig = String::from_utf8_lossy(&cval).to_string();
items.push((ckey.to_vec(), cn, dig));
}
}
for (_, fn_num, dig) in items {
match self.clone_evt_msg(pre, fn_num, &dig) {
Ok(msg) => msgs.push(msg),
Err(_) => continue, }
}
Ok(msgs)
}
pub fn clone_delegation(&self, kever: &Kever<'db>) -> Result<Vec<Vec<u8>>, DBError> {
let mut msgs = Vec::new();
if kever.delegated {
if let Some(ref delpre) = kever.delpre {
if let Some(dkever) = self.kevers.get(delpre) {
let delegator_msgs = self.clone_delegation(dkever)?;
msgs.extend(delegator_msgs);
let delegator_events = self.clone_pre_iter(delpre, Some(0))?;
msgs.extend(delegator_events);
}
}
}
Ok(msgs)
}
pub fn clone_evt_msg(&self, pre: &str, fn_num: u64, dig: &str) -> Result<Vec<u8>, DBError> {
let mut msg = Vec::<u8>::new(); let mut atc = Vec::<u8>::new();
let dg_key = dg_key(pre, dig);
let raw = self
.evts
.get::<_, Vec<u8>>(&[&dg_key])
.map_err(|_| DBError::MissingEntryError(format!("Missing event for dig={}.", dig)))?;
msg.extend_from_slice(&raw.unwrap_or_default());
let sigs = self
.sigs
.get::<_, Vec<u8>>(&[&dg_key])
.map_err(|_| DBError::MissingEntryError(format!("Missing sigs for dig={}.", dig)))?;
let counter = BaseCounter::from_code_and_count(
Some(ctr_dex_1_0::CONTROLLER_IDX_SIGS),
Some(sigs.len() as u64),
Some("1.0"),
)
.unwrap()
.qb64b();
atc.extend_from_slice(&counter);
for sig in sigs {
atc.extend_from_slice(&sig);
}
if let Ok(wigs) = self.wigs.get::<_, Vec<u8>>(&[&dg_key]) {
if !wigs.is_empty() {
let counter = BaseCounter::from_code_and_count(
Some(ctr_dex_1_0::WITNESS_IDX_SIGS),
Some(wigs.len() as u64),
Some("1.0"),
)
.unwrap()
.qb64b();
atc.extend_from_slice(&counter);
for wig in wigs {
atc.extend_from_slice(&wig);
}
}
}
if let Ok(Some(couple)) = self.aess.get::<_, Option<Vec<u8>>>(&[&dg_key]) {
let counter = BaseCounter::from_code_and_count(
Some(ctr_dex_1_0::SEAL_SOURCE_COUPLES),
Some(1),
Some("1.0"),
)
.unwrap()
.qb64b();
atc.extend_from_slice(&counter);
atc.extend_from_slice(&couple.unwrap());
}
if let Ok(quads) = self.vrcs.get::<_, Vec<u8>>(&[&dg_key]) {
if !quads.is_empty() {
let counter = BaseCounter::from_code_and_count(
Some(ctr_dex_1_0::TRANS_RECEIPT_QUADRUPLES),
Some(quads.len() as u64),
Some("1.0"),
)
.unwrap()
.qb64b();
atc.extend_from_slice(&counter);
for quad in quads {
atc.extend_from_slice(&quad);
}
}
}
if let Ok(coups) = self.rcts.get::<_, Vec<u8>>(&[&dg_key]) {
if !coups.is_empty() {
let counter = BaseCounter::from_code_and_count(
Some(ctr_dex_1_0::NON_TRANS_RECEIPT_COUPLES),
Some(coups.len() as u64),
Some("1.0"),
)
.unwrap()
.qb64b();
atc.extend_from_slice(&counter);
for coup in coups {
atc.extend_from_slice(&coup);
}
}
}
let dts = self.dtss.get::<_, Vec<u8>>(&[&dg_key]).map_err(|_| {
DBError::MissingEntryError(format!("Missing datetime for dig={}.", dig))
})?;
let counter = BaseCounter::from_code_and_count(
Some(ctr_dex_1_0::FIRST_SEEN_REPLAY_COUPLES),
Some(1),
Some("1.0"),
)
.unwrap()
.qb64b();
atc.extend_from_slice(&counter);
let fn_bytes = Number::from_num_and_code(&BigUint::from(fn_num), num_dex::HUGE)
.unwrap()
.qb64b();
atc.extend_from_slice(&fn_bytes);
let dt = DateTime::parse_from_rfc3339(&String::from_utf8_lossy(&dts[0]))
.map_err(|e| DBError::ValueError(format!("{}", e)))?;
let dater = Dater::from_dt(DateTime::from(dt)).qb64b();
atc.extend_from_slice(&dater);
if atc.len() % 4 != 0 {
return Err(DBError::ValueError(format!(
"Invalid attachments size={}, nonintegral quadlets.",
atc.len()
)));
}
let pcnt = BaseCounter::from_code_and_count(
Some(ctr_dex_1_0::ATTACHMENT_GROUP),
Some((atc.len() / 4) as u64),
Some("1.0"),
)
.unwrap()
.qb64b();
msg.extend_from_slice(&pcnt);
msg.extend_from_slice(&atc);
Ok(msg)
}
pub fn get_fel_item_all_pre_iter(&self) -> Result<Vec<(String, u64, String)>, DBError> {
let mut items = Vec::new();
let on_items: Vec<(Vec<Vec<u8>>, u64, Vec<u8>)> = self
.fels
.get_on_item_iter(&[b""], 0)
.map_err(|e| DBError::DatabaseError(format!("Error getting all FEL items: {}", e)))?;
for (ckey, cn, cval) in on_items {
if let Some(prefix_bytes) = ckey.first() {
let pre = String::from_utf8_lossy(prefix_bytes).to_string();
let fn_num = cn;
let dig = String::from_utf8_lossy(&cval).to_string();
items.push((pre, fn_num, dig));
}
}
items.sort_by(|a, b| a.1.cmp(&b.1));
Ok(items)
}
pub fn clone_all_pre_iter(&self) -> Result<Vec<Vec<u8>>, DBError> {
let mut msgs = Vec::new();
let fel_items = self.get_fel_item_all_pre_iter()?;
for (pre, fn_num, dig) in fel_items {
match self.clone_evt_msg(&pre, fn_num, &dig) {
Ok(msg) => msgs.push(msg),
Err(_) => continue, }
}
Ok(msgs)
}
pub fn cnt_sigs(&self, key: &[u8]) -> Result<usize, DBError> {
self.sigs
.cnt(&[key])
.map_err(|e| DBError::DatabaseError(format!("Error counting signatures: {}", e)))
}
pub fn get_sigs_iter(
&self,
key: &[u8],
) -> Result<impl Iterator<Item = Result<Vec<u8>, DBError>>, DBError> {
let iter = self.sigs.get_iter::<_, Vec<u8>>(&[key]).map_err(|e| {
DBError::DatabaseError(format!("Error getting signatures iterator: {}", e))
})?;
let results: Vec<Result<Vec<u8>, DBError>> = iter
.map(|result| {
result.map_err(|e| {
DBError::DatabaseError(format!("Error deserializing signature: {}", e))
})
})
.collect();
Ok(results.into_iter())
}
pub fn fetch_tsgs(
&self,
saider: Saider,
snh: Option<&str>,
) -> Result<Vec<(Prefixer, Seqner, Diger, Vec<Siger>)>, KERIError> {
let mut tsgs = Vec::new();
let mut sigers = Vec::new();
let mut old: Option<Vec<Vec<u8>>> = None;
let items = self
.ssgs
.get_item_iter(&[saider.qb64().as_bytes(), b""], false)
.map_err(|e| {
KERIError::DatabaseError(format!("Failed to get signature items: {}", e))
})?;
for (keys, siger_matters) in items {
if keys.len() < 2 {
continue;
}
let triple = keys[1..].to_vec();
if Some(&triple) != old.as_ref() {
if let Some(snh) = snh {
if triple.len() >= 2 {
let seq_str = String::from_utf8_lossy(&triple[1]);
if seq_str.as_ref() > snh {
break; }
}
}
if !sigers.is_empty() && old.is_some() {
if let Some(old_triple) = &old {
let (prefixer, seqner, diger) = self.klasify_triple(old_triple)?;
tsgs.push((prefixer, seqner, diger, sigers.clone()));
sigers.clear();
}
}
old = Some(triple);
}
for siger_matter in siger_matters {
if let Some(siger) = siger_matter.as_any().downcast_ref::<Siger>() {
sigers.push(siger.clone());
}
}
}
if !sigers.is_empty() && old.is_some() {
if let Some(old_triple) = &old {
let (prefixer, seqner, diger) = self.klasify_triple(old_triple)?;
tsgs.push((prefixer, seqner, diger, sigers));
}
}
Ok(tsgs)
}
fn klasify_triple(&self, triple: &[Vec<u8>]) -> Result<(Prefixer, Seqner, Diger), KERIError> {
if triple.len() != 3 {
return Err(KERIError::ValidationError(
"Expected triple of values".to_string(),
));
}
let prefixer = Prefixer::from_qb64(&String::from_utf8_lossy(&triple[0]))
.map_err(|e| KERIError::ValidationError(format!("Failed to create Prefixer: {}", e)))?;
let seqner = Seqner::from_snh(&String::from_utf8_lossy(&triple[1]))
.map_err(|e| KERIError::ValidationError(format!("Failed to create Seqner: {}", e)))?;
let diger = Diger::from_qb64(&String::from_utf8_lossy(&triple[2]))
.map_err(|e| KERIError::ValidationError(format!("Failed to create Diger: {}", e)))?;
Ok((prefixer, seqner, diger))
}
}
impl<'db> Drop for Baser<'db> {
fn drop(&mut self) {
}
}