aboutsummaryrefslogtreecommitdiffhomepage
path: root/tde2e
diff options
context:
space:
mode:
authorlevlam <levlam@telegram.org>2025-05-07 18:54:50 +0300
committerlevlam <levlam@telegram.org>2025-05-07 18:54:50 +0300
commitc912b400cba9c5c602c45bb8384aed388852bf9c (patch)
tree0df9ae3e42fbc3d814f7c281392810b9193732ef /tde2e
parent059e4c631cd9bfcc190ba50d957be17503d2242c (diff)
Simplify return type in functions that can't return an error.
Diffstat (limited to 'tde2e')
-rw-r--r--tde2e/td/e2e/e2e_api.cpp100
1 files changed, 97 insertions, 3 deletions
diff --git a/tde2e/td/e2e/e2e_api.cpp b/tde2e/td/e2e/e2e_api.cpp
index 70bfd89b6..93a7e14c7 100644
--- a/tde2e/td/e2e/e2e_api.cpp
+++ b/tde2e/td/e2e/e2e_api.cpp
@@ -60,10 +60,12 @@ class KeyChain {
}
return td::Status::Error("Wrong new verbosity level specified");
}
+
td::Result<api::PrivateKeyId> generate_private_key() {
TRY_RESULT(mnemonic, Mnemonic::create_new({}));
return from_words(mnemonic.get_words_string());
}
+
td::Result<api::PrivateKeyId> generate_dummy_key() {
auto hash = to_hash("dummy key", "...");
return container_.try_build<Key>(hash, [&]() -> td::Result<PrivateKeyWithMnemonic> {
@@ -71,6 +73,7 @@ class KeyChain {
return PrivateKeyWithMnemonic::from_private_key(PrivateKey::from_slice(key).move_as_ok(), {});
});
}
+
td::Result<api::PrivateKeyId> generate_temporary_private_key() {
TRY_RESULT(private_key, PrivateKey::generate());
auto hash = to_hash("temporary private key", private_key.to_public_key().to_u256().as_slice());
@@ -158,6 +161,7 @@ class KeyChain {
auto hash = to_hash("raw secret", secret);
return container_.try_build<Key>(hash, [&]() -> td::Result<td::SecureString> { return td::SecureString(secret); });
}
+
td::Result<api::SecureBytes> to_words(api::PrivateKeyId private_key_id) {
TRY_RESULT(private_key, to_private_key_with_mnemonic(private_key_id));
api::SecureBytes res;
@@ -203,6 +207,7 @@ class KeyChain {
}
return res;
}
+
td::Result<api::EncryptedMessageForMany> re_encrypt_message_for_many(api::SymmetricKeyId decrypt_key,
const std::vector<api::SymmetricKeyId> &key_ids,
td::Slice encrypted_header,
@@ -250,10 +255,12 @@ class KeyChain {
return QRHandshakeBob::create(bob_user_id, private_key_ref.to_private_key());
});
}
+
td::Result<api::Bytes> handshake_bob_send_start(api::HandshakeId bob_handshake_id) {
TRY_RESULT(bob_handshake, to_handshake_bob_ref(bob_handshake_id));
return bob_handshake->generate_start();
}
+
td::Result<api::HandshakeId> handshake_create_for_alice(api::UserId alice_user_id,
api::PrivateKeyId alice_private_key_id,
api::UserId bob_user_id, td::Slice bob_public_key,
@@ -265,6 +272,7 @@ class KeyChain {
bob_public_key_internal, start.str());
});
}
+
td::Result<api::Bytes> handshake_alice_send_accept(api::HandshakeId alice_handshake_id) {
TRY_RESULT(alice_handshake, to_handshake_alice_ref(alice_handshake_id));
return alice_handshake->generate_accept().as_slice().str();
@@ -297,19 +305,22 @@ class KeyChain {
return api::Ok();
}
- td::Result<api::Bytes> handshake_get_start_id(td::Slice start) {
+ api::Bytes handshake_get_start_id(td::Slice start) {
auto hash = to_hash("handshake start id", start);
return hash.as_slice().str();
}
+
td::Result<api::LoginId> login_create_for_bob() {
auto bob_fake_id = 0;
auto bob_fake_pk = generate_dummy_key().move_as_ok();
return handshake_create_for_bob(bob_fake_id, bob_fake_pk);
}
+
td::Result<api::Bytes> login_bob_send_start(api::LoginId bob_login_id) {
TRY_RESULT(bob_handshake, to_handshake_bob_ref(bob_login_id));
return bob_handshake->generate_start();
}
+
td::Result<api::Bytes> login_create_for_alice(api::UserId alice_user_id, api::PrivateKeyId alice_private_key_id,
td::Slice start) {
auto bob_fake_id = 0;
@@ -339,12 +350,13 @@ class KeyChain {
api::Result<api::Ok> login_destroy(api::LoginId login_id) {
return handshake_destroy(login_id);
}
+
td::Result<api::Ok> login_destroy_all() {
return handshake_destroy({});
}
+
td::Result<api::StorageId> storage_create(api::PrivateKeyId key_id, td::Slice last_block) {
TRY_RESULT(private_key_ref, to_private_key_with_mnemonic(key_id));
-
TRY_RESULT(storage, EncryptedStorage::create(last_block, private_key_ref.to_private_key()));
return container_.emplace<EncryptedStorage>(std::move(storage));
}
@@ -366,26 +378,31 @@ class KeyChain {
TRY_RESULT(public_key_ref, to_public_key(key));
return storage_ref->update(KeyContactByPublicKey{public_key_ref.to_u256()}, std::move(signed_entry));
}
+
template <class T>
td::Result<api::SignedEntry<T>> storage_sign_entry(api::PrivateKeyId key, api::Entry<T> entry) {
TRY_RESULT(private_key_ref, to_private_key_with_mnemonic(key));
return EncryptedStorage::sign_entry(private_key_ref.to_private_key(), std::move(entry));
}
+
td::Result<std::optional<api::Contact>> storage_get_contact(api::StorageId storage_id, api::PublicKeyId key) {
TRY_RESULT(storage_ref, to_storage_ref(storage_id));
TRY_RESULT(public_key_ref, to_public_key(key));
return storage_ref->get(KeyContactByPublicKey{public_key_ref.to_u256()}, false);
}
+
td::Result<std::optional<api::Contact>> storage_get_contact_optimistic(api::StorageId storage_id,
api::PublicKeyId key) {
TRY_RESULT(storage_ref, to_storage_ref(storage_id));
TRY_RESULT(public_key_ref, to_public_key(key));
return storage_ref->get(KeyContactByPublicKey{public_key_ref.to_u256()}, true);
}
+
td::Result<std::int64_t> storage_blockchain_height(api::StorageId storage_id) {
TRY_RESULT(storage_ref, to_storage_ref(storage_id));
return storage_ref->get_height();
}
+
td::Result<api::StorageUpdates> storage_blockchain_apply_block(api::StorageId storage_id, td::Slice block) {
TRY_RESULT(storage_ref, to_storage_ref(storage_id));
TRY_RESULT(updates, storage_ref->apply_block(block));
@@ -395,12 +412,14 @@ class KeyChain {
});
return api::StorageUpdates{std::move(fixed_updates)};
}
+
td::Result<api::Ok> storage_blockchain_add_proof(api::StorageId storage_id, td::Slice proof,
td::Span<std::string> keys) {
TRY_RESULT(storage_ref, to_storage_ref(storage_id));
TRY_STATUS(storage_ref->add_proof(proof, keys));
return api::Ok();
}
+
td::Result<api::StorageBlockchainState> storage_get_blockchain_state(api::StorageId storage_id) {
TRY_RESULT(storage_ref, to_storage_ref(storage_id));
auto state = storage_ref->get_blockchain_state();
@@ -417,7 +436,8 @@ class KeyChain {
}
return std::make_shared<GroupState>(std::move(group_state));
}
- td::Result<api::CallState> to_call_state(const GroupState &group_state) {
+
+ api::CallState to_call_state(const GroupState &group_state) {
api::CallState call_state;
for (auto &participant : group_state.participants) {
auto public_key_id = from_public_key(participant.public_key.to_secure_string()).move_as_ok();
@@ -432,6 +452,7 @@ class KeyChain {
TRY_RESULT(group_state, to_group_state(initial_state));
return Call::create_zero_block(private_key_ref.to_private_key(), group_state);
}
+
tde2e_api::Result<std::string> call_create_self_add_block(api::PrivateKeyId private_key_id, td::Slice previous_block,
const tde2e_api::CallParticipant &self) {
TRY_RESULT(private_key_ref, to_private_key_with_mnemonic(private_key_id));
@@ -446,6 +467,7 @@ class KeyChain {
TRY_RESULT(call, Call::create(user_id, private_key_ref.to_private_key(), last_block));
return container_.emplace<Call>(std::move(call));
}
+
td::Result<api::Bytes> call_describe(api::CallId call_id) {
TRY_RESULT(call_ref, to_call_ref(call_id));
td::StringBuilder sb;
@@ -458,16 +480,19 @@ class KeyChain {
TRY_RESULT(group_state, to_group_state(new_state));
return call_ref->build_change_state(group_state);
}
+
td::Result<api::SecureBytes> call_export_shared_key(api::CallId call_id) {
TRY_RESULT(call_ref, to_call_ref(call_id));
TRY_RESULT(shared_key, call_ref->shared_key());
return shared_key.as_slice().str();
}
+
td::Result<api::Bytes> call_encrypt(api::CallId call_id, api::CallChannelId channel_id, td::Slice message,
size_t unencrypted_prefix_size) {
TRY_RESULT(call_ref, to_call_ref(call_id));
return call_ref->encrypt(channel_id, message, unencrypted_prefix_size);
}
+
td::Result<api::SecureBytes> call_decrypt(api::CallId call_id, api::UserId user_id, api::CallChannelId channel_id,
td::Slice message) {
TRY_RESULT(call_ref, to_call_ref(call_id));
@@ -478,6 +503,7 @@ class KeyChain {
TRY_RESULT(call_ref, to_call_ref(call_id));
return call_ref->get_height();
}
+
td::Result<api::CallState> call_apply_block(api::CallId call_id, td::Slice block) {
TRY_RESULT(call_ref, to_call_ref(call_id));
TRY_STATUS(call_ref->apply_block(block));
@@ -495,10 +521,12 @@ class KeyChain {
TRY_RESULT(call_ref, to_call_ref(call_id));
return call_ref->get_verification_state();
}
+
td::Result<api::CallVerificationState> call_receive_inbound_message(api::CallId call_id, td::Slice message) {
TRY_RESULT(call_ref, to_call_ref(call_id));
return call_ref->receive_inbound_message(message);
}
+
td::Result<std::vector<std::string>> call_pull_outbound_messages(api::CallId call_id) {
TRY_RESULT(call_ref, to_call_ref(call_id));
return call_ref->pull_outbound_messages();
@@ -508,6 +536,7 @@ class KeyChain {
TRY_RESULT(call_ref, to_call_ref(call_id));
return call_ref->get_verification_words();
}
+
td::Result<api::PublicKey> to_public_key_api(api::AnyKeyId key_id) const {
TRY_RESULT(public_key, to_public_key(key_id));
return public_key.to_secure_string().as_slice().str();
@@ -516,6 +545,7 @@ class KeyChain {
private:
using Key = std::variant<td::SecureString, PublicKey, PrivateKeyWithMnemonic>;
using Handshake = std::variant<QRHandshakeAlice, QRHandshakeBob>;
+
Container<TypeInfo<Key, false, true>, TypeInfo<Handshake, true, true>, TypeInfo<EncryptedStorage, true, false>,
TypeInfo<Call, true, true>>
container_;
@@ -553,54 +583,69 @@ class KeyChain {
TRY_RESULT(handshake, container_.get_unique<Handshake>(alice_handshake_id));
return convert<QRHandshakeAlice>(std::move(handshake));
}
+
td::Result<HandshakeBobRef> to_handshake_bob_ref(api::HandshakeId bob_handshake_id) {
TRY_RESULT(handshake, container_.get_unique<Handshake>(bob_handshake_id));
return convert<QRHandshakeBob>(std::move(handshake));
}
+
td::Result<StorageRef> to_storage_ref(api::StorageId storage_id) {
return container_.get_unique<EncryptedStorage>(storage_id);
}
+
td::Result<CallRef> to_call_ref(api::CallId call_id) {
return container_.get_unique<Call>(call_id);
}
};
} // namespace tde2e_core
+
namespace tde2e_api {
+
tde2e_core::KeyChain &get_default_keychain() {
static tde2e_core::KeyChain keychain;
return keychain;
}
+
td::Slice to_slice(std::string_view s) {
if (s.empty()) {
return td::Slice();
}
return td::Slice(s.data(), s.size());
}
+
Result<Ok> set_log_verbosity_level(int new_verbosity_level) {
return get_default_keychain().set_log_verbosity_level(new_verbosity_level);
}
+
Result<PrivateKeyId> key_generate_private_key() {
return get_default_keychain().generate_private_key();
}
+
Result<PrivateKeyId> key_generate_temporary_private_key() {
return get_default_keychain().generate_temporary_private_key();
}
+
Result<PrivateKeyId> key_derive_secret(PrivateKeyId key_id, Slice tag) {
return get_default_keychain().derive_secret(key_id, to_slice(tag));
}
+
Result<Bytes> key_to_encrypted_private_key(PrivateKeyId key_id, SymmetricKeyId secret_id) {
return get_default_keychain().to_encrypted_private_key(key_id, secret_id);
}
+
Result<PrivateKeyId> key_from_encrypted_private_key(Slice encrypted_key, SymmetricKeyId secret_id) {
return get_default_keychain().from_encrypted_private_key(to_slice(encrypted_key), secret_id);
}
+
Result<SymmetricKeyId> key_from_bytes(SecureSlice secret) {
return get_default_keychain().from_bytes(to_slice(secret));
}
+
Result<Bytes> key_to_encrypted_private_key_internal(PrivateKeyId key_id, SymmetricKeyId secret_id) {
return get_default_keychain().to_encrypted_private_key_internal(key_id, secret_id);
}
+
Result<PrivateKeyId> key_from_encrypted_private_key_internal(Slice encrypted_key, SymmetricKeyId secret_id) {
return get_default_keychain().from_encrypted_private_key_internal(to_slice(encrypted_key), secret_id);
}
@@ -620,16 +665,20 @@ Result<PublicKey> key_to_public_key(PrivateKeyId key_id) {
Result<SecureBytes> key_to_words(PrivateKeyId key_id) {
return get_default_keychain().to_words(key_id);
}
+
Result<PrivateKeyId> key_from_words(SecureSlice words) {
return get_default_keychain().from_words(to_slice(words));
}
+
Result<Int512> key_sign(PrivateKeyId key, Slice data) {
return get_default_keychain().sign(key, to_slice(data));
}
+
Result<Ok> key_destroy(AnyKeyId key_id) {
TRY_STATUS(get_default_keychain().destroy(key_id));
return Ok();
}
+
Result<Ok> key_destroy_all() {
TRY_STATUS(get_default_keychain().destroy({}));
return Ok();
@@ -639,16 +688,20 @@ Result<EncryptedMessageForMany> encrypt_message_for_many(const std::vector<Symme
SecureSlice message) {
return get_default_keychain().encrypt_message_for_many(std::move(key_ids), to_slice(message));
}
+
Result<SecureBytes> decrypt_message_for_many(SymmetricKeyId key_id, Slice encrypted_header, Slice encrypted_message) {
return get_default_keychain().decrypt_message_for_many(key_id, to_slice(encrypted_header),
to_slice(encrypted_message));
}
+
Result<Bytes> encrypt_message_for_one(SymmetricKeyId key_id, SecureSlice message) {
return get_default_keychain().encrypt_message_for_one(key_id, to_slice(message));
}
+
Result<SecureBytes> decrypt_message_for_one(SymmetricKeyId key_id, Slice encrypted_message) {
return get_default_keychain().decrypt_message_for_one(key_id, to_slice(encrypted_message));
}
+
Result<EncryptedMessageForMany> re_encrypt_message_for_many(SymmetricKeyId decrypt_key_id,
const std::vector<SymmetricKeyId> &encrypt_key_ids,
Slice encrypted_header, Slice encrypted_message) {
@@ -659,34 +712,43 @@ Result<EncryptedMessageForMany> re_encrypt_message_for_many(SymmetricKeyId decry
Result<HandshakeId> handshake_create_for_bob(UserId bob_user_id, PrivateKeyId bob_private_key_id) {
return get_default_keychain().handshake_create_for_bob(bob_user_id, bob_private_key_id);
}
+
Result<Bytes> handshake_bob_send_start(HandshakeId bob_handshake_id) {
return get_default_keychain().handshake_bob_send_start(bob_handshake_id);
}
+
Result<HandshakeId> handshake_create_for_alice(UserId alice_user_id, PrivateKeyId alice_private_key_id,
UserId bob_user_id, const PublicKey &bob_public_key, Slice start) {
return get_default_keychain().handshake_create_for_alice(alice_user_id, alice_private_key_id, bob_user_id,
to_slice(bob_public_key), to_slice(start));
}
+
Result<Bytes> handshake_alice_send_accept(HandshakeId alice_handshake_id) {
return get_default_keychain().handshake_alice_send_accept(alice_handshake_id);
}
+
Result<Bytes> handshake_bob_receive_accept_send_finish(HandshakeId bob_handshake_id, UserId alice_id,
const PublicKey &alice_public_key, Slice accept) {
return get_default_keychain().handshake_bob_receive_accept_send_finish(bob_handshake_id, alice_id,
to_slice(alice_public_key), to_slice(accept));
}
+
Result<Bytes> handshake_start_id(Slice start) {
return get_default_keychain().handshake_get_start_id(to_slice(start));
}
+
Result<Ok> handshake_alice_receive_finish(HandshakeId alice_handshake_id, Slice finish) {
return get_default_keychain().handshake_alice_receive_finish(alice_handshake_id, to_slice(finish));
}
+
Result<SymmetricKeyId> handshake_get_shared_key_id(HandshakeId handshake_id) {
return get_default_keychain().handshake_get_shared_key_id(handshake_id);
}
+
Result<Ok> handshake_destroy(HandshakeId handshake_id) {
return get_default_keychain().handshake_destroy(handshake_id);
}
+
Result<Ok> handshake_destroy_all() {
return get_default_keychain().handshake_destroy({});
}
@@ -694,19 +756,24 @@ Result<Ok> handshake_destroy_all() {
Result<LoginId> login_create_for_bob() {
return get_default_keychain().login_create_for_bob();
}
+
Result<Bytes> login_bob_send_start(LoginId bob_login_id) {
return get_default_keychain().login_bob_send_start(bob_login_id);
}
+
Result<Bytes> login_create_for_alice(UserId alice_user_id, PrivateKeyId alice_private_key_id, Slice start) {
return get_default_keychain().login_create_for_alice(alice_user_id, alice_private_key_id, to_slice(start));
}
+
Result<PrivateKeyId> login_finish_for_bob(LoginId bob_login_id, UserId alice_user_id, const PublicKey &alice_public_key,
Slice data) {
return get_default_keychain().login_finish_for_bob(bob_login_id, alice_user_id, alice_public_key, to_slice(data));
}
+
Result<Ok> login_destroy(LoginId login_id) {
return get_default_keychain().login_destroy(login_id);
}
+
Result<Ok> login_destroy_all() {
return get_default_keychain().login_destroy_all();
}
@@ -714,35 +781,45 @@ Result<Ok> login_destroy_all() {
Result<StorageId> storage_create(PrivateKeyId key_id, Slice last_block) {
return get_default_keychain().storage_create(key_id, to_slice(last_block));
}
+
Result<Ok> storage_destroy(StorageId storage_id) {
return get_default_keychain().storage_destroy(storage_id);
}
+
Result<Ok> storage_destroy_all() {
return get_default_keychain().storage_destroy({});
}
+
template <class T>
Result<UpdateId> storage_update_contact(StorageId storage_id, PublicKeyId key, SignedEntry<T> signed_entry) {
return get_default_keychain().storage_update_contact(storage_id, key, std::move(signed_entry));
}
+
template <class T>
Result<SignedEntry<T>> storage_sign_entry(PrivateKeyId key, Entry<T> entry) {
return get_default_keychain().storage_sign_entry(key, std::move(entry));
}
+
Result<std::optional<Contact>> storage_get_contact(StorageId storage_id, PublicKeyId key) {
return get_default_keychain().storage_get_contact(storage_id, key);
}
+
Result<std::optional<Contact>> storage_get_contact_optimistic(StorageId storage_id, PublicKeyId key) {
return get_default_keychain().storage_get_contact_optimistic(storage_id, key);
}
+
Result<std::int64_t> storage_blockchain_height(StorageId storage_id) {
return get_default_keychain().storage_blockchain_height(storage_id);
}
+
Result<StorageUpdates> storage_blockchain_apply_block(StorageId storage_id, Slice block) {
return get_default_keychain().storage_blockchain_apply_block(storage_id, to_slice(block));
}
+
Result<Ok> storage_blockchain_add_proof(StorageId storage_id, Slice proof, const std::vector<std::string> &keys) {
return get_default_keychain().storage_blockchain_add_proof(storage_id, to_slice(proof), keys);
}
+
Result<StorageBlockchainState> storage_get_blockchain_state(StorageId storage_id) {
return get_default_keychain().storage_get_blockchain_state(storage_id);
}
@@ -750,16 +827,20 @@ Result<StorageBlockchainState> storage_get_blockchain_state(StorageId storage_id
Result<Bytes> call_create_zero_block(PrivateKeyId private_key_id, const CallState &initial_state) {
return get_default_keychain().call_create_zero_block(private_key_id, initial_state);
}
+
Result<Bytes> call_create_self_add_block(PrivateKeyId private_key_id, Slice previous_block,
const CallParticipant &self) {
return get_default_keychain().call_create_self_add_block(private_key_id, to_slice(previous_block), self);
}
+
Result<CallId> call_create(UserId user_id, PrivateKeyId private_key_id, Slice last_block) {
return get_default_keychain().call_create(user_id, private_key_id, to_slice(last_block));
}
+
Result<std::string> call_describe(CallId call_id) {
return get_default_keychain().call_describe(call_id);
}
+
Result<std::string> call_describe_block(Slice block_slice) {
bool is_server = tde2e_core::Blockchain::is_from_server(to_slice(block_slice));
TRY_RESULT(block_str, tde2e_core::Blockchain::from_any_to_local(std::string(block_slice)));
@@ -773,6 +854,7 @@ Result<std::string> call_describe_block(Slice block_slice) {
TRY_STATUS(parser.get_status());
return PSTRING() << (is_server ? "Server:" : "Local:") << to_string(block);
}
+
Result<std::string> call_describe_message(Slice broadcast_slice) {
bool is_server = tde2e_core::Blockchain::is_from_server(to_slice(broadcast_slice));
TRY_RESULT(broadcast_str, tde2e_core::Blockchain::from_any_to_local(std::string(broadcast_slice)));
@@ -783,34 +865,44 @@ Result<std::string> call_describe_message(Slice broadcast_slice) {
TRY_STATUS(parser.get_status());
return PSTRING() << (is_server ? "Server:" : "Local:") << to_string(broadcast);
}
+
Result<Bytes> call_create_change_state_block(CallId call_id, const CallState &new_state) {
return get_default_keychain().call_create_change_state_block(call_id, new_state);
}
+
Result<SecureBytes> call_export_shared_key(CallId call_id) {
return get_default_keychain().call_export_shared_key(call_id);
}
+
Result<Bytes> call_encrypt(CallId call_id, CallChannelId channel_id, SecureSlice message,
size_t unencrypted_prefix_size) {
return get_default_keychain().call_encrypt(call_id, channel_id, to_slice(message), unencrypted_prefix_size);
}
+
Result<SecureBytes> call_decrypt(CallId call_id, UserId user_id, CallChannelId channel_id, Slice message) {
return get_default_keychain().call_decrypt(call_id, user_id, channel_id, to_slice(message));
}
+
Result<int> call_get_height(CallId call_id) {
return get_default_keychain().call_get_height(call_id);
}
+
Result<CallState> call_apply_block(CallId call_id, Slice block) {
return get_default_keychain().call_apply_block(call_id, to_slice(block));
}
+
Result<CallState> call_get_state(CallId call_id) {
return get_default_keychain().call_get_state(call_id);
}
+
Result<CallVerificationState> call_get_verification_state(CallId call_id) {
return get_default_keychain().call_get_verification_state(call_id);
}
+
Result<CallVerificationState> call_receive_inbound_message(CallId call_id, Slice message) {
return get_default_keychain().call_receive_inbound_message(call_id, to_slice(message));
}
+
Result<std::vector<Bytes>> call_pull_outbound_messages(CallId call_id) {
return get_default_keychain().call_pull_outbound_messages(call_id);
}
@@ -818,9 +910,11 @@ Result<std::vector<Bytes>> call_pull_outbound_messages(CallId call_id) {
Result<CallVerificationWords> call_get_verification_words(CallId call_id) {
return get_default_keychain().call_get_verification_words(call_id);
}
+
Result<Ok> call_destroy(CallId call_id) {
return get_default_keychain().call_destroy(call_id);
}
+
Result<Ok> call_destroy_all() {
return get_default_keychain().call_destroy({});
}