diff options
Diffstat (limited to 'adenosine-pds/src/repo.rs')
-rw-r--r-- | adenosine-pds/src/repo.rs | 208 |
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() ); } |