Skip to content

Commit c2b9906

Browse files
codabrinkcameronvoellnplasterermchenani
authored
Migrate Identity (#1621)
* passkey member identifier * nit * incremental progress * move public identifiers into its own file * adapt association log * external identifier * enforce permissions via data structures * wip * wip * more cleanup * wip * cleanup * more cleanup * cleanup verified signature * cleanup id/mod.rs * cleanup serialization, update protos * more cleanup * more cleanup * continue making improvements * cleanup * checking in progress * continue cleanup * cleaner approach * more cleanup * cleanup * fix the query * cleanup * database adjustments * rename wallet entry to identity cache * consent record to root identifier * cleanup builder.rs * update consent * update consent save * update a few more methods * two errors left * xmtp_mls is done, now for the bindings * continue cleanup * work on the ffi more * Update the InboxOwner trait * rename to PublicIdentifier * wip * refactor ffi progress * mls cleanup * cleanup * update the cli example * continue cleanup * continue updating * finish with node/client.rs * update node consent state * consent state in node * more cleaning up * continue cleanup * fix typo * cleanup wasm client * cleanup * proto * fix a test * revert signature text * update migration * update migration * update migration one more time * fix * rework migration approach * schema gen * fix * checking in * turn off for now * default ident kind to Ethereum * update proto * update nomenclature * fix consent * test fix * test fix * cleanup * tweak udl * taplo * adjust ffi * update the udl * cleanup * sign * put the udl in the namespace * relying partner * ffi relying partner * node relying partner * wasm relying partner * udl * remove udl * java kts file * api fix * ignore faulty test * cleanup * cleanup * test fix * lint * test fix * lint * fix bench * prettier * lint * lint * fix bench * lint * lint * lint * cleanup * update kotlin gen script * todo done * re-add udl file to get android build working (#1678) Co-authored-by: cameronvoell <cameronvoell@users.noreply.github.com> * remove ffirootidentifier * remove wasm root identifier * remove node root identifier * lint * cleanup * fixes for the new tests * cleanup * use an env var * drop address from consent * lint * fix * lint * lint * legacy interop tests (#1694) * legacy interop tests * test group * cleanup * revert bindings_node * revert bindings_node * update comment * Update xmtp_mls/src/client.rs Co-authored-by: Mojtaba Chenani <chenani@outlook.com> * Update xmtp_mls/src/identity_updates.rs Co-authored-by: Mojtaba Chenani <chenani@outlook.com> * Update xmtp_mls/src/client.rs Co-authored-by: Cameron Voell <1103838+cameronvoell@users.noreply.github.com> * Update xmtp_mls/src/client.rs Co-authored-by: Cameron Voell <1103838+cameronvoell@users.noreply.github.com> * undo comment * update can_message * lint * fix node tests * ffi public identifier -> ffi identifier * cleanup * cleanup * just identifier * bump * lint * remove disappearing messages test from node * disable another test * more cleanup * flakiness --------- Co-authored-by: Cameron Voell <1103838+cameronvoell@users.noreply.github.com> Co-authored-by: cameronvoell <cameronvoell@users.noreply.github.com> Co-authored-by: Naomi Plasterer <naomi@xmtp.com> Co-authored-by: Mojtaba Chenani <chenani@outlook.com>
1 parent 8771b14 commit c2b9906

File tree

112 files changed

+5799
-3691
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+5799
-3691
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,6 @@ ecies_bindings_wasm/
167167
**/tracing-flamegraph.svg
168168

169169
chain_urls.json
170+
171+
# Mise Configs
172+
.mise.toml

Cargo.lock

+3-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindings_ffi/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ crate-type = ["lib", "cdylib", "staticlib"]
99

1010
[dependencies]
1111
futures.workspace = true
12+
hex.workspace = true
1213
parking_lot.workspace = true
1314
prost.workspace = true
1415
thiserror.workspace = true

bindings_ffi/benches/create_client.rs

+16-11
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ use xmtp_common::{
1010
bench::{bench_async_setup, BENCH_ROOT_SPAN},
1111
tmp_path,
1212
};
13-
use xmtp_id::InboxOwner;
13+
use xmtp_id::associations::test_utils::WalletTestExt;
1414
use xmtp_mls::utils::test::HISTORY_SYNC_URL;
15-
use xmtpv3::generate_inbox_id;
15+
use xmtpv3::identity::FfiIdentifier;
1616

1717
#[macro_use]
1818
extern crate tracing;
@@ -52,8 +52,9 @@ fn create_ffi_client(c: &mut Criterion) {
5252
|| {
5353
bench_async_setup(|| async {
5454
let wallet = xmtp_cryptography::utils::generate_local_wallet();
55+
let ident = wallet.identifier();
5556
let nonce = 1;
56-
let inbox_id = generate_inbox_id(wallet.get_address(), nonce).unwrap();
57+
let inbox_id = ident.inbox_id(nonce).unwrap();
5758
let path = tmp_path();
5859
let (url, is_secure) = network_url();
5960
let api = xmtpv3::mls::connect_to_backend(url, is_secure)
@@ -62,20 +63,21 @@ fn create_ffi_client(c: &mut Criterion) {
6263
(
6364
api,
6465
inbox_id,
65-
wallet.get_address(),
66+
wallet.identifier(),
6667
nonce,
6768
path,
6869
span.clone(),
6970
)
7071
})
7172
},
72-
|(api, inbox_id, address, nonce, path, span)| async move {
73+
|(api, inbox_id, ident, nonce, path, span)| async move {
74+
let ffi_ident: FfiIdentifier = ident.into();
7375
xmtpv3::mls::create_client(
7476
api,
7577
Some(path),
7678
Some(vec![0u8; 32]),
7779
&inbox_id,
78-
address,
80+
ffi_ident,
7981
nonce,
8082
None,
8183
Some(HISTORY_SYNC_URL.to_string()),
@@ -99,9 +101,11 @@ fn cached_create_ffi_client(c: &mut Criterion) {
99101
let _ = fdlimit::raise_fd_limit();
100102
let mut benchmark_group = c.benchmark_group("create_client_from_cached");
101103
let wallet = xmtp_cryptography::utils::generate_local_wallet();
104+
let ident = wallet.identifier();
102105
let nonce = 1;
103-
let inbox_id = generate_inbox_id(wallet.get_address(), nonce).unwrap();
104-
let address = wallet.get_address();
106+
let inbox_id = ident.inbox_id(nonce).unwrap();
107+
let ffi_ident: FfiIdentifier = ident.into();
108+
let address = wallet.identifier();
105109
let path = tmp_path();
106110
let (url, is_secure) = network_url();
107111
let api = runtime.block_on(async {
@@ -113,7 +117,7 @@ fn cached_create_ffi_client(c: &mut Criterion) {
113117
Some(path.clone()),
114118
Some(vec![0u8; 32]),
115119
&inbox_id.clone(),
116-
address.clone(),
120+
ffi_ident,
117121
nonce,
118122
None,
119123
Some(HISTORY_SYNC_URL.to_string()),
@@ -138,13 +142,14 @@ fn cached_create_ffi_client(c: &mut Criterion) {
138142
span.clone(),
139143
)
140144
},
141-
|(api, inbox_id, address, nonce, path, history_sync, span)| async move {
145+
|(api, inbox_id, ident, nonce, path, history_sync, span)| async move {
146+
let ffi_ident: FfiIdentifier = ident.into();
142147
xmtpv3::mls::create_client(
143148
api,
144149
Some(path),
145150
Some(vec![0u8; 32]),
146151
&inbox_id,
147-
address,
152+
ffi_ident,
148153
nonce,
149154
None,
150155
Some(history_sync),

bindings_ffi/build.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::process::Command;
22

33
fn main() {
4-
uniffi::generate_scaffolding("./src/xmtpv3.udl").expect("Building the UDL file failed");
54
Command::new("make")
65
.args(["libxmtp-version"])
76
.status()

bindings_ffi/gen_kotlin.sh

-1
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,3 @@ unzip -o LibXMTPKotlinFFI.zip
7171
cd ../../..
7272

7373
cp -r $BINDINGS_PATH/src/uniffi/$PROJECT_NAME/jniLibs/* ~/XMTP/xmtp-android/library/src/main/jniLibs
74-

bindings_ffi/src/identity.rs

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use std::fmt::Display;
2+
use xmtp_cryptography::signature::IdentifierValidationError;
3+
use xmtp_id::associations::{ident, Identifier};
4+
5+
use crate::GenericError;
6+
7+
#[derive(uniffi::Record, Hash, PartialEq, Eq, Clone)]
8+
pub struct FfiIdentifier {
9+
pub identifier: String,
10+
pub identifier_kind: FfiIdentifierKind,
11+
pub relying_partner: Option<String>,
12+
}
13+
14+
#[derive(uniffi::Enum, Hash, PartialEq, Eq, Clone)]
15+
pub enum FfiIdentifierKind {
16+
Ethereum,
17+
Passkey,
18+
}
19+
20+
impl FfiIdentifier {
21+
pub fn inbox_id(&self, nonce: u64) -> Result<String, GenericError> {
22+
let ident: Identifier = self.clone().try_into().map_err(GenericError::from_error)?;
23+
Ok(ident.inbox_id(nonce)?)
24+
}
25+
}
26+
27+
impl Display for FfiIdentifier {
28+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29+
match self.identifier_kind {
30+
FfiIdentifierKind::Ethereum => write!(f, "{}", self.identifier),
31+
FfiIdentifierKind::Passkey => write!(f, "{}", hex::encode(&self.identifier)),
32+
}
33+
}
34+
}
35+
36+
#[allow(unused)]
37+
#[uniffi::export]
38+
pub fn generate_inbox_id(
39+
account_identifier: FfiIdentifier,
40+
nonce: u64,
41+
) -> Result<String, GenericError> {
42+
account_identifier.inbox_id(nonce)
43+
}
44+
45+
impl From<Identifier> for FfiIdentifier {
46+
fn from(ident: Identifier) -> Self {
47+
match ident {
48+
Identifier::Ethereum(ident::Ethereum(addr)) => Self {
49+
identifier: addr,
50+
identifier_kind: FfiIdentifierKind::Ethereum,
51+
relying_partner: None,
52+
},
53+
Identifier::Passkey(ident::Passkey {
54+
key,
55+
relying_partner,
56+
}) => Self {
57+
identifier: hex::encode(key),
58+
identifier_kind: FfiIdentifierKind::Passkey,
59+
relying_partner,
60+
},
61+
}
62+
}
63+
}
64+
65+
impl TryFrom<FfiIdentifier> for Identifier {
66+
type Error = IdentifierValidationError;
67+
fn try_from(ident: FfiIdentifier) -> Result<Self, Self::Error> {
68+
let ident = match ident.identifier_kind {
69+
FfiIdentifierKind::Ethereum => Self::eth(ident.identifier)?,
70+
FfiIdentifierKind::Passkey => {
71+
Self::passkey_str(&ident.identifier, ident.relying_partner)?
72+
}
73+
};
74+
Ok(ident)
75+
}
76+
}
77+
78+
pub trait IdentityExt<T, U> {
79+
fn to_internal(self) -> Result<Vec<U>, IdentifierValidationError>;
80+
}
81+
82+
impl IdentityExt<FfiIdentifier, Identifier> for Vec<FfiIdentifier> {
83+
fn to_internal(self) -> Result<Vec<Identifier>, IdentifierValidationError> {
84+
let ident: Result<Vec<_>, IdentifierValidationError> =
85+
self.into_iter().map(|ident| ident.try_into()).collect();
86+
ident
87+
}
88+
}
89+
90+
pub trait FfiCollectionExt<T> {
91+
fn to_ffi(self) -> Vec<T>;
92+
}
93+
impl FfiCollectionExt<FfiIdentifier> for Vec<Identifier> {
94+
fn to_ffi(self) -> Vec<FfiIdentifier> {
95+
self.into_iter().map(Into::into).collect()
96+
}
97+
}
98+
pub trait FfiCollectionTryExt<T> {
99+
fn to_internal(self) -> Result<Vec<T>, IdentifierValidationError>;
100+
}
101+
impl FfiCollectionTryExt<Identifier> for Vec<FfiIdentifier> {
102+
fn to_internal(self) -> Result<Vec<Identifier>, IdentifierValidationError> {
103+
self.into_iter().map(|ident| ident.try_into()).collect()
104+
}
105+
}

bindings_ffi/src/inbox_owner.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,32 @@
1-
use xmtp_cryptography::signature::{RecoverableSignature, SignatureError};
1+
use crate::identity::FfiIdentifier;
2+
use xmtp_cryptography::signature::{
3+
IdentifierValidationError, RecoverableSignature, SignatureError,
4+
};
5+
use xmtp_id::associations::Identifier;
26

37
// TODO proper error handling
4-
#[derive(Debug, thiserror::Error)]
8+
#[derive(uniffi::Error, Debug, thiserror::Error)]
59
pub enum SigningError {
610
#[error("This is a generic error")]
711
Generic,
812
}
913

14+
#[derive(uniffi::Error, Debug, thiserror::Error)]
15+
pub enum IdentityValidationError {
16+
#[error("Error: {0:?}")]
17+
Generic(String),
18+
}
19+
1020
impl From<uniffi::UnexpectedUniFFICallbackError> for SigningError {
1121
fn from(_: uniffi::UnexpectedUniFFICallbackError) -> Self {
1222
Self::Generic
1323
}
1424
}
1525

1626
// A simplified InboxOwner passed to Rust across the FFI boundary
27+
#[uniffi::export(with_foreign)]
1728
pub trait FfiInboxOwner: Send + Sync {
18-
fn get_address(&self) -> String;
29+
fn get_identifier(&self) -> Result<FfiIdentifier, IdentityValidationError>;
1930
fn sign(&self, text: String) -> Result<Vec<u8>, SigningError>;
2031
}
2132

@@ -30,8 +41,12 @@ impl RustInboxOwner {
3041
}
3142

3243
impl xmtp_mls::InboxOwner for RustInboxOwner {
33-
fn get_address(&self) -> String {
34-
self.ffi_inbox_owner.get_address().to_lowercase()
44+
fn get_identifier(&self) -> Result<Identifier, IdentifierValidationError> {
45+
let ident = self
46+
.ffi_inbox_owner
47+
.get_identifier()
48+
.map_err(|err| IdentifierValidationError::Generic(err.to_string()))?;
49+
ident.try_into()
3550
}
3651

3752
fn sign(&self, text: &str) -> Result<RecoverableSignature, SignatureError> {

bindings_ffi/src/lib.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
11
#![recursion_limit = "256"]
22
#![warn(clippy::unwrap_used)]
3+
pub mod identity;
34
pub mod inbox_owner;
45
pub mod logger;
56
pub mod mls;
67

78
pub use crate::inbox_owner::SigningError;
8-
use inbox_owner::FfiInboxOwner;
99
pub use mls::*;
1010
use std::error::Error;
11+
use xmtp_cryptography::signature::IdentifierValidationError;
1112

1213
extern crate tracing as log;
1314

14-
pub use ffi::*;
15-
#[allow(clippy::all)]
16-
mod ffi {
17-
use super::*;
18-
uniffi::include_scaffolding!("xmtpv3");
19-
}
15+
uniffi::setup_scaffolding!("xmtpv3");
2016

2117
#[derive(uniffi::Error, thiserror::Error, Debug)]
2218
#[uniffi(flat_error)]
@@ -63,6 +59,8 @@ pub enum GenericError {
6359
ApiClientBuild(#[from] xmtp_api_grpc::GrpcBuilderError),
6460
#[error(transparent)]
6561
Grpc(#[from] xmtp_api_grpc::GrpcError),
62+
#[error(transparent)]
63+
AddressValidation(#[from] IdentifierValidationError),
6664
}
6765

6866
#[derive(uniffi::Error, thiserror::Error, Debug)]

0 commit comments

Comments
 (0)