summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/erebos/identity.h2
-rw-r--r--src/attach.cpp12
-rw-r--r--src/identity.cpp101
-rw-r--r--src/identity.h15
-rw-r--r--src/main.cpp7
-rw-r--r--src/message.cpp4
-rw-r--r--src/network.cpp2
-rw-r--r--src/network/protocol.cpp2
-rw-r--r--src/state.cpp2
9 files changed, 118 insertions, 29 deletions
diff --git a/include/erebos/identity.h b/include/erebos/identity.h
index 4792330..fa8fde3 100644
--- a/include/erebos/identity.h
+++ b/include/erebos/identity.h
@@ -41,7 +41,9 @@ public:
bool operator!=(const Identity & other) const;
std::optional<Ref> ref() const;
+ std::optional<Ref> extRef() const;
std::vector<Ref> refs() const;
+ std::vector<Ref> extRefs() const;
std::vector<Ref> updates() const;
class Builder
diff --git a/src/attach.cpp b/src/attach.cpp
index 3d351f8..887de38 100644
--- a/src/attach.cpp
+++ b/src/attach.cpp
@@ -75,11 +75,19 @@ void AttachService::handlePairingResult(Context & ctx, Stored<AttachIdentity> at
if (!key)
throw runtime_error("failed to load secret key");
- auto id = Identity::load(key->signAdd(att->identity).ref());
+ vector<StoredIdentityPart> parts = ctx.local()->identity()->extData();
+ parts.emplace_back(key->signAdd(att->identity));
+ filterAncestors(parts);
+
+ auto id = Identity::load(parts);
if (!id)
printf("New identity validation failed\n");
- auto rid = ctx.local().ref().storage().copy(*id->ref());
+ optional<Ref> tmpref = id->extRef();
+ if (not tmpref)
+ tmpref = id->modify().commit().extRef();
+
+ auto rid = ctx.local().ref().storage().copy(*tmpref);
id = Identity::load(rid);
auto owner = id->owner();
diff --git a/src/identity.cpp b/src/identity.cpp
index ae20b3b..8b6ee2a 100644
--- a/src/identity.cpp
+++ b/src/identity.cpp
@@ -9,7 +9,7 @@
using namespace erebos;
using std::async;
-using std::get_if;
+using std::holds_alternative;
using std::nullopt;
using std::runtime_error;
using std::set;
@@ -89,6 +89,7 @@ vector<Stored<Signed<IdentityData>>> Identity::data() const
for (const auto & d : p->data)
base.push_back(d.base());
+ filterAncestors(base);
return base;
}
@@ -149,8 +150,26 @@ optional<Ref> Identity::ref() const
return nullopt;
}
+optional<Ref> Identity::extRef() const
+{
+ if (p->data.size() == 1)
+ return p->data[0].ref();
+ return nullopt;
+}
+
vector<Ref> Identity::refs() const
{
+ auto base = data();
+ vector<Ref> res;
+ res.reserve(base.size());
+
+ for (const auto & d : base)
+ res.push_back(d.ref());
+ return res;
+}
+
+vector<Ref> Identity::extRefs() const
+{
vector<Ref> res;
res.reserve(p->data.size());
for (const auto & idata : p->data)
@@ -178,9 +197,22 @@ Identity::Builder Identity::create(const Storage & st)
Identity::Builder Identity::modify() const
{
+ vector<Stored<Signed<IdentityData>>> prevBase;
+ vector<StoredIdentityPart> prevExt;
+
+ prevBase.reserve(p->data.size());
+ for (const auto & d : p->data) {
+ prevBase.push_back(d.base());
+ if (holds_alternative<Stored<Signed<IdentityExtension>>>(d.part))
+ prevExt.push_back(d);
+ }
+
+ filterAncestors(prevBase);
+
return Builder (new Builder::Priv {
.storage = p->data[0].ref().storage(),
- .prev = data(),
+ .prevBase = move(prevBase),
+ .prevExt = move(prevExt),
.keyIdentity = p->data[0].base()->data->keyIdentity,
.keyMessage = p->data[0].base()->data->keyMessage,
});
@@ -247,11 +279,18 @@ Identity::Builder::Builder(Priv * p): p(p) {}
Identity Identity::Builder::commit() const
{
- auto idata = p->storage.store(IdentityData {
- .prev = p->prev,
- .name = p->name,
- .owner = p->owner && p->owner->p->data.size() == 1 ?
- optional(p->owner->p->data[0].base()) : nullopt,
+ optional<Stored<Signed<IdentityData>>> ownerBaseData;
+ optional<StoredIdentityPart> ownerExtData;
+ if (p->owner && p->owner->p->data.size() == 1) {
+ ownerExtData = p->owner->p->data[0];
+ ownerBaseData = ownerExtData->base();
+ if (holds_alternative<Stored<Signed<IdentityData>>>(ownerExtData->part))
+ ownerExtData.reset();
+ }
+
+ auto base = p->storage.store(IdentityData {
+ .prev = p->prevBase,
+ .owner = ownerBaseData,
.keyIdentity = p->keyIdentity,
.keyMessage = p->keyMessage,
});
@@ -260,15 +299,38 @@ Identity Identity::Builder::commit() const
if (!key)
throw runtime_error("failed to load secret key");
- auto sdata = key->sign(idata);
- if (idata->owner) {
- if (auto okey = SecretKey::load((*idata->owner)->data->keyIdentity))
- sdata = okey->signAdd(sdata);
+ auto sbase = key->sign(base);
+ if (base->owner) {
+ if (auto okey = SecretKey::load((*base->owner)->data->keyIdentity))
+ sbase = okey->signAdd(sbase);
else
throw runtime_error("failed to load secret key");
}
- auto p = Identity::Priv::validate({ StoredIdentityPart(sdata) });
+ optional<StoredIdentityPart> spart;
+
+ if (not p->prevExt.empty() || p->name || ownerExtData) {
+ auto ext = p->storage.store(IdentityExtension {
+ .base = sbase,
+ .prev = p->prevExt,
+ .name = p->name,
+ .owner = ownerExtData,
+ });
+
+ auto sext = key->sign(ext);
+ if (ext->owner) {
+ if (auto okey = SecretKey::load(p->owner->keyIdentity()))
+ sext = okey->signAdd(sext);
+ else
+ throw runtime_error("failed to load secret key");
+ }
+
+ spart.emplace(sext);
+ } else {
+ spart.emplace(sbase);
+ }
+
+ auto p = Identity::Priv::validate({ *spart });
if (!p)
throw runtime_error("failed to validate committed identity");
@@ -350,6 +412,21 @@ IdentityExtension IdentityExtension::load(const Ref & ref)
};
}
+Ref IdentityExtension::store(const Storage & st) const
+{
+ vector<Record::Item> items;
+
+ items.emplace_back("SBASE", base);
+ for (const auto & p : prev)
+ items.emplace_back("SPREV", p.ref());
+ if (name)
+ items.emplace_back("name", *name);
+ if (owner)
+ items.emplace_back("owner", owner->ref());
+
+ return st.storeObject(Record(std::move(items)));
+}
+
StoredIdentityPart StoredIdentityPart::load(const Ref & ref)
{
if (auto srec = ref->asRecord()) {
diff --git a/src/identity.h b/src/identity.h
index 1653f51..bfa5932 100644
--- a/src/identity.h
+++ b/src/identity.h
@@ -20,9 +20,9 @@ struct IdentityData
static IdentityData load(const Ref &);
Ref store(const Storage & st) const;
- const vector<Stored<Signed<IdentityData>>> prev;
- const optional<string> name;
- const optional<Stored<Signed<IdentityData>>> owner;
+ const vector<Stored<Signed<IdentityData>>> prev {};
+ const optional<string> name {};
+ const optional<Stored<Signed<IdentityData>>> owner {};
const Stored<PublicKey> keyIdentity;
const optional<Stored<PublicKey>> keyMessage;
};
@@ -33,9 +33,9 @@ struct IdentityExtension
Ref store(const Storage & st) const;
const Stored<Signed<IdentityData>> base;
- const vector<StoredIdentityPart> prev;
- const optional<string> name;
- const optional<StoredIdentityPart> owner;
+ const vector<StoredIdentityPart> prev {};
+ const optional<string> name {};
+ const optional<StoredIdentityPart> owner {};
};
struct Identity::Priv
@@ -56,7 +56,8 @@ struct Identity::Priv
struct Identity::Builder::Priv
{
Storage storage;
- vector<Stored<Signed<IdentityData>>> prev = {};
+ vector<Stored<Signed<IdentityData>>> prevBase = {};
+ vector<StoredIdentityPart> prevExt = {};
optional<string> name = nullopt;
optional<Identity> owner = nullopt;
Stored<PublicKey> keyIdentity;
diff --git a/src/main.cpp b/src/main.cpp
index 0eb379b..3100695 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -289,14 +289,15 @@ void startServer(const vector<string> &)
config.service<DirectMessageService>()
.onUpdate([](const DirectMessageThread & thread, ssize_t, ssize_t) {
- if (thread.at(0).from()->sameAs(server->identity()))
+ if (thread.at(0).from()->sameAs(server->identity().finalOwner()))
return;
ostringstream ss;
string name = "<unnamed>";
- if (auto opt = thread.peer().name())
- name = *opt;
+ if (auto from = thread.at(0).from())
+ if (auto fname = from->name())
+ name = *fname;
ss << "dm-received"
<< " from " << name
diff --git a/src/message.cpp b/src/message.cpp
index 8ae1601..a9d6139 100644
--- a/src/message.cpp
+++ b/src/message.cpp
@@ -69,7 +69,7 @@ Ref DirectMessageData::store(const Storage & st) const
for (const auto & prev : prev)
items.emplace_back("PREV", prev.ref());
if (from)
- items.emplace_back("from", from->ref().value());
+ items.emplace_back("from", from->extRef().value());
if (time)
items.emplace_back("time", *time);
if (text)
@@ -373,7 +373,7 @@ DirectMessage DirectMessageService::send(const Identity & to, const string & tex
auto threads = loc->shared<DirectMessageThreads>();
msg = st.store(DirectMessageData {
.prev = threads.thread(to).p->head,
- .from = server.identity().finalOwner(),
+ .from = loc->identity()->finalOwner(),
.time = ZonedTime::now(),
.text = text,
});
diff --git a/src/network.cpp b/src/network.cpp
index c1c9c0f..7f37cf7 100644
--- a/src/network.cpp
+++ b/src/network.cpp
@@ -736,7 +736,7 @@ void Server::Peer::finalizeChannel(ReplyBuilder & reply, unique_ptr<Channel> ch)
connection.channel().emplace<unique_ptr<Channel>>(move(ch));
vector<NetworkProtocol::Header::Item> hitems;
- for (const auto & r : server.self.refs())
+ for (const auto & r : server.self.extRefs())
reply.header(NetworkProtocol::Header::AnnounceUpdate { r.digest() });
for (const auto & r : server.self.updates())
reply.header(NetworkProtocol::Header::AnnounceUpdate { r.digest() });
diff --git a/src/network/protocol.cpp b/src/network/protocol.cpp
index 02c3dae..b781693 100644
--- a/src/network/protocol.cpp
+++ b/src/network/protocol.cpp
@@ -150,7 +150,7 @@ void NetworkProtocol::updateIdentity(Identity id)
self = move(id);
vector<Header::Item> hitems;
- for (const auto & r : self->refs())
+ for (const auto & r : self->extRefs())
hitems.push_back(Header::AnnounceUpdate { r.digest() });
for (const auto & r : self->updates())
hitems.push_back(Header::AnnounceUpdate { r.digest() });
diff --git a/src/state.cpp b/src/state.cpp
index 40d4eec..31171d7 100644
--- a/src/state.cpp
+++ b/src/state.cpp
@@ -38,7 +38,7 @@ Ref LocalState::store(const Storage & st) const
vector<Record::Item> items;
if (p->identity)
- items.emplace_back("id", *p->identity->ref());
+ items.emplace_back("id", *p->identity->extRef());
for (const auto & x : p->shared.tip)
items.emplace_back("shared", x);