Skip to content
This repository has been archived by the owner on Apr 15, 2024. It is now read-only.

[v2.0] Introduce Topics #236

Merged
merged 37 commits into from
Jun 14, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
15eb1dc
First pass branching
DyrellC May 13, 2022
8886b36
AsRef for topic
DyrellC May 16, 2022
d79e56d
mask topic directly, include in address gen, eq failing for user
DyrellC May 18, 2022
125f314
Fix examples/merge overwrites
DyrellC May 19, 2022
c6eda71
Add anchor/latest link to key store, remove link_to from sending
DyrellC May 19, 2022
3fbf7ea
clippy/fmt/warnings
DyrellC May 19, 2022
bd41e2b
fix tests
DyrellC May 19, 2022
8515d9d
fmt
DyrellC May 19, 2022
6d904c5
fmt in nightly
DyrellC May 19, 2022
c5c104c
remove unused functions
DyrellC May 20, 2022
cd30f54
Write test to expose `BranchStore` not removing all cursors in `Branc…
May 24, 2022
27fe5ca
remove fold and use for_each in cursor removal
DyrellC May 24, 2022
ea855fb
Merge branch 'v2.0/test-topics' of https://github.com/DyrellC/streams…
DyrellC May 24, 2022
2b00e82
Insert own base branch topic
DyrellC May 25, 2022
8aa1fa6
Make Topic String
DyrellC May 26, 2022
0e12d43
Merge branch 'v2.0-dev' of https://github.com/iotaledger/streams into…
DyrellC May 31, 2022
53cb461
Check size before resizing bytes
DyrellC May 31, 2022
05c7d84
fmt/clippy
DyrellC May 31, 2022
d257605
tests update
DyrellC May 31, 2022
3990b43
Merge branch 'v2.0/move-keys' of https://github.com/DyrellC/streams i…
DyrellC May 31, 2022
21afe44
fmt
DyrellC May 31, 2022
79bd3ea
fix cursor store test
DyrellC May 31, 2022
0e222b4
Merge branch 'v2.0-dev' of https://github.com/iotaledger/streams into…
DyrellC Jun 2, 2022
4c26b18
first round review changes
DyrellC Jun 9, 2022
b068917
round two review updates
DyrellC Jun 9, 2022
10f923f
update tests
DyrellC Jun 9, 2022
f14f065
Mac check for backup/restore, Address::gen takes topic by ref
DyrellC Jun 9, 2022
1194c8e
Update streams/src/api/cursor_store.rs
DyrellC Jun 9, 2022
ef728fd
Update cursor_store for anchor and latest link set/get
DyrellC Jun 9, 2022
d301431
fmt, clippy
DyrellC Jun 9, 2022
158b3f3
Merge branch 'v2.0/test-topics' of https://github.com/DyrellC/streams…
DyrellC Jun 9, 2022
705daad
typo
DyrellC Jun 9, 2022
e514d50
base_topic -> base_branch
DyrellC Jun 9, 2022
5b837d5
clean up user from review suggestions
DyrellC Jun 9, 2022
91c0b37
revert byte changes
DyrellC Jun 9, 2022
a5f0ae1
remove resize result
DyrellC Jun 9, 2022
d191de1
rename CursorStore and BranchStore
DyrellC Jun 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions lets/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,17 @@ impl AppAddr {
Self(bytes)
}

pub fn gen(identifier: Identifier, app_idx: usize) -> AppAddr {
pub fn gen(identifier: Identifier, base_topic: Topic) -> AppAddr {
DyrellC marked this conversation as resolved.
Show resolved Hide resolved
let mut addr = [0u8; 40];
let id_bytes = identifier.as_bytes();
// Create spongos to squeeze topic into final 8 bytes
let mut s = Spongos::<KeccakF1600>::init();
s.absorb(base_topic);
s.commit();
let squeezed_topic: [u8; 8] = s.squeeze();
DyrellC marked this conversation as resolved.
Show resolved Hide resolved
assert_eq!(id_bytes.len(), 32, "identifier must be 32 bytes long");
addr[..32].copy_from_slice(id_bytes);
addr[32..].copy_from_slice(&app_idx.to_be_bytes());
addr[32..].copy_from_slice(&squeezed_topic);
Self::new(addr)
}

Expand Down
79 changes: 16 additions & 63 deletions lets/src/id/identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,11 @@ use spongos::{
// Local
#[cfg(feature = "did")]
use crate::id::did::{DIDMethodId, DataWrapper};
use crate::{
id::psk::{Psk, PskId},
message::{ContentEncrypt, ContentEncryptSizeOf, ContentVerify},
};
use crate::message::{ContentEncrypt, ContentEncryptSizeOf, ContentVerify};

#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Identifier {
Ed25519(ed25519::PublicKey),
PskId(PskId),
#[cfg(feature = "did")]
DID(DIDMethodId),
}
Expand All @@ -48,7 +44,6 @@ impl core::fmt::Debug for Identifier {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Ed25519(arg0) => f.debug_tuple("Ed25519").field(&hex::encode(&arg0)).finish(),
Self::PskId(arg0) => f.debug_tuple("PskId").field(&hex::encode(arg0)).finish(),
#[cfg(feature = "did")]
Self::DID(arg0) => f.debug_tuple("DID").field(&hex::encode(arg0)).finish(),
}
Expand All @@ -60,7 +55,6 @@ impl Identifier {
pub(crate) fn as_bytes(&self) -> &[u8] {
match self {
Identifier::Ed25519(public_key) => public_key.as_slice(),
Identifier::PskId(id) => id.as_bytes(),
#[cfg(feature = "did")]
Identifier::DID(did) => did.as_ref(),
}
Expand All @@ -86,10 +80,6 @@ impl Identifier {
pub fn is_ed25519(&self) -> bool {
matches!(self, Self::Ed25519(_))
}

pub fn is_psk(&self) -> bool {
matches!(self, Self::PskId(_))
}
}

impl Default for Identifier {
Expand All @@ -105,18 +95,6 @@ impl From<ed25519::PublicKey> for Identifier {
}
}

impl From<PskId> for Identifier {
fn from(pskid: PskId) -> Self {
Identifier::PskId(pskid)
}
}

impl From<Psk> for Identifier {
fn from(psk: Psk) -> Self {
Identifier::PskId(psk.to_pskid())
}
}

#[cfg(feature = "did")]
impl From<&IotaDID> for Identifier {
fn from(did: &IotaDID) -> Self {
Expand Down Expand Up @@ -156,14 +134,9 @@ impl Mask<&Identifier> for sizeof::Context {
self.mask(oneof)?.mask(pk)?;
Ok(self)
}
Identifier::PskId(pskid) => {
let oneof = Uint8::new(1);
self.mask(oneof)?.mask(NBytes::new(pskid))?;
Ok(self)
}
#[cfg(feature = "did")]
Identifier::DID(did) => {
let oneof = Uint8::new(2);
let oneof = Uint8::new(1);
self.mask(oneof)?.mask(NBytes::new(did))?;
Ok(self)
}
Expand All @@ -183,14 +156,9 @@ where
self.mask(oneof)?.mask(pk)?;
Ok(self)
}
Identifier::PskId(pskid) => {
let oneof = Uint8::new(1);
self.mask(oneof)?.mask(NBytes::new(pskid))?;
Ok(self)
}
#[cfg(feature = "did")]
Identifier::DID(did) => {
let oneof = Uint8::new(2);
let oneof = Uint8::new(1);
self.mask(oneof)?.mask(NBytes::new(did))?;
Ok(self)
}
Expand All @@ -212,13 +180,8 @@ where
self.mask(&mut pk)?;
*identifier = Identifier::Ed25519(pk);
}
1 => {
let mut pskid = PskId::default();
self.mask(NBytes::new(&mut pskid))?;
*identifier = Identifier::PskId(pskid);
}
#[cfg(feature = "did")]
2 => {
1 => {
let mut method_id = DIDMethodId::default();
self.mask(NBytes::new(&mut method_id))?;
let did = method_id.try_to_did()?;
Expand Down Expand Up @@ -291,17 +254,12 @@ where
// TODO: Find a better way to represent this logic without the need for an additional trait
#[async_trait(?Send)]
impl ContentEncryptSizeOf<Identifier> for sizeof::Context {
async fn encrypt_sizeof(&mut self, recipient: &Identifier, exchange_key: &[u8], key: &[u8]) -> Result<&mut Self> {
match recipient {
Identifier::PskId(_) => self
.absorb(External::new(&NBytes::new(Psk::try_from(exchange_key)?)))?
.commit()?
.mask(NBytes::new(key)),
// TODO: Replace with separate logic for EdPubKey and DID instances (pending Identity xkey introdution)
_ => match <[u8; 32]>::try_from(exchange_key) {
Ok(slice) => self.x25519(&x25519::PublicKey::from(slice), NBytes::new(key)),
Err(e) => Err(anyhow!("Invalid x25519 key: {}", e)),
},
async fn encrypt_sizeof(&mut self, _recipient: &Identifier, exchange_key: &[u8], key: &[u8]) -> Result<&mut Self> {
// TODO: Replace with separate logic for EdPubKey and DID instances (pending Identity xkey
// introdution)
match <[u8; 32]>::try_from(exchange_key) {
Ok(slice) => self.x25519(&x25519::PublicKey::from(slice), NBytes::new(key)),
Err(e) => Err(anyhow!("Invalid x25519 key: {}", e)),
}
}
}
Expand All @@ -312,17 +270,12 @@ where
F: PRP,
OS: io::OStream,
{
async fn encrypt(&mut self, recipient: &Identifier, exchange_key: &[u8], key: &[u8]) -> Result<&mut Self> {
match recipient {
Identifier::PskId(_) => self
.absorb(External::new(&NBytes::new(Psk::try_from(exchange_key)?)))?
.commit()?
.mask(NBytes::new(key)),
// TODO: Replace with separate logic for EdPubKey and DID instances (pending Identity xkey introdution)
_ => match <[u8; 32]>::try_from(exchange_key) {
Ok(byte_array) => self.x25519(&x25519::PublicKey::from(byte_array), NBytes::new(key)),
Err(e) => Err(anyhow!("Invalid x25519 key: {}", e)),
},
async fn encrypt(&mut self, _recipient: &Identifier, exchange_key: &[u8], key: &[u8]) -> Result<&mut Self> {
// TODO: Replace with separate logic for EdPubKey and DID instances (pending Identity xkey
// introdution)
match <[u8; 32]>::try_from(exchange_key) {
Ok(byte_array) => self.x25519(&x25519::PublicKey::from(byte_array), NBytes::new(key)),
Err(e) => Err(anyhow!("Invalid x25519 key: {}", e)),
}
}
}
75 changes: 15 additions & 60 deletions lets/src/id/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,14 @@ use spongos::{
#[cfg(feature = "did")]
use crate::id::did::{DataWrapper, DID};
use crate::{
id::{ed25519::Ed25519, identifier::Identifier, psk::Psk},
id::{ed25519::Ed25519, identifier::Identifier},
message::{ContentDecrypt, ContentSign, ContentSignSizeof},
};

#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
#[allow(clippy::large_enum_variant)]
pub enum Identity {
Ed25519(Ed25519),
Psk(Psk),
#[cfg(feature = "did")]
DID(DID),
}
Expand All @@ -56,31 +55,11 @@ impl Default for Identity {

impl Identity {
// #[deprecated = "to be removed once key exchange is encapsulated within Identity"]
pub fn _ke_sk(&self) -> Option<x25519::SecretKey> {
pub fn _ke_sk(&self) -> x25519::SecretKey {
match self {
Self::Ed25519(ed25519) => {
let x_secret: x25519::SecretKey = ed25519.inner().into();
Some(x_secret)
}
Self::Psk(_) => None,
#[cfg(feature = "did")]
Self::DID(DID::PrivateKey(info)) => Some(info.ke_kp().0),
#[cfg(feature = "did")]
Self::DID(DID::Default) => unreachable!(),
// TODO: Account implementation
}
}

// #[deprecated = "to be removed once key exchange is encapsulated within Identity"]
pub fn _ke(&self) -> [u8; 32] {
match self {
Self::Psk(psk) => psk.to_bytes(),
Self::Ed25519(ed25519) => {
let x_secret: x25519::SecretKey = ed25519.inner().into();
x_secret.to_bytes()
}
Self::Ed25519(ed25519) => ed25519.inner().into(),
#[cfg(feature = "did")]
Self::DID(DID::PrivateKey(info)) => info.ke_kp().0.to_bytes(),
Self::DID(DID::PrivateKey(info)) => info.ke_kp().0,
#[cfg(feature = "did")]
Self::DID(DID::Default) => unreachable!(),
// TODO: Account implementation
Expand All @@ -90,7 +69,6 @@ impl Identity {
pub fn to_identifier(&self) -> Identifier {
match self {
Self::Ed25519(ed25519) => ed25519.inner().public_key().into(),
&Self::Psk(psk) => psk.into(),
#[cfg(feature = "did")]
Self::DID(did) => did.info().did().into(),
}
Expand All @@ -103,12 +81,6 @@ impl From<Ed25519> for Identity {
}
}

impl From<Psk> for Identity {
fn from(psk: Psk) -> Self {
Self::Psk(psk)
}
}

#[cfg(feature = "did")]
impl From<DID> for Identity {
fn from(did: DID) -> Self {
Expand All @@ -125,10 +97,9 @@ impl From<Identity> for Identifier {
impl Mask<&Identity> for sizeof::Context {
fn mask(&mut self, identity: &Identity) -> Result<&mut Self> {
match identity {
Identity::Psk(psk) => self.mask(Uint8::new(0))?.mask(NBytes::new(psk)),
Identity::Ed25519(ed25519) => self.mask(Uint8::new(1))?.mask(NBytes::new(ed25519)),
Identity::Ed25519(ed25519) => self.mask(Uint8::new(0))?.mask(NBytes::new(ed25519)),
#[cfg(feature = "did")]
Identity::DID(did) => self.mask(Uint8::new(2))?.mask(did),
Identity::DID(did) => self.mask(Uint8::new(1))?.mask(did),
}
}
}
Expand All @@ -140,10 +111,9 @@ where
{
fn mask(&mut self, identity: &Identity) -> Result<&mut Self> {
match identity {
Identity::Psk(psk) => self.mask(Uint8::new(0))?.mask(NBytes::new(psk)),
Identity::Ed25519(ed25519) => self.mask(Uint8::new(1))?.mask(NBytes::new(ed25519)),
Identity::Ed25519(ed25519) => self.mask(Uint8::new(0))?.mask(NBytes::new(ed25519)),
#[cfg(feature = "did")]
Identity::DID(did) => self.mask(Uint8::new(2))?.mask(did),
Identity::DID(did) => self.mask(Uint8::new(1))?.mask(did),
}
}
}
Expand All @@ -158,19 +128,13 @@ where
self.mask(&mut oneof)?;
match oneof.inner() {
0 => {
let mut psk = Psk::default();
self.mask(NBytes::new(&mut psk))?;
*identity = Identity::Psk(psk);
Ok(self)
}
1 => {
let mut ed25519_bytes = [0; ed25519::SECRET_KEY_LENGTH];
self.mask(NBytes::new(&mut ed25519_bytes))?;
*identity = Identity::Ed25519(ed25519::SecretKey::from_bytes(ed25519_bytes).into());
Ok(self)
}
#[cfg(feature = "did")]
2 => {
1 => {
let mut did = DID::default();
self.mask(&mut did)?;
*identity = Identity::DID(did);
Expand All @@ -194,8 +158,6 @@ impl ContentSignSizeof<Identity> for sizeof::Context {
Ok(self)
}

Identity::Psk(_) => Err(anyhow!("PSKs cannot be used as signature keys")),

#[cfg(feature = "did")]
Identity::DID(did_impl) => match did_impl {
DID::PrivateKey(info) => {
Expand Down Expand Up @@ -231,8 +193,6 @@ where
Ok(self)
}

Identity::Psk(_) => Err(anyhow!("PSKs cannot be used as signature keys")),

#[cfg(feature = "did")]
Identity::DID(did_impl) => {
match did_impl {
Expand Down Expand Up @@ -279,17 +239,12 @@ where
F: PRP,
IS: io::IStream,
{
async fn decrypt(&mut self, recipient: &Identity, exchange_key: &[u8], key: &mut [u8]) -> Result<&mut Self> {
match recipient {
Identity::Psk(_) => self
.absorb(External::new(&NBytes::new(Psk::try_from(exchange_key)?)))?
.commit()?
.mask(NBytes::new(key)),
// TODO: Replace with separate logic for EdPubKey and DID instances (pending Identity xkey introduction)
_ => match <[u8; 32]>::try_from(exchange_key) {
Ok(byte_array) => self.x25519(&x25519::SecretKey::from_bytes(byte_array), NBytes::new(key)),
Err(e) => Err(anyhow!("Invalid x25519 key: {}", e)),
},
async fn decrypt(&mut self, _recipient: &Identity, exchange_key: &[u8], key: &mut [u8]) -> Result<&mut Self> {
// TODO: Replace with separate logic for EdPubKey and DID instances (pending Identity xkey
// introduction)
match <[u8; 32]>::try_from(exchange_key) {
Ok(byte_array) => self.x25519(&x25519::SecretKey::from_bytes(byte_array), NBytes::new(key)),
Err(e) => Err(anyhow!("Invalid x25519 key: {}", e)),
}
}
}
12 changes: 0 additions & 12 deletions lets/src/id/psk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@ impl Psk {
spongos.sponge(seed)
}

pub fn as_bytes(&self) -> &[u8] {
&self.0
}

pub(crate) fn to_bytes(self) -> [u8; 32] {
self.0
}

pub fn to_pskid(self) -> PskId {
let mut spongos = Spongos::<KeccakF1600>::init();
spongos.absorb("PSKID");
Expand Down Expand Up @@ -80,10 +72,6 @@ impl PskId {
{
Psk::from_seed::<T>(seed).to_pskid()
}

pub(crate) fn as_bytes(&self) -> &[u8] {
&self.0
}
}

impl AsRef<[u8]> for PskId {
Expand Down
2 changes: 1 addition & 1 deletion lets/src/message/hdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{
};

#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[allow(clippy::upper_case_acronyms)]
pub struct HDF {
encoding: u8,
Expand Down
4 changes: 2 additions & 2 deletions lets/src/message/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use super::{
transport::TransportMessage,
};

#[derive(Clone, Copy, PartialEq, Eq, Hash, Default, Debug)]
#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)]
pub struct Message<Content> {
header: HDF,
payload: PCF<Content>,
Expand All @@ -41,7 +41,7 @@ impl<Payload> Message<Payload> {
}

pub fn header(&self) -> HDF {
self.header
self.header.clone()
DyrellC marked this conversation as resolved.
Show resolved Hide resolved
}

pub fn payload(&self) -> &PCF<Payload> {
Expand Down
Loading