summaryrefslogtreecommitdiffstats
path: root/adenosine-pds/src/repo.rs
diff options
context:
space:
mode:
authorBryan Newbold <bnewbold@robocracy.org>2022-11-06 23:08:33 -0800
committerBryan Newbold <bnewbold@robocracy.org>2022-11-06 23:08:33 -0800
commit388d4c004146865161e2661fb63c705e7f097f3a (patch)
tree40ad5f05fd805b779b95fc27780cb143fafe88bf /adenosine-pds/src/repo.rs
parent31d427f7342a58308501ba7e1f74751393299cf1 (diff)
downloadadenosine-388d4c004146865161e2661fb63c705e7f097f3a.tar.gz
adenosine-388d4c004146865161e2661fb63c705e7f097f3a.zip
pds: refactor to use typed identifiers a lot more
Diffstat (limited to 'adenosine-pds/src/repo.rs')
-rw-r--r--adenosine-pds/src/repo.rs208
1 files changed, 102 insertions, 106 deletions
diff --git a/adenosine-pds/src/repo.rs b/adenosine-pds/src/repo.rs
index 289125c..ad9aade 100644
--- a/adenosine-pds/src/repo.rs
+++ b/adenosine-pds/src/repo.rs
@@ -1,6 +1,6 @@
use crate::load_car_to_blockstore;
use crate::mst::{collect_mst_keys, generate_mst, CommitNode, MetadataNode, RootNode};
-use adenosine_cli::identifiers::{Nsid, Tid};
+use adenosine_cli::identifiers::{Did, Nsid, Tid};
use anyhow::{anyhow, ensure, Context, Result};
use ipfs_sqlite_block_store::BlockStore;
use libipld::cbor::DagCborCodec;
@@ -16,11 +16,11 @@ use std::str::FromStr;
pub struct RepoCommit {
pub sig: Box<[u8]>,
- pub commit_cid: String,
- pub did: String,
- pub prev: Option<String>,
- pub meta_cid: String,
- pub mst_cid: String,
+ pub commit_cid: Cid,
+ pub did: Did,
+ pub prev: Option<Cid>,
+ pub meta_cid: Cid,
+ pub mst_cid: Cid,
}
pub struct RepoStore {
@@ -52,59 +52,51 @@ impl RepoStore {
})
}
- pub fn get_ipld(&mut self, cid: &str) -> Result<Ipld> {
- let ipld_cid = Cid::from_str(cid)?;
- if let Some(b) = self.db.get_block(&ipld_cid)? {
- let block: Block<DefaultParams> = Block::new(ipld_cid, b)?;
+ pub fn get_ipld(&mut self, cid: &Cid) -> Result<Ipld> {
+ if let Some(b) = self.db.get_block(cid)? {
+ let block: Block<DefaultParams> = Block::new(cid.clone(), b)?;
block.ipld()
} else {
Err(anyhow!("missing IPLD CID: {}", cid))
}
}
- pub fn get_blob(&mut self, cid: &str) -> Result<Option<Vec<u8>>> {
- let cid = Cid::from_str(cid)?;
- Ok(self.db.get_block(&cid)?)
+ pub fn get_blob(&mut self, cid: &Cid) -> Result<Option<Vec<u8>>> {
+ Ok(self.db.get_block(cid)?)
}
/// Returns CID that was inserted
- pub fn put_ipld<S: libipld::codec::Encode<DagCborCodec>>(
- &mut self,
- record: &S,
- ) -> Result<String> {
+ pub fn put_ipld<S: libipld::codec::Encode<DagCborCodec>>(&mut self, record: &S) -> Result<Cid> {
let block = Block::<DefaultParams>::encode(DagCborCodec, Code::Sha2_256, record)?;
let cid = *block.cid();
self.db
.put_block(block, None)
.context("writing IPLD DAG-CBOR record to blockstore")?;
- Ok(cid.to_string())
+ Ok(cid)
}
/// Returns CID that was inserted
- pub fn put_blob(&mut self, data: &[u8]) -> Result<String> {
+ pub fn put_blob(&mut self, data: &[u8]) -> Result<Cid> {
let block = Block::<DefaultParams>::encode(libipld::raw::RawCodec, Code::Sha2_256, data)?;
let cid = *block.cid();
self.db
.put_block(block, None)
.context("writing non-record blob to blockstore")?;
- Ok(cid.to_string())
+ Ok(cid)
}
/// Quick alias lookup
- pub fn lookup_commit(&mut self, did: &str) -> Result<Option<String>> {
- Ok(self
- .db
- .resolve(Cow::from(did.as_bytes()))?
- .map(|cid| cid.to_string()))
+ pub fn lookup_commit(&mut self, did: &Did) -> Result<Option<Cid>> {
+ Ok(self.db.resolve(Cow::from(did.as_bytes()))?)
}
- pub fn get_commit(&mut self, commit_cid: &str) -> Result<RepoCommit> {
+ pub fn get_commit(&mut self, commit_cid: &Cid) -> Result<RepoCommit> {
// read records by CID: commit, root, meta
let commit_node: CommitNode = DagCborCodec
.decode(
&self
.db
- .get_block(&Cid::from_str(commit_cid)?)?
+ .get_block(commit_cid)?
.ok_or(anyhow!("expected commit block in store"))?,
)
.context("parsing commit IPLD node from blockstore")?;
@@ -136,24 +128,24 @@ impl RepoStore {
);
Ok(RepoCommit {
sig: commit_node.sig,
- commit_cid: commit_cid.to_string(),
- meta_cid: root_node.meta.to_string(),
- did: metadata_node.did,
- prev: root_node.prev.map(|cid| cid.to_string()),
- mst_cid: root_node.data.to_string(),
+ commit_cid: commit_cid.clone(),
+ meta_cid: root_node.meta,
+ did: Did::from_str(&metadata_node.did)?,
+ prev: root_node.prev,
+ mst_cid: root_node.data,
})
}
- pub fn get_mst_record_by_key(&mut self, mst_cid: &str, key: &str) -> Result<Option<Ipld>> {
+ pub fn get_mst_record_by_key(&mut self, mst_cid: &Cid, key: &str) -> Result<Option<Ipld>> {
let map = self.mst_to_map(mst_cid)?;
if let Some(cid) = map.get(key) {
- self.get_ipld(&cid.to_string()).map(|v| Some(v))
+ self.get_ipld(&cid).map(|v| Some(v))
} else {
Ok(None)
}
}
- pub fn collections(&mut self, did: &str) -> Result<Vec<String>> {
+ pub fn collections(&mut self, did: &Did) -> Result<Vec<String>> {
let commit = if let Some(c) = self.lookup_commit(did)? {
self.get_commit(&c)?
} else {
@@ -171,9 +163,9 @@ impl RepoStore {
pub fn get_atp_record(
&mut self,
- did: &str,
- collection: &str,
- tid: &str,
+ did: &Did,
+ collection: &Nsid,
+ tid: &Tid,
) -> Result<Option<Ipld>> {
let commit = if let Some(c) = self.lookup_commit(did)? {
self.get_commit(&c)?
@@ -184,7 +176,7 @@ impl RepoStore {
self.get_mst_record_by_key(&commit.mst_cid, &record_key)
}
- pub fn write_metadata(&mut self, did: &str) -> Result<String> {
+ pub fn write_metadata(&mut self, did: &Did) -> Result<Cid> {
self.put_ipld(&MetadataNode {
datastore: "mst".to_string(),
did: did.to_string(),
@@ -192,61 +184,47 @@ impl RepoStore {
})
}
- pub fn write_root(
- &mut self,
- meta_cid: &str,
- prev: Option<&str>,
- mst_cid: &str,
- ) -> Result<String> {
+ pub fn write_root(&mut self, meta_cid: Cid, prev: Option<Cid>, mst_cid: Cid) -> Result<Cid> {
self.put_ipld(&RootNode {
auth_token: None,
- // TODO: not unwrap here
- prev: prev.map(|s| Cid::from_str(s).unwrap()),
- // TODO: not 'metadata'?
- meta: Cid::from_str(meta_cid)?,
- data: Cid::from_str(mst_cid)?,
+ prev,
+ meta: meta_cid,
+ data: mst_cid,
})
}
- pub fn write_commit(&mut self, did: &str, root_cid: &str, sig: &str) -> Result<String> {
+ pub fn write_commit(&mut self, did: &Did, root_cid: Cid, sig: &str) -> Result<Cid> {
let commit_cid = self.put_ipld(&CommitNode {
- root: Cid::from_str(root_cid)?,
+ root: root_cid,
sig: sig.as_bytes().to_vec().into_boxed_slice(),
})?;
- self.db
- .alias(did.as_bytes().to_vec(), Some(&Cid::from_str(&commit_cid)?))?;
+ self.db.alias(did.as_bytes().to_vec(), Some(&commit_cid))?;
Ok(commit_cid)
}
- pub fn mst_from_map(&mut self, map: &BTreeMap<String, String>) -> Result<String> {
- // TODO: not unwrap in iter
- let cid_map: BTreeMap<String, Cid> = BTreeMap::from_iter(
- map.iter()
- .map(|(k, v)| (k.to_string(), Cid::from_str(v).unwrap())),
- );
- let mst_cid = generate_mst(&mut self.db, &cid_map)?;
- Ok(mst_cid.to_string())
+ pub fn mst_from_map(&mut self, map: &BTreeMap<String, Cid>) -> Result<Cid> {
+ let mst_cid = generate_mst(&mut self.db, map)?;
+ Ok(mst_cid)
}
- fn mst_to_cid_map(&mut self, mst_cid: &str) -> Result<BTreeMap<String, Cid>> {
+ pub fn mst_to_map(&mut self, mst_cid: &Cid) -> Result<BTreeMap<String, Cid>> {
let mut cid_map: BTreeMap<String, Cid> = Default::default();
- let mst_cid = Cid::from_str(mst_cid)?;
- collect_mst_keys(&mut self.db, &mst_cid, &mut cid_map)
+ collect_mst_keys(&mut self.db, mst_cid, &mut cid_map)
.context("reading repo MST from blockstore")?;
Ok(cid_map)
}
- pub fn update_mst(&mut self, mst_cid: &str, mutations: &[Mutation]) -> Result<String> {
- let mut cid_map = self.mst_to_cid_map(mst_cid)?;
+ pub fn update_mst(&mut self, mst_cid: &Cid, mutations: &[Mutation]) -> Result<Cid> {
+ let mut cid_map = self.mst_to_map(mst_cid)?;
for m in mutations.iter() {
match m {
Mutation::Create(collection, tid, val) => {
let cid = self.put_ipld(val)?;
- cid_map.insert(format!("/{}/{}", collection, tid), Cid::from_str(&cid)?);
+ cid_map.insert(format!("/{}/{}", collection, tid), cid);
}
Mutation::Update(collection, tid, val) => {
let cid = self.put_ipld(val)?;
- cid_map.insert(format!("/{}/{}", collection, tid), Cid::from_str(&cid)?);
+ cid_map.insert(format!("/{}/{}", collection, tid), cid);
}
Mutation::Delete(collection, tid) => {
cid_map.remove(&format!("/{}/{}", collection, tid));
@@ -254,21 +232,13 @@ impl RepoStore {
}
}
let mst_cid = generate_mst(&mut self.db, &cid_map)?;
- Ok(mst_cid.to_string())
- }
-
- /// Returns all the keys for a directory, as a sorted vec of strings
- pub fn mst_to_map(&mut self, mst_cid: &str) -> Result<BTreeMap<String, String>> {
- let cid_map = self.mst_to_cid_map(mst_cid)?;
- let ret_map: BTreeMap<String, String> =
- BTreeMap::from_iter(cid_map.into_iter().map(|(k, v)| (k, v.to_string())));
- Ok(ret_map)
+ Ok(mst_cid)
}
/// returns the root commit from CAR file
- pub fn load_car(&mut self, car_path: &PathBuf, alias: &str) -> Result<String> {
+ pub fn load_car(&mut self, car_path: &PathBuf, alias: &str) -> Result<Cid> {
let cid = load_car_to_blockstore(&mut self.db, car_path, alias)?;
- Ok(cid.to_string())
+ Ok(cid)
}
/// Exports in CAR format to a Writer
@@ -276,8 +246,8 @@ impl RepoStore {
/// The "from" commit CID feature is not implemented.
pub fn write_car<W: std::io::Write>(
&mut self,
- _did: &str,
- _from_commit_cid: Option<&str>,
+ _did: &Did,
+ _from_commit_cid: Option<&Cid>,
_out: &mut W,
) -> Result<()> {
unimplemented!()
@@ -289,76 +259,102 @@ fn test_repo_mst() {
use libipld::ipld;
let mut repo = RepoStore::open_ephemeral().unwrap();
- let did = "did:plc:dummy";
+ let did = Did::from_str("did:plc:dummy").unwrap();
// basic blob and IPLD record put/get
let blob = b"beware the swamp thing";
- let blob_cid: String = repo.put_blob(blob).unwrap();
+ let blob_cid = repo.put_blob(blob).unwrap();
let record = ipld!({"some-thing": 123});
- let record_cid: String = repo.put_ipld(&record).unwrap();
+ let record_cid = repo.put_ipld(&record).unwrap();
repo.get_blob(&blob_cid).unwrap().unwrap();
repo.get_ipld(&record_cid).unwrap();
// basic MST get/put
- let mut map: BTreeMap<String, String> = Default::default();
- let empty_map_cid: String = repo.mst_from_map(&map).unwrap();
+ let mut map: BTreeMap<String, Cid> = Default::default();
+ let empty_map_cid = repo.mst_from_map(&map).unwrap();
assert_eq!(map, repo.mst_to_map(&empty_map_cid).unwrap());
assert!(repo
- .get_mst_record_by_key(&empty_map_cid, "/records/1")
+ .get_mst_record_by_key(&empty_map_cid, "/test.records/44444444444444")
.unwrap()
.is_none());
map.insert("/blobs/1".to_string(), blob_cid.clone());
map.insert("/blobs/2".to_string(), blob_cid.clone());
- map.insert("/records/1".to_string(), record_cid.clone());
- map.insert("/records/2".to_string(), record_cid.clone());
- let simple_map_cid: String = repo.mst_from_map(&map).unwrap();
+ map.insert(
+ "/test.records/44444444444444".to_string(),
+ record_cid.clone(),
+ );
+ map.insert(
+ "/test.records/22222222222222".to_string(),
+ record_cid.clone(),
+ );
+ let simple_map_cid = repo.mst_from_map(&map).unwrap();
assert_eq!(map, repo.mst_to_map(&simple_map_cid).unwrap());
// create root and commit IPLD nodes
- let meta_cid = repo.write_metadata(did).unwrap();
- let simple_root_cid = repo.write_root(&meta_cid, None, &simple_map_cid).unwrap();
+ let meta_cid = repo.write_metadata(&did).unwrap();
+ let simple_root_cid = repo.write_root(meta_cid, None, simple_map_cid).unwrap();
let simple_commit_cid = repo
- .write_commit(did, &simple_root_cid, "dummy-sig")
+ .write_commit(&did, simple_root_cid, "dummy-sig")
.unwrap();
assert_eq!(
Some(record.clone()),
- repo.get_mst_record_by_key(&simple_map_cid, "/records/1")
+ repo.get_mst_record_by_key(&simple_map_cid, "/test.records/44444444444444")
.unwrap()
);
assert_eq!(
Some(record.clone()),
- repo.get_atp_record(did, "records", "1").unwrap()
+ repo.get_atp_record(
+ &did,
+ &Nsid::from_str("test.records").unwrap(),
+ &Tid::from_str("44444444444444").unwrap()
+ )
+ .unwrap()
);
assert!(repo
- .get_mst_record_by_key(&simple_map_cid, "/records/3")
+ .get_mst_record_by_key(&simple_map_cid, "/test.records/33333333333333")
+ .unwrap()
+ .is_none());
+ assert!(repo
+ .get_atp_record(
+ &did,
+ &Nsid::from_str("test.records").unwrap(),
+ &Tid::from_str("33333333333333").unwrap()
+ )
.unwrap()
.is_none());
- assert!(repo.get_atp_record(did, "records", "3").unwrap().is_none());
assert_eq!(
Some(simple_commit_cid.clone()),
- repo.lookup_commit(did).unwrap()
+ repo.lookup_commit(&did).unwrap()
);
- map.insert("/records/3".to_string(), record_cid.clone());
- let simple3_map_cid: String = repo.mst_from_map(&map).unwrap();
+ map.insert(
+ "/test.records/33333333333333".to_string(),
+ record_cid.clone(),
+ );
+ let simple3_map_cid = repo.mst_from_map(&map).unwrap();
let simple3_root_cid = repo
- .write_root(&meta_cid, Some(&simple_commit_cid), &simple3_map_cid)
+ .write_root(meta_cid, Some(simple_commit_cid), simple3_map_cid)
.unwrap();
let simple3_commit_cid = repo
- .write_commit(did, &simple3_root_cid, "dummy-sig3")
+ .write_commit(&did, simple3_root_cid, "dummy-sig3")
.unwrap();
assert_eq!(map, repo.mst_to_map(&simple3_map_cid).unwrap());
assert_eq!(
Some(record.clone()),
- repo.get_mst_record_by_key(&simple3_map_cid, "/records/3")
+ repo.get_mst_record_by_key(&simple3_map_cid, "/test.records/33333333333333")
.unwrap()
);
assert_eq!(
Some(record.clone()),
- repo.get_atp_record(did, "records", "3").unwrap()
+ repo.get_atp_record(
+ &did,
+ &Nsid::from_str("test.records").unwrap(),
+ &Tid::from_str("33333333333333").unwrap()
+ )
+ .unwrap()
);
let commit = repo.get_commit(&simple3_commit_cid).unwrap();
assert_eq!(commit.sig.to_vec(), b"dummy-sig3".to_vec());
@@ -367,6 +363,6 @@ fn test_repo_mst() {
assert_eq!(commit.mst_cid, simple3_map_cid);
assert_eq!(
Some(simple3_commit_cid.clone()),
- repo.lookup_commit(did).unwrap()
+ repo.lookup_commit(&did).unwrap()
);
}