aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbryan newbold <bnewbold@robocracy.org>2023-04-10 00:19:13 -0700
committerbryan newbold <bnewbold@robocracy.org>2023-04-10 00:19:13 -0700
commit4c51ee2decdd709be9d38806e002d7f69bcd3ebd (patch)
tree1d49c6a4dd2bee9f65505bd851d7cb1a24343150
parentbca44be1b01d2fd2f021cfaed344ff945f9b41b6 (diff)
downloadadenosine-4c51ee2decdd709be9d38806e002d7f69bcd3ebd.tar.gz
adenosine-4c51ee2decdd709be9d38806e002d7f69bcd3ebd.zip
repov2 commit node updates
-rw-r--r--adenosine/src/mst.rs37
-rw-r--r--adenosine/src/repo.rs126
2 files changed, 54 insertions, 109 deletions
diff --git a/adenosine/src/mst.rs b/adenosine/src/mst.rs
index 7c9d4ee..ba86e4f 100644
--- a/adenosine/src/mst.rs
+++ b/adenosine/src/mst.rs
@@ -23,25 +23,20 @@ use std::collections::BTreeMap;
use std::path::PathBuf;
#[derive(Debug, DagCbor, PartialEq, Eq)]
-pub struct CommitNode {
- pub root: Cid,
- pub sig: Box<[u8]>,
-}
-
-#[derive(Debug, DagCbor, PartialEq, Eq)]
-pub struct RootNode {
- pub auth_token: Option<String>,
+pub struct SignedCommitNode {
+ pub did: String,
+ pub version: u8,
pub prev: Option<Cid>,
- // TODO: not 'metadata'?
- pub meta: Cid,
pub data: Cid,
+ pub sig: Box<[u8]>,
}
#[derive(Debug, DagCbor, PartialEq, Eq)]
-pub struct MetadataNode {
- pub datastore: String, // "mst"
+pub struct UnsignedCommitNode {
pub did: String,
- pub version: u8, // 1
+ pub version: u8,
+ pub prev: Option<Cid>,
+ pub data: Cid,
}
#[derive(Debug, DagCbor, PartialEq, Eq)]
@@ -124,30 +119,20 @@ pub fn dump_mst_keys(db_path: &PathBuf) -> Result<()> {
&db.get_block(&commit_cid)?
.ok_or(anyhow!("expected commit block in store"))?
);
- let commit: CommitNode = DagCborCodec.decode(
+ let commit: SignedCommitNode = DagCborCodec.decode(
&db.get_block(&commit_cid)?
.ok_or(anyhow!("expected commit block in store"))?,
)?;
debug!("Commit: {:?}", commit);
- let root: RootNode = DagCborCodec.decode(
- &db.get_block(&commit.root)?
- .ok_or(anyhow!("expected root block in store"))?,
- )?;
- debug!("Root: {:?}", root);
- let metadata: MetadataNode = DagCborCodec.decode(
- &db.get_block(&root.meta)?
- .ok_or(anyhow!("expected metadata block in store"))?,
- )?;
- debug!("Metadata: {:?}", metadata);
let mst_node: MstNode = DagCborCodec.decode(
- &db.get_block(&root.data)?
+ &db.get_block(&commit.data)?
.ok_or(anyhow!("expected block in store"))?,
)?;
debug!("MST root node: {:?}", mst_node);
debug!("============");
println!("{did}");
- print_mst_keys(&mut db, &root.data)?;
+ print_mst_keys(&mut db, &commit.data)?;
Ok(())
}
diff --git a/adenosine/src/repo.rs b/adenosine/src/repo.rs
index a3a5a12..3fb3a40 100644
--- a/adenosine/src/repo.rs
+++ b/adenosine/src/repo.rs
@@ -3,7 +3,7 @@ use crate::car::{
};
use crate::crypto::KeyPair;
use crate::identifiers::{Did, Nsid, Tid};
-use crate::mst::{collect_mst_keys, generate_mst, CommitNode, MetadataNode, RootNode};
+use crate::mst::{collect_mst_keys, generate_mst, SignedCommitNode, UnsignedCommitNode};
use anyhow::{anyhow, ensure, Context, Result};
use ipfs_sqlite_block_store::BlockStore;
use libipld::cbor::DagCborCodec;
@@ -20,13 +20,12 @@ use std::str::FromStr;
#[derive(Debug, serde::Serialize)]
pub struct RepoCommit {
- pub sig: Box<[u8]>,
- pub commit_cid: Cid,
- pub root_cid: Cid,
pub did: Did,
+ pub version: u8,
pub prev: Option<Cid>,
- pub meta_cid: Cid,
pub mst_cid: Cid,
+ pub sig: Box<[u8]>,
+ pub commit_cid: Cid,
}
impl RepoCommit {
@@ -34,13 +33,12 @@ impl RepoCommit {
/// (aka, CID as a string, not an array of bytes).
pub fn to_pretty_json(&self) -> Value {
json!({
- "sig": data_encoding::HEXUPPER.encode(&self.sig),
- "commit_cid": self.commit_cid.to_string(),
- "root_cid": self.root_cid.to_string(),
"did": self.did.to_string(),
+ "version": self.version.to_string(),
"prev": self.prev.map(|v| v.to_string()),
- "meta_cid": self.meta_cid.to_string(),
"mst_cid": self.mst_cid.to_string(),
+ "sig": data_encoding::HEXUPPER.encode(&self.sig),
+ "commit_cid": self.commit_cid.to_string(),
})
}
}
@@ -115,7 +113,7 @@ impl RepoStore {
pub fn get_commit(&mut self, commit_cid: &Cid) -> Result<RepoCommit> {
// read records by CID: commit, root, meta
- let commit_node: CommitNode = DagCborCodec
+ let commit_node: SignedCommitNode = DagCborCodec
.decode(
&self
.db
@@ -123,40 +121,18 @@ impl RepoStore {
.ok_or(anyhow!("expected commit block in store"))?,
)
.context("parsing commit IPLD node from blockstore")?;
- let root_node: RootNode = DagCborCodec
- .decode(
- &self
- .db
- .get_block(&commit_node.root)?
- .ok_or(anyhow!("expected root block in store"))?,
- )
- .context("parsing root IPLD node from blockstore")?;
- let metadata_node: MetadataNode = DagCborCodec
- .decode(
- &self
- .db
- .get_block(&root_node.meta)?
- .ok_or(anyhow!("expected metadata block in store"))?,
- )
- .context("parsing metadata IPLD node from blockstore")?;
- ensure!(
- metadata_node.datastore == "mst",
- "unexpected repo metadata.datastore: {}",
- metadata_node.datastore
- );
ensure!(
- metadata_node.version == 1,
- "unexpected repo metadata.version: {}",
- metadata_node.version
+ commit_node.version == 2,
+ "unexpected repo version: {}",
+ commit_node.version
);
Ok(RepoCommit {
+ did: Did::from_str(&commit_node.did)?,
+ version: commit_node.version,
+ prev: commit_node.prev,
+ mst_cid: commit_node.data,
sig: commit_node.sig,
commit_cid: *commit_cid,
- root_cid: commit_node.root,
- meta_cid: root_node.meta,
- did: Did::from_str(&metadata_node.did)?,
- prev: root_node.prev,
- mst_cid: root_node.data,
})
}
@@ -200,26 +176,28 @@ impl RepoStore {
self.get_mst_record_by_key(&commit.mst_cid, &record_key)
}
- pub fn write_metadata(&mut self, did: &Did) -> Result<Cid> {
- self.put_ipld(&MetadataNode {
- datastore: "mst".to_string(),
+ pub fn write_commit(
+ &mut self,
+ did: &Did,
+ prev: Option<Cid>,
+ mst_cid: Cid,
+ signing_key: &KeyPair,
+ ) -> Result<Cid> {
+ let unsigned_commit = UnsignedCommitNode {
did: did.to_string(),
- version: 1,
- })
- }
-
- pub fn write_root(&mut self, meta_cid: Cid, prev: Option<Cid>, mst_cid: Cid) -> Result<Cid> {
- self.put_ipld(&RootNode {
- auth_token: None,
+ version: 2,
prev,
- meta: meta_cid,
data: mst_cid,
- })
- }
+ };
+ let block = Block::<DefaultParams>::encode(DagCborCodec, Code::Sha2_256, &unsigned_commit)?;
+ let digest = sha256::digest(block.data());
+ let sig = signing_key.sign_bytes(digest.as_bytes());
- pub fn write_commit(&mut self, did: &Did, root_cid: Cid, sig: &str) -> Result<Cid> {
- let commit_cid = self.put_ipld(&CommitNode {
- root: root_cid,
+ let commit_cid = self.put_ipld(&SignedCommitNode {
+ did: did.to_string(),
+ version: 2,
+ prev,
+ data: mst_cid,
sig: sig.as_bytes().to_vec().into_boxed_slice(),
})?;
self.db.alias(did.as_bytes().to_vec(), Some(&commit_cid))?;
@@ -272,19 +250,11 @@ impl RepoStore {
let new_mst_cid = self
.update_mst(&last_commit.mst_cid, mutations)
.context("updating MST in repo")?;
- let new_root_cid = self.write_root(
- last_commit.meta_cid,
- Some(last_commit.commit_cid),
- new_mst_cid,
- )?;
- // TODO: is this how signatures are supposed to work?
- // TODO: no, CID in bytes and sign that?
- let sig = signing_key.sign_bytes(new_root_cid.to_string().as_bytes());
- self.write_commit(did, new_root_cid, &sig)
+ self.write_commit(did, Some(last_commit.commit_cid), new_mst_cid, &signing_key)
}
/// Reads in a full MST tree starting at a repo commit, then re-builds and re-writes the tree
- /// in to the repo, and verifies that both the MST root CIDs and the repo root CIDs are identical.
+ /// in to the repo, and verifies that both the MST root CIDs are identical.
pub fn verify_repo_mst(&mut self, commit_cid: &Cid) -> Result<()> {
// load existing commit and MST tree
let existing_commit = self.get_commit(commit_cid)?;
@@ -300,16 +270,6 @@ impl RepoStore {
))?;
}
- let new_root_cid =
- self.write_root(existing_commit.meta_cid, existing_commit.prev, new_mst_cid)?;
- if new_root_cid != existing_commit.root_cid {
- Err(anyhow!(
- "repo root CID did not verify: {} != {}",
- existing_commit.root_cid,
- new_root_cid
- ))?;
- }
-
Ok(())
}
@@ -359,6 +319,7 @@ fn test_repo_mst() {
let mut repo = RepoStore::open_ephemeral().unwrap();
let did = Did::from_str("did:plc:dummy").unwrap();
+ let dummy_keypair = KeyPair::new_random();
// basic blob and IPLD record put/get
let blob = b"beware the swamp thing";
@@ -387,10 +348,8 @@ fn test_repo_mst() {
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 simple_commit_cid = repo
- .write_commit(&did, simple_root_cid, "dummy-sig")
+ .write_commit(&did, None, simple_map_cid, &dummy_keypair)
.unwrap();
assert_eq!(
Some(record.clone()),
@@ -422,11 +381,13 @@ fn test_repo_mst() {
map.insert("test.records/33333333333333".to_string(), record_cid);
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)
- .unwrap();
let simple3_commit_cid = repo
- .write_commit(&did, simple3_root_cid, "dummy-sig3")
+ .write_commit(
+ &did,
+ Some(simple_commit_cid),
+ simple3_map_cid,
+ &dummy_keypair,
+ )
.unwrap();
assert_eq!(map, repo.mst_to_map(&simple3_map_cid).unwrap());
assert_eq!(
@@ -444,7 +405,6 @@ fn test_repo_mst() {
.unwrap()
);
let commit = repo.get_commit(&simple3_commit_cid).unwrap();
- assert_eq!(commit.sig.to_vec(), b"dummy-sig3".to_vec());
assert_eq!(commit.did, did);
assert_eq!(commit.prev, Some(simple_commit_cid));
assert_eq!(commit.mst_cid, simple3_map_cid);