Skip to content

Groups

Info::Info

Constructs a group info config object from existing data (stored from dump()).

To construct a blank info object (i.e. with no pre-existing dumped data to load) pass std::nullopt as the third argument.

Encryption keys must be loaded before the Info object can be modified or parse other Info messages, and are typically loaded by providing the Info object to the Keys class.

Declaration

Info(ustring_view ed25519_pubkey,
     std::optional<ustring_view> ed25519_secretkey,
     std::optional<ustring_view> dumped);

Parameters

  • ed25519_pubkey is the public key of this group, used to validate config messages. Config messages not signed with this key will be rejected.
  • ed25519_secretkey is the secret key of the group, used to sign pushed config messages. This is only possessed by the group admin(s), and must be provided in order to make and push config changes.
  • dumped — either std::nullopt to construct a new, empty object; or binary state data that was previously dumped from an instance of this class by calling dump().

Returns

Info::destroy_group

Sets the group as permanently deleted, and set this status in the group's config. Receiving clients are supposed to remove the conversation from their conversation list when this happens.

This change is permanent; the flag cannot be unset once set!

Declaration

void destroy_group();

Parameters

None: this call is destructive and permanent. Be careful!

Returns

Info::encryption_domain

Returns the encryption domain used when encrypting messages of this type.

Declaration

const char* encryption_domain() const override { return "groups::Info"; }

Parameters

This endpoint takes no inputs.

Returns

  • const char* - Will return "groups::Info"

Info::get_created

Returns the creation timestamp, if set/known.

Declaration

std::optional<int64_t> get_created() const;

Parameters

This endpoint takes no inputs.

Returns

  • std::optional<int64_t> — the unix timestamp when the group was created, or nullopt if the creation timestamp is not set.

Info::get_delete_attach_before

Returns the delete-attachments-before unix timestamp (seconds) for the group; clients should delete all messages from the closed group with timestamps earlier than this value, if set.

Returns std::nullopt if no delete-attachments-before timestamp is set.

Declaration

std::optional<int64_t> get_delete_attach_before() const;

Parameters

This endpoint takes no inputs.

Returns

  • int64_t — the unix timestamp for which all older message attachments shall be deleted

Info::get_delete_before

Returns the delete-before unix timestamp (seconds) for the group; clients should delete all messages from the closed group with timestamps earlier than this value, if set.

Returns std::nullopt if no delete-before timestamp is set.

Declaration

std::optional<int64_t> get_delete_before() const;

Parameters

This endpoint takes no inputs.

Returns

  • int64_t — the unix timestamp for which all older messages shall be delete

Info::get_description

Returns the group description, or std::nullopt if there is no group description set.

If given a description longer than Info::DESCRIPTION_MAX_LENGTH (2000) bytes it will be truncated.

Declaration

std::optional<std::string_view> get_description() const;

Parameters

This endpoint takes no inputs.

Returns

  • std::optional<std::string_view> - Returns the group description if it is set

Info::get_expiry_timer

Returns the group's current message expiry timer, or std::nullopt if no expiry timer is set. If not nullopt then the expiry will always be >= 1s.

Note that groups only support expire-after-send expiry timers and so there is no separate expiry type setting.

Declaration

std::optional<std::chrono::seconds> get_expiry_timer() const;

Parameters

This endpoint takes no inputs.

Returns

  • std::chrono::seconds — the expiry timer duration

Info::get_name

Returns the group name, or std::nullopt if there is no group name set.

Declaration

std::optional<std::string_view> get_name() const;

Parameters

This endpoint takes no inputs.

Returns

  • std::optional<std::string_view> - Returns the group name if it is set

Info::get_profile_pic

Gets the group's current profile pic URL and decryption key. The returned object will evaluate as false if the URL and/or key are not set.

Declaration

profile_pic get_group_pic() const;

Parameters

This endpoint takes no inputs.

Returns

  • profile_pic - Returns the group's profile pic

Info::id

Contains the (read-only) id of this group, that is, 03 followed by the pubkey in hex. (This is equivalent to a 05-prefixed session_id, but is the group-specific identifier).

Declaration

const std::string id;

Parameters

This endpoint takes no inputs.

Returns

  • std::string containing the hex group id/pubkey

Info::is_destroyed

Returns true if this group has been marked destroyed; the receiving client is expected to delete it.

Declaration

bool is_destroyed() const;

Parameters

This endpoint takes no inputs.

Returns

  • true if the group has been destroyed, false otherwise.

Info::set_created

Sets the created timestamp. It's recommended (but not required) that you only set this if not already set.

Declaration

void set_created(int64_t timestamp);

Parameters

  • session_id — hex string of the session id
  • timestamp — standard unix timestamp when the group was created

Returns

Info::set_delete_attach_before

Sets a "delete attachments before" unix timestamp: this instructs clients to drop the attachments (though not necessarily the messages themselves; see get_delete_before for that) from any messages older than the given timestamp. Returns nullopt if no delete-attachments-before timestamp is set.

The given value is checked for sanity (e.g. if you pass milliseconds it will be interpreted as such)

Declaration

void set_delete_attach_before(int64_t timestamp);

Parameters

  • timestamp — the new unix timestamp before which clients should delete attachments. Pass 0 (or negative) to disable the delete-attachment-before timestamp.

Returns

Info::set_delete_before

Sets a "delete before" unix timestamp: this instructs clients to delete all messages from the closed group history with a timestamp earlier than this value. Returns nullopt if no delete-before timestamp is set.

The given value is checked for sanity (e.g. if you pass milliseconds it will be interpreted as such)

Declaration

void set_delete_before(int64_t timestamp);

Parameters

  • timestamp — the new unix timestamp before which clients should delete messages. Pass 0 (or negative) to disable the delete-before timestamp.

Returns

Info::set_description

Sets the optional group description; if given an empty string then an existing description is removed.

Declaration

void set_description(std::string_view new_desc);

Parameters

  • new_desc — The new description to be put into the group Info

Returns

Info::set_description_truncated

Sets the optional group description; if given an empty string then an existing description is removed. The same as set_description but if the name is too long it'll be truncated.

Declaration

void set_description_truncated(std::string new_desc);

Parameters

  • new_desc — The new description to be put into the group Info

Returns

Info::set_expiry_timer

Sets (or clears) the group's message expiry timer. If > 0s the setting becomes the delete-after-send value; if omitted or given a 0 or negative duration then the expiring message timer is disabled for the group.

Declaration

void set_expiry_timer(std::chrono::seconds expiration_timer = 0min);

Parameters

  • expiration_timer — how long the expiration timer should be, defaults to zero (disabling message expiration) if the argument is omitted.

Returns

Info::set_name

Sets the group name; if given an empty string then the name is removed.

If given a name longer than Info::NAME_MAX_LENGTH (100) bytes an error will be thrown.

Declaration

void set_name(std::string_view new_name);

Parameters

  • new_name — The name to be put into the group Info

Returns

Info::set_name_truncated

Sets the group name; if given an empty string then the name is removed.

If given a name longer than Info::NAME_MAX_LENGTH (100) bytes it will be truncated.

Declaration

void set_name_truncated(std::string new_name);

Parameters

  • new_name — The name to be put into the group Info

Returns

Info::set_profile_pic

Sets the group's current profile pic to a new URL and decryption key. Clears both if either one is empty.

Declaration

void set_profile_pic(std::string_view url, ustring_view key);
void set_profile_pic(profile_pic pic);

Parameters

  • First function:
  • url — URL pointing to the profile pic
  • key — Decryption key
  • Second function:
  • pic — Profile pic object

Returns

Info::storage_namespace

Returns the Info namespace. Is constant, will always return Namespace::GroupInfo

Declaration

Namespace storage_namespace() const override { return Namespace::GroupInfo; }

Parameters

This endpoint takes no inputs.

Returns

  • Namespace - Will return Namespace::GroupInfo

Keys::Keys

Constructs a group members config object from existing data (stored from dump()) and a list of encryption keys for encrypting new and decrypting existing messages.

To construct a blank info object (i.e. with no pre-existing dumped data to load) pass std::nullopt as the last argument.

When no dump is provided the initial Keys object will be created with no keys loaded at all, these will be loaded later into this and the info/members objects when loading keys via received config messages. If this is a brand new group then rekey() MUST be called, otherwise the group will be in an invalid state.

Declaration

Keys(ustring_view user_ed25519_secretkey,
     ustring_view group_ed25519_pubkey,
     std::optional<ustring_view> group_ed25519_secretkey,
     std::optional<ustring_view> dumped,
     Info& info,
     Members& members);

Parameters

  • user_ed25519_secretkey is the ed25519 secret key backing the current user's session ID, and is used to decrypt incoming keys. It is required.
  • group_ed25519_pubkey is the public key of the group, used to verify message signatures on key updates. Required. Should not include the 03 prefix.
  • group_ed25519_secretkey is the secret key of the group, used to encrypt, decrypt, and sign config messages. This is only possessed by the group admin(s), and must be provided in order to make and push config changes.
  • dumped — either std::nullopt to construct a new, empty object; or binary state data that was previously dumped from an instance of this class by calling dump().
  • info and members — will be loaded with the group keys, if present in the dump.

Returns

Keys::current_hashes

Returns a set of message hashes of messages that contain currently active decryption keys. These are the messages that should be periodically renewed by clients with write access to keep them alive for other accounts (or devices) who might need them in the future.

Declaration

std::unordered_set<std::string> current_hashes() const;

Parameters

This endpoint takes no inputs.

Returns

  • vector of message hashes

Keys::decrypt_message

Decrypts group message content that was presumably encrypted with encrypt_message, verifies the sender signature, decompresses the message (if necessary) and then returns the author pubkey and the plaintext data.

To prevent against memory exhaustion attacks, this method will fail if the value is a compressed value that would decompress to a value larger than 1MB.

Declaration

std::pair<std::string, ustring> decrypt_message(ustring_view ciphertext) const;

Parameters

  • ciphertext — an encrypted, encoded, signed, (possibly) compressed message as produced by encrypt_message().

Returns

  • std::pair<std::string, ustring> — the session ID (in hex) and the plaintext binary data that was encrypted.

On failure this throws a std::exception-derived exception with a .what() string containing some diagnostic info on what part failed. Typically a production session client would catch (and possibly log) but otherwise ignore such exceptions and just not process the message if it throws.

Keys::dump

Returns a dump of the current state of this keys config that allows the Keys object to be reinstantiated from scratch. Updates the internal needs_dump flag to false.

Although this can be called at any time, it is recommended to only do so when needs_dump() returns true.

Declaration

ustring dump();

Parameters

This endpoint takes no inputs.

Returns

  • opaque binary data containing the group keys and other Keys config data that can be passed to the Keys constructor to reinitialize a Keys object with the current state.

Keys::encrypt_message

Compresses, signs, and encrypts group message content.

This method is passed a binary value containing a group message (typically a serialized protobuf, but this method doesn't care about the specific data). That data will be, in order: - compressed (but only if this actually reduces the data size) - signed by the user's underlying session Ed25519 pubkey - tagged with the user's underlying session Ed25519 pubkey (from which the session id can be computed). - all of the above encoded into a bt-encoded dict - suffix-padded with null bytes so that the final output value will be a multiple of 256 bytes - encrypted with the most-current group encryption key

Since compression and padding is applied as part of this method, it is not required that the given message include its own padding (and in fact, such padding will typically be compressed down to nothing (if non-random)).

This final encrypted value is then returned to be pushed to the swarm as-is (i.e. not further wrapped). For users downloading the message, all of the above is processed in reverse by passing the returned message into decrypt_message().

The current implementation uses XChaCha20-Poly1305 for encryption and zstd for compression; the bt-encoded value is a dict consisting of keys: - "": the version of this encoding, currently set to 1. This MUST be bumped if this is changed in such a way that older clients will not be able to properly decrypt such a message. - "a": the Ed25519 pubkey (32 bytes) of the author of the message. (This will be converted to a x25519 pubkey to extract the sender's session id when decrypting). - "s": signature by "a" of whichever of "d" or "z" are included in the data. Exacly one of: - "d": the uncompressed data (which must be non-empty if present) - "z": the zstd-compressed data (which must be non-empty if present)

When compression is enabled (by omitting the compress argument or specifying it as true) then ZSTD compression will be attempted on the plaintext message and will be used if the compressed data is smaller than the uncompressed data. If disabled, or if compression does not reduce the size, then the message will not be compressed.

This method will throw on failure, which can happen in two cases: - if there no encryption keys are available at all (which should not occur in normal use). - if given a plaintext buffer larger than 1MB (even if the compressed version would be much smaller). It is recommended that clients impose their own limits much smaller than this on data passed into encrypt_message; this limitation is in this function to match the decrypt_message limit which is merely intended to guard against decompression memory exhaustion attacks.

Declaration

ustring encrypt_message(
        ustring_view plaintext, bool compress = true, size_t padding = 256) const;

Parameters

  • plaintext — the binary message to encrypt.
  • compress — can be specified as false to forcibly disable compression. Normally omitted, to use compression if and only if it reduces the size.
  • padding — the padding multiple: padding will be added as needed to attain a multiple of this value for the final result. 0 or 1 disables padding entirely. Normally omitted to use the default of next-multiple-of-256.

Returns

  • ciphertext — the encrypted, etc. value to send to the swarm

Keys::encryption_domain

Returns the encryption domain used when encrypting messages of this type.

Declaration

const char* encryption_domain() const { return "groups::Keys"; }

Parameters

This endpoint takes no inputs.

Returns

  • const char* - Will return "groups::Keys"

Keys::encryption_key

Accesses the current encryption key: that is, the most current group decryption key. Throws if there are no encryption keys at all. (This is essentially the same as group_keys()[0], except for the throwing and avoiding needing to constructor a vector).

You normally don't need to call this; the key is used automatically by methods such as encrypt_message() that need it.

Declaration

ustring_view group_enc_key() const;

Parameters

This endpoint takes no inputs.

Returns

  • ustring_view of the most current group encryption key.

Keys::group_keys

Returns all the unexpired decryption keys that we know about. Keys are returned ordered from most-recent to least-recent (and so the first one is meant to be used as the encryption key), including a pending key if this object is in the process of pushing a new keys message.

This isn't typically directly needed: this object manages the key lists in the info and members objects itself.

Declaration

std::vector<ustring_view> group_keys() const;

Parameters

This endpoint takes no inputs.

Returns

  • std::vector<ustring_view> - vector of encryption keys.

Keys::is_admin

True if we have admin permissions (i.e. we know the group's master secret key).

Declaration

bool admin() const { return _sign_sk && _sign_pk; }

Parameters

This endpoint takes no inputs.

Returns

  • true if this object knows the group's master key

Keys::key_supplement

Generates a supplemental key message for one or more session IDs. This is used to distribute existing active keys to a new member so that that member can access existing keys, configs, and messages. Only admins can call this.

The recommended order of operations for adding such a member is: - add the member to Members - generate the key supplement - push new members & key supplement (ideally in a batch) - send invite details, auth signature, etc. to the new user

To add a member without giving them access you would use rekey() instead of this method.

Declaration

ustring key_supplement(const std::vector<std::string>& sids) const;

Parameters

  • sid or sids — session ID(s) of the members to generate a supplemental key for (there are two versions of this function, one taking a single ID and one taking a vector). Session IDs are specified in hex.

Returns

  • ustring containing the message that should be pushed to the swarm containing encrypted keys for the given user(s).

Keys::load_admin_key

Loads the group secret key into the Keys object (as well as passing it along to the Info and Members objects).

The primary use of this is when accepting a promotion-to-admin: the Keys object would be constructed as a regular member (without the admin key) then this method "upgrades" the object with the group signing key.

This will do nothing if the secret key is already known; it will throw if the given secret key does not yield the group's public key. The given key can be either the 32 byte seed, or the libsodium 64 byte "secret key" (which is just the seed and cached public key stuck together).

Declaration

void load_admin_key(ustring_view secret, Info& info, Members& members);

Parameters

  • secret — the group's 64-byte secret key or 32-byte seed
  • info and members — will be loaded with the group keys if the key is loaded successfully.

Outputs: nothing. After a successful call, admin() will return true. Throws if the given secret key does not match the group's pubkey.

Returns

Keys::load_key

Loads a key pulled down from the swarm into this Keys object.

A Session client must process messages from the keys namespace before other group config messages as new key messages may contain encryption keys needed to decrypt the other group config message types.

It is safe to load the same config multiple times, and to load expired configs; such cases would typically not change the keys, but are allowed anyway.

This method should always be wrapped in a try/catch: if the given configuration data is malformed or is not properly signed an exception will be raised (but the Keys object remains usable).

Declaration

bool load_key_message(
        std::string_view hash,
        ustring_view data,
        int64_t timestamp_ms,
        Info& info,
        Members& members);

Parameters

  • hash - the message hash from the swarm
  • data - the full stored config message value
  • timestamp_ms - the timestamp (from the swarm) when this message was stored (used to track when other keys expire).
  • info - the given group::Info object's en/decryption key list will be updated to match this object's key list.
  • members - the given group::Members object's en/decryption key list will be updated to match this object's key list.

Returns

  • throws std::runtime_error (typically a subclass thereof) on failure to parse.
  • returns true if we found a key for us in the message, false if we did not. Note that this is mainly informative and does not signal an error: false could mean, for instance, be a supplemental message that wasn't for us. Note also that true doesn't mean keys changed: it could mean we decrypted one for us, but already had it.

Keys::make_dump

Returns a dump of the current state; unlike dump() this does not update the internal needs_dump flag; it is mostly used internally (by dump()), but can also be called externally for debugging purposes.

Declaration

ustring make_dump() const;

Parameters

This endpoint takes no inputs.

Returns

  • ustring — Returns binary data of the state dump

Keys::needs_dump

Returns true if this Keys config has changes, either made directly or from incoming configs, that need to be dumped to the database (made since the last call to dump()), false if no changes have been made.

Declaration

bool needs_dump() const;

Parameters

This endpoint takes no inputs.

Returns

  • true if state needs to be dumped, false if state hasn't changed since the last call to dump().

Keys::needs_rekey

Returns true if the key list requires a new key to be generated and pushed to the server (by calling rekey()). This will only be true for admin accounts (as only admin accounts can call rekey()). Note that this value will also remain true until the pushed data is fetched and loaded via load_key_message.

Note that this not only tracks when an automatic rekey() is needed because of a key collision (such as two admins removing different members at the same time); there are other situations in which rekey() should also be called (such as when kicking a member) that are not reflected by this flag.

The recommended use of this method is to call it immediately after fetching messages from the group config namespace of the swarm, whether or not new configs were retrieved, but after processing incoming new config messages that were pulled down.

Unlike regular config messages, there is no need to confirm the push: confirmation (and adoption of the new keys) happens when the new keys arrived back down from the swarm in the next fetch.

Declaration

bool needs_rekey() const;

Parameters

This endpoint takes no inputs.

Returns

  • true if a rekey is needed, false otherwise.

Keys::pending_config

If a rekey has been performed but not yet confirmed then this will contain the config message to be pushed to the swarm. If there is no push current pending then this returns nullopt. The value should be used immediately (i.e. the ustring_view may not remain valid if other calls to the config object are made).

Declaration

std::optional<ustring_view> pending_config() const;

Parameters

This endpoint takes no inputs.

Returns

  • std::optional<ustring_view> — returns a populated config message that should be pushed, if not yet confirmed, otherwise when no pending update is present this returns nullopt.

Keys::pending_key

After calling rekey() this contains the new group encryption key before it is confirmed pushed into the swarm. This is primarily intended for internal use as this key is generally already propagated to the member/info lists when rekeying occurs.

The pending key is dropped when an incoming keys message is successfully loaded with either the pending key itself, or a keys message with a higher generation.

Declaration

std::optional<ustring_view> pending_key() const;

Parameters

This endpoint takes no inputs.

Returns

  • std::optional<ustring_view> the encryption key generated by the last rekey() call. This is set to a new key when rekey() is called, and is cleared when any config message is successfully loaded by load_key.

Keys::rekey

Generate a new encryption key for the group and returns an encrypted key message to be pushed to the swarm containing the key, encrypted for the members of the given config::groups::Members object. This can only be done by an admin account (i.e. we must have the group's private key).

This method is intended to be called in these situations: - potentially after loading new keys config messages (see needs_rekey()) - when removing a member to switch to a new encryption key for the group that excludes that member. - when adding a member and switching to a new encryption key (without making the old key available to the member) so that the new member cannot decipher pre-existing configs and messages.

This method is closely coupled to the group's Info and Members configs: it updates their encryption keys and sets them as dirty, requiring a re-push to re-encrypt each of them. Typically a rekey is performed as follows:

  • rekey() is called, returning the new keys config.
  • info.push() is called to get the new info config (re-encrypted with the new key)
  • members.push() is called to get the new members config (using the new key)
  • all three new configs are pushed (ideally all at once, in a single batch request).

Declaration

ustring_view rekey(Info& info, Members& members);

Parameters

  • Info - the group's Info; it will be dirtied after the rekey and will require a push.
  • Members - the current Members config for the group. When removing one or more members this should be the list of members with the specific members already removed. The members config will be dirtied after the rekey and will require a push.

Returns

  • ustring_view containing the data that needs to be pushed to the config keys namespace for the group. (This can be re-obtained from pending_config() if needed until it has been confirmed or superceded). This data must be consumed or copied from the returned string_view immediately: it will not be valid past other calls on the Keys config object.

Keys::size

Returns the number of distinct decryption keys that we know about. Mainly for debugging/information purposes.

Declaration

size_t size() const;

Parameters

This endpoint takes no inputs.

Returns

  • size_t of the number of keys we know about

Keys::storage_namespace

Returns the Keys namespace. Is constant, will always return Namespace::GroupKeys

Declaration

Namespace storage_namespace() const { return Namespace::GroupKeys; }

Parameters

This endpoint takes no inputs.

Returns

  • Namespace - Will return Namespace::GroupKeys

Keys::swarm_auth

This struct containing the storage server authentication values for subaccount authentication. The three strings in this struct may be either raw bytes, or base64 encoded, depending on the binary parameter passed to swarm_subaccount_sign.

.subaccount is the value to be passed as the "subaccount" authentication parameter. (It consists of permission flags followed by a blinded public key.)

.subaccount_sig is the value to be passed as the "subaccount_sig" authentication parameter. (It consists of an admin-produced signature of the subaccount, providing permission for that token to be used for authentication).

.signature is the value to be passed as the "signature" authentication parameter. (It is an Ed25519 signature that validates using the blinded public key inside subaccount).

Declaration

struct swarm_auth {

Parameters

This endpoint takes no inputs.

Returns

Keys::swarm_make_subaccount

Constructs a swarm subaccount signing value that a member can use to access messages in the swarm. Requires group admins keys.

Declaration

ustring swarm_make_subaccount(
        std::string_view session_id, bool write = true, bool del = false) const;

Parameters

  • session_id — the session ID of the member (in hex)
  • write — if true (which is the default if omitted) then the member shall be allowed to submit messages into the group account of the swarm and extend (but not shorten) the expiry of messages in the group account. If false then the user can only retrieve messages.
  • del — if true (default is false) then the user shall be allowed to delete messages from the swarm. This permission can be used to appoint a sort of "moderator" who can delete messages without having the full admin group keys.

Returns

  • ustring — contains a subaccount swarm signing value; this can be passed (by the user) into swarm_subaccount_sign to sign a value suitable for swarm authentication. (Internally this packs the flags, blinding factor, and group admin signature together and will be 4 + 32 + 64 = 100 bytes long).

This value must be provided to the user so that they can authentication. The user should call swarm_verify_subaccount to verify that the signing value was indeed signed by a group admin before using/storing it.

The signing value produced will be the same (for a given session_id/write/del values) when constructed by any admin of the group.

Keys::swarm_subaccount_sign

This helper function generates the required signature for swarm subaccount authentication, given the user's keys and swarm auth keys (as provided by an admin, produced via swarm_make_subaccount).

Storage server subaccount authentication requires passing the three values in the returned struct in the storage server request. (See Keys::swarm_auth for details).

Declaration

swarm_auth swarm_subaccount_sign(
        ustring_view msg, ustring_view signing_value, bool binary = false) const;

Parameters

  • msg — the data that needs to be signed (which depends on the storage server request being made; for example, "retrieve9991234567890123" for a retrieve request to namespace 999 made at unix time 1234567890.123; see storage server RPC documentation for details).
  • signing_value — the 100-byte subaccount signing value, as produced by an admin's swarm_make_subaccount and provided to this member.
  • binary — if set to true then the returned values will be binary. If omitted (or explicitly false), the returned struct values will be base64-encoded suitable for direct passing as JSON values to the storage server without further encoding/modification.

Returns

  • struct containing three binary values enabling swarm authentication (see description above).

Keys::swarm_subaccount_token

Constructs the subaccount token for a session id. The main use of this is to submit a swarm token revocation; for issuing subaccount tokens you want to use swarm_make_subaccount instead. This will produce the same subaccount token that swarm_make_subaccount implicitly creates that can be passed to a swarm to add a revocation for that subaccount.

This is recommended to be used when removing a non-admin member to prevent their access. (Note, however, that there are circumstances where this can fail to prevent access, and so should be combined with proper member removal and key rotation so that even if the member gains access to messages, they cannot read them).

Declaration

ustring swarm_subaccount_token(
        std::string_view session_id, bool write = true, bool del = false) const;

Parameters

  • session_id — the session ID of the member (in hex)
  • write, del — optional; see swarm_make_subaccount. The same arguments should be provided (or omitted) as were used in swarm_make_subaccount.

Returns

  • 36 byte token that can be used for swarm token revocation.

Keys::swarm_verify_subaccount

Verifies that a received subaccount signing value (allegedly produced by swarm_make_subaccount) is a valid subaccount signing value for the given group pubkey, including a proper signature by an admin of the group. The signing value must have read permission, but parameters can be given to also require write or delete permissions. A subaccount signing value should always be checked for validity using this before creating a group that would depend on it.

There are two versions of this function: a static one callable without having a Keys instance that takes the group id and user's session Ed25519 secret key as arguments; and a member function that omits these first two arguments (using the ones from the Keys instance).

Declaration

static bool swarm_verify_subaccount(
        std::string group_id,
        ustring_view session_ed25519_secretkey,
        ustring_view signing_value,
        bool write = false,
        bool del = false);

Parameters

  • groupid — the group id/pubkey, in hex, beginning with "03".
  • session_ed25519_secretkey — the user's Session ID secret key.
  • signing_value — the subaccount signing value to validate
  • write — if true, require that the signing_value has write permission (i.e. that the user will be allowed to post messages).
  • del — if true, required that the signing_value has delete permissions (i.e. that the user will be allowed to remove storage messages from the group's swarm). Note that this permission is about forcible swarm message deletion, and has no effect on an ability to submit a deletion meta-message to the group (which only requires writing a message).

Returns

  • true if signing_value is a valid subaccount signing value for groupid with read (and possible write and/or del permissions, if requested). false if the signing value does not validate or does not meet the requirements.

Members::Members

Constructs a group members config object from existing data (stored from dump()) and a list of encryption keys for encrypting new and decrypting existing messages.

To construct a blank info object (i.e. with no pre-existing dumped data to load) pass std::nullopt as the third argument.

Encryption keys must be loaded before the Info object can be modified or parse other Info messages, and are typically loaded by providing the Info object to the Keys class.

Declaration

Members(ustring_view ed25519_pubkey,
        std::optional<ustring_view> ed25519_secretkey,
        std::optional<ustring_view> dumped);

Parameters

  • ed25519_pubkey is the public key of this group, used to validate config messages. Config messages not signed with this key will be rejected.
  • ed25519_secretkey is the secret key of the group, used to sign pushed config messages. This is only possessed by the group admin(s), and must be provided in order to make and push config changes.
  • dumped — either std::nullopt to construct a new, empty object; or binary state data that was previously dumped from an instance of this class by calling dump().

Returns

Members::begin

Iterators for iterating through all members. Typically you access this implicit via a for loop over the Members object:

    for (auto& member : members) {
        // use member.session_id, member.name, etc.
    }

This iterates in sorted order through the session_ids.

It is NOT permitted to add/modify/remove records while iterating; instead such modifications require two passes: an iterator loop to collect the required modifications, then a second pass to apply the modifications.

Declaration

iterator begin() const { return iterator{data["m"].dict()}; }

Parameters

This endpoint takes no inputs.

Returns

  • iterator - Returns an iterator for the beginning of the members

Members::encryption_domain

Returns the encryption domain used when encrypting messages of this type.

Declaration

const char* encryption_domain() const override { return "groups::Members"; }

Parameters

This endpoint takes no inputs.

Returns

  • const char* - Will return "groups::Members"

Members::end

Iterator for passing the end of the members

Declaration

iterator end() const { return iterator{nullptr}; }

Parameters

This endpoint takes no inputs.

Returns

  • iterator - Returns an iterator for the end of the members

Members::erase

Removes a session ID from the member list, if present.

Typically this call should be coupled with a re-key of the group's encryption key so that the removed member cannot read the group. For example:

bool removed = members.erase("050123456789abcdef...");
// You can remove more than one at a time, if needed:
removed |= members.erase("050000111122223333...");

if (removed) {
    auto new_keys_conf = keys.rekey(members);
    members.add_key(*keys.pending_key(), true);
    auto [seqno, new_memb_conf, obs] = members.push();

    // Send the two new configs to the swarm (via a seqence of two `store`s):
    // - new_keys_conf goes into the keys namespace
    // - new_memb_conf goes into the members namespace
}

Declaration

bool erase(std::string_view session_id);

Parameters

  • session_id the hex session ID of the member to remove

Returns

  • true if the member was found (and removed); false if the member was not in the list.

Members::get

Looks up and returns a member by hex session ID. Returns nullopt if the session ID was not found, otherwise returns a filled out member.

Declaration

std::optional<member> get(std::string_view pubkey_hex) const;

Parameters

  • pubkey_hex — hex string of the session id

Returns

  • std::optional<member> - Returns nullopt if session ID was not found, otherwise a filled out member struct.

Members::get_or_construct

Similar to get(), but if the session ID does not exist this returns a filled-out member containing the session_id (all other fields will be empty/defaulted). This is intended to be combined with set to set-or-create a record.

NB: calling this does not add the session id to the member list when called: that requires also calling set with this value.

Declaration

member get_or_construct(std::string_view pubkey_hex) const;

Parameters

  • pubkey_hex — hex string of the session id

Returns

  • member - Returns a filled out member struct

Members::get_status

This function goes through the various status values and returns a single consolidated status for the member.

Declaration

member::Status get_status(const member& member) const {

Parameters

  • member — member value to to retrieve the status for

Returns

  • status - an enum indicating the consolidated status of this member in the group.

Members::has_pending_send

This function can be used to check if a member is pending send locally.

Declaration

bool has_pending_send(std::string pubkey_hex) const;

Parameters

  • pubkey_hex — hex string of the session id

Returns

  • bool - true if that sessionid is marked as pending send locally

Members::set

Sets or updates the various values associated with a member with the given info. The usual use is to access the current info, change anything desired, then pass it back into set, e.g.:

    auto m = members.get_or_construct(pubkey);
    m.name = "Session User 42";
    members.set(m);

Declaration

void set(const member& member);

Parameters

  • member — member value to set

Returns

Members::set_pending_send

This function can be used to set the pending send state of a member. If that effectively made a change, it will set _needs_dump to true.

Declaration

void set_pending_send(std::string pubkey_hex, bool pending);

Parameters

  • pubkey_hex — hex string of the session id
  • pending — pending send state to set for that member

Returns

Members::size

Returns the number of members in the group.

Declaration

size_t size() const;

Parameters

This endpoint takes no inputs.

Returns

  • size_t - number of members

Members::storage_namespace

Returns the Members namespace. Is constant, will always return Namespace::GroupMembers

Declaration

Namespace storage_namespace() const override { return Namespace::GroupMembers; }

Parameters

This endpoint takes no inputs.

Returns

  • Namespace - Will return Namespace::GroupMembers

current_generation

Returns the current generation number for the latest keys message.

Declaration

int current_generation() const { return keys_.empty() ? 0 : keys_.back().generation; }

Parameters

This endpoint takes no inputs.

Returns

  • int — latest keys generation number.

member::admin

Flag that is set to indicate to the group that this member is an admin or has been promoted to admin.

Note that this is only informative but isn't a permission gate: someone could still possess the admin keys without this (e.g. if they cleared the flag to appear invisible), or could have lost (or never had) the keys even if this is set.

Declaration

bool admin = false;

member::into

Converts the member info into a C struct.

Declaration

void into(config_group_member& m) const;

Parameters

  • m — Reference to C struct to fill with group member info.

Returns

member::name

The member's human-readable name. Optional. This is used by other members of the group to display a member's details before having seen a message from that member.

Declaration

std::string name;

member::profile_picture

The member's profile picture (URL & decryption key). Optional. This is used by other members of the group to display a member's details before having seen a message from that member.

Declaration

profile_pic profile_picture;

member::session_id

The member's session ID, in hex.

Declaration

std::string session_id;

member::set_invite_failed

This marks the user to indicate that their invitation message failed to send (this is intended as a signal to other clients that the invitation should be reissued).

Declaration

void set_invite_failed() { invite_status = STATUS_FAILED; }

Parameters

This endpoint takes no inputs.

Returns

member::set_invite_not_sent

This resets the invite status of a user to STATUS_NOT_SENT.

Declaration

void set_invite_not_sent() { invite_status = STATUS_NOT_SENT; }

Parameters

This endpoint takes no inputs.

Returns

member::set_invite_sent

This marks the user as having had an invitation message sent to them.

Declaration

void set_invite_sent() { invite_status = STATUS_SENT; }

Parameters

This endpoint takes no inputs.

Returns

member::set_name

Sets a name; this is exactly the same as assigning to .name directly, except that we throw an exception if the given name is longer than MAX_NAME_LENGTH.

Note that you can set a longer name directly into the .name member, but it will be truncated when serializing the record.

Declaration

void set_name(std::string name);

Parameters

  • name — Name to assign to the contact

Returns

member::set_name_truncated

Sets a name; this is exactly the same as assigning to .name directly, except that we truncate if the given name is longer than MAX_NAME_LENGTH.

Note that you can set a longer name directly into the .name member, but it will be truncated when serializing the record.

Declaration

void set_name_truncated(std::string name);

Parameters

  • name — Name to assign to the contact

Returns

member::set_promoted

This marks the user as having a pending promotion-to-admin in the group, waiting for the promotion message to be sent to them.

Declaration

void set_promoted() {

Parameters

This endpoint takes no inputs.

Returns

member::set_promotion_accepted

This marks the user as having accepted a promotion to admin in the group.

Declaration

void set_promotion_accepted() {

Parameters

This endpoint takes no inputs.

Returns

member::set_promotion_failed

This marks the user as being promoted to an admin, but that their promotion message failed to send (this is intended as a signal to other clients that the promotion should be reissued).

Declaration

void set_promotion_failed() {

Parameters

This endpoint takes no inputs.

Returns

member::set_promotion_sent

This marks the user as having a pending promotion-to-admin in the group, and that a promotion message has been sent to them.

Declaration

void set_promotion_sent() {

Parameters

This endpoint takes no inputs.

Returns

member::set_removed

Sets the "removed" flag for this user. This marks the user as pending removal from the group. The optional messages parameter can be specified as true if we want to remove any messages sent by the member upon a successful removal.

Declaration

void set_removed(bool messages = false) {

Parameters

  • messages: can be specified as true to indicate any messages sent by the member should also be removed upon a successful member removal.

Returns

member::supplement

Flag that is set to indicate to the group that this member was added with a supplemental key rotation so that other admins can trigger the same key rotation method if they send a new invitation to the same member.

Note that this should be cleared when a member accepts an invitation.

Declaration

bool supplement = false;

members::set_invite_accepted

This clears the "invited" and "supplement" flags for this user, thus indicating that the user has accepted an invitation and is now a regular member of the group.

Declaration

void set_invite_accepted() {

Parameters

This endpoint takes no inputs.

Returns