diff --git a/bindings_ffi/src/mls.rs b/bindings_ffi/src/mls.rs index 8cd097362..6870a388c 100644 --- a/bindings_ffi/src/mls.rs +++ b/bindings_ffi/src/mls.rs @@ -2552,6 +2552,9 @@ mod tests { let bo_group = bo.group(alix_group.id()).unwrap(); bo_group.send("bo1".as_bytes().to_vec()).await.unwrap(); + // Temporary workaround for OpenMLS issue - make sure Alix's epoch is up-to-date + // https://github.com/xmtp/libxmtp/issues/1116 + alix_group.sync().await.unwrap(); alix_group.send("alix1".as_bytes().to_vec()).await.unwrap(); // Move the group forward by 3 epochs (as Alix's max_past_epochs is @@ -2755,6 +2758,9 @@ mod tests { log::info!("Caro sending fifth message"); // Caro sends a message in the group caro_group.update_installations().await.unwrap(); + // Temporary workaround for OpenMLS issue - make sure Caro's epoch is up-to-date + // https://github.com/xmtp/libxmtp/issues/1116 + caro_group.sync().await.unwrap(); caro_group .send("Fifth message".as_bytes().to_vec()) .await diff --git a/xmtp_id/src/associations/mod.rs b/xmtp_id/src/associations/mod.rs index 022a948bf..287e447e5 100644 --- a/xmtp_id/src/associations/mod.rs +++ b/xmtp_id/src/associations/mod.rs @@ -18,7 +18,7 @@ pub use self::serialization::{map_vec, try_map_vec, DeserializationError}; pub use self::signature::*; pub use self::state::{AssociationState, AssociationStateDiff}; -// Apply a single IdentityUpdate to an existing AssociationState +/// Apply a single [`IdentityUpdate`] to an existing [`AssociationState`] and return a new [`AssociationState`] pub fn apply_update( initial_state: AssociationState, update: IdentityUpdate, @@ -26,7 +26,7 @@ pub fn apply_update( update.update_state(Some(initial_state), update.client_timestamp_ns) } -// Get the current state from an array of `IdentityUpdate`s. Entire operation fails if any operation fails +/// Get the current state from an array of `IdentityUpdate`s. Entire operation fails if any operation fails pub fn get_state>( updates: Updates, ) -> Result { diff --git a/xmtp_id/src/associations/verified_signature.rs b/xmtp_id/src/associations/verified_signature.rs index 94b933889..023055d86 100644 --- a/xmtp_id/src/associations/verified_signature.rs +++ b/xmtp_id/src/associations/verified_signature.rs @@ -49,6 +49,10 @@ impl VerifiedSignature { )) } + /** + * Verifies an ECDSA signature against the provided signature text and ensures that the recovered + * address matches the expected address. + */ pub fn from_recoverable_ecdsa_with_expected_address>( signature_text: Text, signature_bytes: &[u8], @@ -95,6 +99,8 @@ impl VerifiedSignature { )) } + /// Verifies a legacy delegated signature and recovers the wallet address responsible + /// associated with the signer. pub fn from_legacy_delegated>( signature_text: Text, signature_bytes: &[u8], @@ -120,6 +126,7 @@ impl VerifiedSignature { )) } + /// Verifies a smart contract wallet signature using the provided signature verifier. pub async fn from_smart_contract_wallet>( signature_text: Text, signature_verifier: &dyn SmartContractSignatureVerifier, diff --git a/xmtp_mls/IDENTITY.md b/xmtp_mls/IDENTITY.md deleted file mode 100644 index 12dd180f5..000000000 --- a/xmtp_mls/IDENTITY.md +++ /dev/null @@ -1,176 +0,0 @@ -# XMTP Identity Structure - -In XMTP v3, a messaging account is represented by an Ethereum wallet address. An account consists of multiple app installations that may send and receive messages on behalf of it. Each installation is a separate cryptographic identity with its own set of keys. - -``` -Amal's account (Ethereum wallet address) -│ -├── Converse app (mobile phone) -│ └── Installation key bundle 1 -│ -├── Coinbase Wallet app (mobile phone) -│ └── Installation key bundle 2 -│ -├── Lenster app (tablet) -│ └── Installation key bundle 3 -│ -└── Coinbase Wallet app (tablet) - └── Installation key bundle 4 -``` - -Using per-installation keys provides the following benefits: - -- Installation private keys are never shared across devices or published onto the network. -- The user may enumerate the installations that have messaging access to their account. -- The user may revoke keys on a per-installation level. - -## Identity lifecycle - -### Ethereum wallet - -As of Nov 30 2023, an Ethereum wallet consists of a secp256k1 keypair, and is identified by a public address, which is the hex-encoding of the last 20 bytes of the Keccak-256 hash of the public key, prepended by `0x`. Wallet keys do not expire and are not rotatable - in the event of a compromise, the user must create a new wallet. The user is expected to have a pre-existing Ethereum wallet prior to onboarding with XMTP. - -The wallet keys can be used to sign arbitrary text, with most wallet software requiring explicit [user acceptance](https://docs.metamask.io/wallet/how-to/sign-data/#use-personal_sign) of the signature text. The signature text is formatted according to version `0x45` of [EIP-191](https://eips.ethereum.org/EIPS/eip-191), and is signed via a recoverable ECDSA signature. - -Wallet signature requests originating from XMTP will additionally prepend context to the EIP-191 `message` field to prevent collisions between signatures in different contexts: - -``` -XMTP: