Skip to content

Commit

Permalink
Add default signing key as a generic verification method (#421)
Browse files Browse the repository at this point in the history
* Rename auth to int chain everywhere

* Create verification method with attached auth

* Fix generations in tests

* Update remaining generations in tests

* Remove outdated TODO

* Impl generic verif method in low level API

* Use 'integration' instead of 'int'

* Add test that verifies number of verif. methods

* Assert the authentication relationship
  • Loading branch information
PhilippGackstatter authored Sep 29, 2021
1 parent cf81524 commit 8a63e14
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 68 deletions.
18 changes: 9 additions & 9 deletions identity-account/src/account/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ impl Account {
let snapshot: IdentitySnapshot = self.load_snapshot(identity).await?;
let state: &IdentityState = snapshot.identity();

let fragment: Fragment = Fragment::new(fragment.into());
let fragment: Fragment = Fragment::new(fragment);
let method: &TinyMethod = state.methods().fetch(fragment.name())?;
let location: &KeyLocation = method.location();

Expand Down Expand Up @@ -282,7 +282,7 @@ impl Account {
new_state: &IdentityState,
document: &mut IotaDocument,
) -> Result<()> {
if new_state.auth_generation() == Generation::new() {
if new_state.integration_generation() == Generation::new() {
let method: &TinyMethod = new_state.authentication()?;
let location: &KeyLocation = method.location();

Expand All @@ -299,7 +299,7 @@ impl Account {
Ok(())
}

async fn process_auth_change(&self, old_root: IdentitySnapshot) -> Result<()> {
async fn process_integration_change(&self, old_root: IdentitySnapshot) -> Result<()> {
let new_root: IdentitySnapshot = self.load_snapshot(old_root.id()).await?;

let old_state: &IdentityState = old_root.identity();
Expand All @@ -315,7 +315,7 @@ impl Account {
self.state.clients.publish_document(&new_doc).await?.into()
};

let events: [Event; 1] = [Event::new(EventData::AuthMessage(message))];
let events: [Event; 1] = [Event::new(EventData::IntegrationMessage(message))];

self.commit_events(&new_root, &events).await?;

Expand Down Expand Up @@ -478,7 +478,7 @@ impl Account {
let id: IdentityId = snapshot.id();

match Publish::new(&commits) {
Publish::Auth => self.process_auth_change(snapshot).await?,
Publish::Integration => self.process_integration_change(snapshot).await?,
Publish::Diff => self.process_diff_change(snapshot).await?,
Publish::None => {}
}
Expand Down Expand Up @@ -635,7 +635,7 @@ impl State {
#[derive(Clone, Copy, Debug)]
enum Publish {
None,
Auth,
Integration,
Diff,
}

Expand All @@ -646,9 +646,9 @@ impl Publish {

const fn apply(self, commit: &Commit) -> Self {
match (self, commit.event().data()) {
(Self::Auth, _) => Self::Auth,
(_, EventData::IdentityCreated(..)) => Self::Auth,
(_, EventData::AuthMessage(_)) => self,
(Self::Integration, _) => Self::Integration,
(_, EventData::IdentityCreated(..)) => Self::Integration,
(_, EventData::IntegrationMessage(_)) => self,
(_, EventData::DiffMessage(_)) => self,
(_, _) => Self::Diff,
}
Expand Down
11 changes: 8 additions & 3 deletions identity-account/src/events/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl Command {
UpdateError::InvalidMethodType(authentication)
);

let generation: Generation = state.auth_generation();
let generation: Generation = state.integration_generation();
let location: KeyLocation = KeyLocation::new_authentication(authentication, generation);

// The key location must be available
Expand All @@ -112,10 +112,15 @@ impl Command {
let network: Option<&str> = network.as_deref();
let document: IotaDID = IotaDID::from_components(public.as_ref(), network)?;

let method_fragment = Fragment::new(method.location().fragment());

Ok(Some(vec![
Event::new(EventData::IdentityCreated(document)),
// TODO: MethodScope::VerificationMethod when possible
Event::new(EventData::MethodCreated(MethodScope::Authentication, method)),
Event::new(EventData::MethodCreated(MethodScope::VerificationMethod, method)),
Event::new(EventData::MethodAttached(
method_fragment,
vec![MethodScope::Authentication],
)),
]))
}
Self::CreateMethod {
Expand Down
10 changes: 5 additions & 5 deletions identity-account/src/events/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ impl Event {
trace!("[Event::apply] State = {:?}", state);

match self.data {
EventData::AuthMessage(message) => {
state.set_auth_message_id(message);
state.increment_auth_generation()?;
EventData::IntegrationMessage(message) => {
state.set_integration_message_id(message);
state.increment_integration_generation()?;
}
EventData::DiffMessage(message) => {
state.set_diff_message_id(message);
Expand Down Expand Up @@ -104,8 +104,8 @@ impl Event {
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(tag = "type", content = "data")]
pub enum EventData {
/// Emitted when a new auth message is published to the IOTA Tangle.
AuthMessage(MessageId),
/// Emitted when a new int message is published to the IOTA Tangle.
IntegrationMessage(MessageId),
/// Emitted when a new diff message is published to the IOTA Tangle.
DiffMessage(MessageId),
/// Emitted when a new identity state is created.
Expand Down
46 changes: 23 additions & 23 deletions identity-account/src/identity/identity_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ pub struct IdentityState {
// Chain State //
// =========== //
id: IdentityId,
auth_generation: Generation,
integration_generation: Generation,
diff_generation: Generation,
#[serde(default = "MessageId::null", skip_serializing_if = "MessageId::is_null")]
this_message_id: MessageId,
#[serde(default = "MessageId::null", skip_serializing_if = "MessageId::is_null")]
last_auth_message_id: MessageId,
last_integration_message_id: MessageId,
#[serde(default = "MessageId::null", skip_serializing_if = "MessageId::is_null")]
last_diff_message_id: MessageId,

Expand All @@ -79,10 +79,10 @@ impl IdentityState {
pub fn new(id: IdentityId) -> Self {
Self {
id,
auth_generation: Generation::new(),
integration_generation: Generation::new(),
diff_generation: Generation::new(),
this_message_id: MessageId::null(),
last_auth_message_id: MessageId::null(),
last_integration_message_id: MessageId::null(),
last_diff_message_id: MessageId::null(),
did: None,
controller: None,
Expand All @@ -103,19 +103,19 @@ impl IdentityState {
self.id
}

/// Returns the current generation of the identity auth chain.
pub fn auth_generation(&self) -> Generation {
self.auth_generation
/// Returns the current generation of the identity integration chain.
pub fn integration_generation(&self) -> Generation {
self.integration_generation
}

/// Returns the current generation of the identity diff chain.
pub fn diff_generation(&self) -> Generation {
self.diff_generation
}

/// Increments the generation of the identity auth chain.
pub fn increment_auth_generation(&mut self) -> Result<()> {
self.auth_generation = self.auth_generation.try_increment()?;
/// Increments the generation of the identity integration chain.
pub fn increment_integration_generation(&mut self) -> Result<()> {
self.integration_generation = self.integration_generation.try_increment()?;
self.diff_generation = Generation::new();

Ok(())
Expand All @@ -132,17 +132,17 @@ impl IdentityState {
// Tangle State
// ===========================================================================

/// Returns the current auth Tangle message id of the identity.
/// Returns the current integration Tangle message id of the identity.
pub fn this_message_id(&self) -> &MessageId {
&self.this_message_id
}

/// Returns the previous auth Tangle message id of the identity.
/// Returns the previous integration Tangle message id of the identity.
pub fn last_message_id(&self) -> &MessageId {
&self.last_auth_message_id
&self.last_integration_message_id
}

/// Returns the previous diff Tangle message id, or the current auth message id.
/// Returns the previous diff Tangle message id, or the current integration message id.
pub fn diff_message_id(&self) -> &MessageId {
if self.last_diff_message_id.is_null() {
&self.this_message_id
Expand All @@ -151,15 +151,15 @@ impl IdentityState {
}
}

/// Sets the current Tangle auth message id of the identity.
pub fn set_auth_message_id(&mut self, message: MessageId) {
// Set the current auth message id as the previous auth message.
self.last_auth_message_id = self.this_message_id;
/// Sets the current Tangle integration message id of the identity.
pub fn set_integration_message_id(&mut self, message: MessageId) {
// Set the current integration message id as the previous integration message.
self.last_integration_message_id = self.this_message_id;

// Clear the diff message id
self.last_diff_message_id = MessageId::null();

// Set the new auth message id
// Set the new integration message id
self.this_message_id = message;
}

Expand Down Expand Up @@ -237,7 +237,7 @@ impl IdentityState {
.methods()
.iter()
.filter(|method| method.is_authentication())
.max_by_key(|method| method.location().auth_generation())
.max_by_key(|method| method.location().integration_generation())
.ok_or(Error::MethodNotFound)
}

Expand All @@ -246,7 +246,7 @@ impl IdentityState {
Ok(KeyLocation {
method,
fragment: Fragment::new(fragment),
auth_generation: self.auth_generation(),
integration_generation: self.integration_generation(),
diff_generation: self.diff_generation(),
})
}
Expand Down Expand Up @@ -312,8 +312,8 @@ impl IdentityState {
document.set_message_id(self.this_message_id);
}

if !self.last_auth_message_id.is_null() {
document.set_previous_message_id(self.last_auth_message_id);
if !self.last_integration_message_id.is_null() {
document.set_previous_message_id(self.last_integration_message_id);
}

document.set_created(self.created.into());
Expand Down
2 changes: 1 addition & 1 deletion identity-account/src/storage/stronghold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ fn fmt_key(prefix: &str, location: &KeyLocation) -> Vec<u8> {
format!(
"{}:{}:{}:{}",
prefix,
location.auth_generation(),
location.integration_generation(),
location.diff_generation(),
location.fragment(),
)
Expand Down
32 changes: 16 additions & 16 deletions identity-account/src/tests/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ async fn test_create_identity() -> Result<()> {

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;

assert_eq!(snapshot.sequence(), Generation::from_u32(3));
assert_eq!(snapshot.sequence(), Generation::from_u32(4));
assert_eq!(snapshot.id(), identity);
assert!(snapshot.identity().did().is_some());
assert_ne!(snapshot.identity().created(), UnixTimestamp::EPOCH);
Expand Down Expand Up @@ -147,8 +147,8 @@ async fn test_create_identity_already_exists() -> Result<()> {

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;

// version is now 3
assert_eq!(snapshot.sequence(), Generation::from(3));
// version is now 4
assert_eq!(snapshot.sequence(), Generation::from(4));

let output: Result<()> = account.process(identity, command, false).await;

Expand All @@ -159,8 +159,8 @@ async fn test_create_identity_already_exists() -> Result<()> {

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;

// version is still 3, no events have been committed
assert_eq!(snapshot.sequence(), Generation::from(3));
// version is still 4, no events have been committed
assert_eq!(snapshot.sequence(), Generation::from(4));

Ok(())
}
Expand Down Expand Up @@ -233,7 +233,7 @@ async fn test_create_method() -> Result<()> {

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;

assert_eq!(snapshot.sequence(), Generation::from_u32(5));
assert_eq!(snapshot.sequence(), Generation::from_u32(6));
assert_eq!(snapshot.id(), identity);
assert!(snapshot.identity().did().is_some());
assert_ne!(snapshot.identity().created(), UnixTimestamp::EPOCH);
Expand Down Expand Up @@ -270,8 +270,8 @@ async fn test_create_method_reserved_fragment() -> Result<()> {

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;

// version is now 3
assert_eq!(snapshot.sequence(), Generation::from_u32(3));
// version is now 4
assert_eq!(snapshot.sequence(), Generation::from_u32(4));

let output: _ = account.process(identity, command, false).await;

Expand All @@ -282,8 +282,8 @@ async fn test_create_method_reserved_fragment() -> Result<()> {

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;

// version is still 3, no new events have been committed
assert_eq!(snapshot.sequence(), Generation::from_u32(3));
// version is still 4, no new events have been committed
assert_eq!(snapshot.sequence(), Generation::from_u32(4));

Ok(())
}
Expand All @@ -309,12 +309,12 @@ async fn test_create_method_duplicate_fragment() -> Result<()> {
};

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;
assert_eq!(snapshot.sequence(), Generation::from_u32(3));
assert_eq!(snapshot.sequence(), Generation::from_u32(4));

account.process(identity, command.clone(), false).await?;

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;
assert_eq!(snapshot.sequence(), Generation::from_u32(5));
assert_eq!(snapshot.sequence(), Generation::from_u32(6));

let output: _ = account.process(identity, command, false).await;

Expand All @@ -324,7 +324,7 @@ async fn test_create_method_duplicate_fragment() -> Result<()> {
));

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;
assert_eq!(snapshot.sequence(), Generation::from_u32(5));
assert_eq!(snapshot.sequence(), Generation::from_u32(6));

Ok(())
}
Expand Down Expand Up @@ -458,13 +458,13 @@ async fn test_delete_method() -> Result<()> {
};

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;
assert_eq!(snapshot.sequence(), Generation::from_u32(3));
assert_eq!(snapshot.sequence(), Generation::from_u32(4));

account.process(identity, command, false).await?;

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;

assert_eq!(snapshot.sequence(), Generation::from_u32(5));
assert_eq!(snapshot.sequence(), Generation::from_u32(6));
assert_eq!(snapshot.identity().methods().len(), 2);
assert!(snapshot.identity().methods().contains("key-1"));
assert!(snapshot.identity().methods().get("key-1").is_some());
Expand All @@ -478,7 +478,7 @@ async fn test_delete_method() -> Result<()> {

let snapshot: IdentitySnapshot = account.load_snapshot(identity).await?;

assert_eq!(snapshot.sequence(), Generation::from_u32(7));
assert_eq!(snapshot.sequence(), Generation::from_u32(8));
assert_eq!(snapshot.identity().methods().len(), 1);
assert!(!snapshot.identity().methods().contains("key-1"));
assert!(snapshot.identity().methods().get("key-1").is_none());
Expand Down
Loading

0 comments on commit 8a63e14

Please sign in to comment.