diff --git a/.husky/pre-commit b/.husky/pre-commit index 6755a382..5b536e47 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,5 +1,2 @@ #!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - -npm test -./dev/go/generate +. "$(dirname -- "$0")/_/husky.sh" \ No newline at end of file diff --git a/go/keystore_api/v1/keystore.pb.go b/go/keystore_api/v1/keystore.pb.go index 726d0be6..943bd8c2 100644 --- a/go/keystore_api/v1/keystore.pb.go +++ b/go/keystore_api/v1/keystore.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: keystore_api/v1/keystore.proto package v1 diff --git a/go/message_api/v1/authn.pb.go b/go/message_api/v1/authn.pb.go index f0a6b961..a3126aec 100644 --- a/go/message_api/v1/authn.pb.go +++ b/go/message_api/v1/authn.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_api/v1/authn.proto package v1 diff --git a/go/message_api/v1/message_api.pb.go b/go/message_api/v1/message_api.pb.go index 36474b5f..88c223d6 100644 --- a/go/message_api/v1/message_api.pb.go +++ b/go/message_api/v1/message_api.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_api/v1/message_api.proto package v1 diff --git a/go/message_api/v1/message_api_grpc.pb.go b/go/message_api/v1/message_api_grpc.pb.go index 4d783e66..554ccd12 100644 --- a/go/message_api/v1/message_api_grpc.pb.go +++ b/go/message_api/v1/message_api_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.2 +// - protoc v4.25.1 // source: message_api/v1/message_api.proto package v1 diff --git a/go/message_contents/ciphertext.pb.go b/go/message_contents/ciphertext.pb.go index 2c743272..528f109f 100644 --- a/go/message_contents/ciphertext.pb.go +++ b/go/message_contents/ciphertext.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_contents/ciphertext.proto package message_contents diff --git a/go/message_contents/composite.pb.go b/go/message_contents/composite.pb.go index ddaf39fc..3395357a 100644 --- a/go/message_contents/composite.pb.go +++ b/go/message_contents/composite.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_contents/composite.proto package message_contents diff --git a/go/message_contents/contact.pb.go b/go/message_contents/contact.pb.go index c31a32b2..49bf0b49 100644 --- a/go/message_contents/contact.pb.go +++ b/go/message_contents/contact.pb.go @@ -7,7 +7,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_contents/contact.proto package message_contents diff --git a/go/message_contents/content.pb.go b/go/message_contents/content.pb.go index 57cc948b..26fa2800 100644 --- a/go/message_contents/content.pb.go +++ b/go/message_contents/content.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_contents/content.proto package message_contents diff --git a/go/message_contents/conversation_reference.pb.go b/go/message_contents/conversation_reference.pb.go index 560eea2f..d933282d 100644 --- a/go/message_contents/conversation_reference.pb.go +++ b/go/message_contents/conversation_reference.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_contents/conversation_reference.proto package message_contents diff --git a/go/message_contents/invitation.pb.go b/go/message_contents/invitation.pb.go index f7a80d30..72ac731c 100644 --- a/go/message_contents/invitation.pb.go +++ b/go/message_contents/invitation.pb.go @@ -5,7 +5,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_contents/invitation.proto package message_contents diff --git a/go/message_contents/message.pb.go b/go/message_contents/message.pb.go index cedd0294..fc1b39ae 100644 --- a/go/message_contents/message.pb.go +++ b/go/message_contents/message.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_contents/message.proto package message_contents diff --git a/go/message_contents/private_key.pb.go b/go/message_contents/private_key.pb.go index 6f59def5..bb257bc7 100644 --- a/go/message_contents/private_key.pb.go +++ b/go/message_contents/private_key.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_contents/private_key.proto package message_contents diff --git a/go/message_contents/public_key.pb.go b/go/message_contents/public_key.pb.go index f04bb9a1..bfa0c886 100644 --- a/go/message_contents/public_key.pb.go +++ b/go/message_contents/public_key.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_contents/public_key.proto package message_contents diff --git a/go/message_contents/signature.pb.go b/go/message_contents/signature.pb.go index 19d7cb2e..e0cb1fb8 100644 --- a/go/message_contents/signature.pb.go +++ b/go/message_contents/signature.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: message_contents/signature.proto package message_contents diff --git a/go/mls/api/v1/mls.pb.go b/go/mls/api/v1/mls.pb.go index a57788ef..9ad438d7 100644 --- a/go/mls/api/v1/mls.pb.go +++ b/go/mls/api/v1/mls.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: mls/api/v1/mls.proto package v1 diff --git a/go/mls/api/v1/mls_grpc.pb.go b/go/mls/api/v1/mls_grpc.pb.go index 2ee9d616..ae6920a9 100644 --- a/go/mls/api/v1/mls_grpc.pb.go +++ b/go/mls/api/v1/mls_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.2 +// - protoc v4.25.1 // source: mls/api/v1/mls.proto package v1 diff --git a/go/mls_validation/v1/service.pb.go b/go/mls_validation/v1/service.pb.go index 5ff51120..913585fb 100644 --- a/go/mls_validation/v1/service.pb.go +++ b/go/mls_validation/v1/service.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc v4.25.1 // source: mls_validation/v1/service.proto package v1 diff --git a/go/mls_validation/v1/service_grpc.pb.go b/go/mls_validation/v1/service_grpc.pb.go index 2aca430b..69af37fd 100644 --- a/go/mls_validation/v1/service_grpc.pb.go +++ b/go/mls_validation/v1/service_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.2 +// - protoc v4.25.1 // source: mls_validation/v1/service.proto package v1 diff --git a/proto/buf.yaml b/proto/buf.yaml index fa54c672..8a7e9558 100644 --- a/proto/buf.yaml +++ b/proto/buf.yaml @@ -14,8 +14,12 @@ lint: - message_contents/content.proto RPC_REQUEST_RESPONSE_UNIQUE: - message_api/v1/message_api.proto + - identity/api/v1/identity.proto + - mls/api/v1/mls.proto RPC_RESPONSE_STANDARD_NAME: - message_api/v1/message_api.proto + - identity/api/v1/identity.proto + - mls/api/v1/mls.proto except: - PACKAGE_DIRECTORY_MATCH - PACKAGE_VERSION_SUFFIX diff --git a/proto/identity/api/v1/identity.proto b/proto/identity/api/v1/identity.proto new file mode 100644 index 00000000..ef4403ec --- /dev/null +++ b/proto/identity/api/v1/identity.proto @@ -0,0 +1,105 @@ +// Message API +syntax = "proto3"; +package xmtp.identity.api.v1; + +import "google/api/annotations.proto"; +import "identity/associations/association.proto"; +import "protoc-gen-openapiv2/options/annotations.proto"; + +option go_package = "github.com/xmtp/proto/v3/go/mls/api/v1"; +option java_package = "org.xmtp.proto.mls.api.v1"; +option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { + info: { + title: "IdentityApi"; + version: "1.0"; + }; +}; + +// RPCs for the new MLS API +service IdentityApi { + // Publishes an identity update for an XID or wallet. An identity update may + // consist of multiple identity actions that have been batch signed. + rpc PublishIdentityUpdate(PublishIdentityUpdateRequest) returns (PublishIdentityUpdateResponse) { + option (google.api.http) = { + post: "/identity/v1/publish-identity-update" + body: "*" + }; + } + + // Used to check for changes related to members of a group. + // Would return an array of any new installations associated with the wallet + // address, and any revocations that have happened. + rpc GetIdentityUpdates(GetIdentityUpdatesRequest) returns (GetIdentityUpdatesResponse) { + option (google.api.http) = { + post: "/identity/v1/get-identity-updates" + body: "*" + }; + } + + // Retrieve the XIDs for the given addresses + rpc GetInboxIds(GetInboxIdsRequest) returns (GetInboxIdsResponse) { + option (google.api.http) = { + post: "/identity/v1/get-inbox-ids" + body: "*" + }; + } +} + +// Publishes an identity update to the network +message PublishIdentityUpdateRequest { + xmtp.identity.associations.IdentityUpdate identity_update = 1; +} + +// The response when an identity update is published +message PublishIdentityUpdateResponse {} + +// Get all updates for an identity since the specified time +message GetIdentityUpdatesRequest { + // Points to the last entry the client has received. The sequence_id should be + // set to 0 if the client has not received anything. + message Request { + string inbox_id = 1; + uint64 sequence_id = 2; + } + + repeated Request requests = 1; +} + +// Returns all log entries for the requested identities +message GetIdentityUpdatesResponse { + // A single entry in the XID log on the server. + message IdentityUpdateLog { + uint64 sequence_id = 1; + uint64 server_timestamp_ns = 2; + xmtp.identity.associations.IdentityUpdate update = 3; + } + + // The update log for a single identity, starting after the last cursor + message Response { + string inbox_id = 1; + repeated IdentityUpdateLog updates = 2; + } + + repeated Response responses = 1; +} + +// Request to retrieve the XIDs for the given addresses +message GetInboxIdsRequest { + // A single request for a given address + message Request { + string address = 1; + } + + repeated Request requests = 1; +} + +// Response with the XIDs for the requested addresses +message GetInboxIdsResponse { + // A single response for a given address + message Response { + string address = 1; + optional string inbox_id = 2; + } + + repeated Response responses = 1; +} diff --git a/proto/identity/associations/association.proto b/proto/identity/associations/association.proto new file mode 100644 index 00000000..12becb26 --- /dev/null +++ b/proto/identity/associations/association.proto @@ -0,0 +1,74 @@ +// Payloads to be signed for identity associations +syntax = "proto3"; + +package xmtp.identity.associations; + +import "identity/associations/signature.proto"; + +option go_package = "github.com/xmtp/proto/v3/go/identity/associations"; +option java_package = "org.xmtp.proto.identity.associations"; + +// The identifier for a member of an XID +message MemberIdentifier { + oneof kind { + string address = 1; + bytes installation_public_key = 2; + } +} + +// The first entry of any XID log. The XID must be deterministically derivable +// from the address and nonce. +// The recovery address defaults to the initial associated_address unless +// there is a subsequent ChangeRecoveryAddress in the log. +message CreateInbox { + string initial_address = 1; + uint64 nonce = 2; + Signature initial_address_signature = 3; // Must be an addressable member +} + +// Adds a new member for an XID - either an addressable member such as a +// wallet, or an installation acting on behalf of an address. +// A key-pair that has been associated with one role MUST not be permitted to be +// associated with a different role. +message AddAssociation { + MemberIdentifier new_member_identifier = 1; + Signature existing_member_signature = 2; + Signature new_member_signature = 3; +} + +// Revokes a member from an XID. The recovery address must sign the revocation. +message RevokeAssociation { + MemberIdentifier member_to_revoke = 1; + Signature recovery_address_signature = 2; +} + +// Changes the recovery address for an XID. The recovery address is not required +// to be a member of the XID. In addition to being able to add members, the +// recovery address can also revoke members. +message ChangeRecoveryAddress { + string new_recovery_address = 1; + Signature existing_recovery_address_signature = 2; +} + +// A single identity operation +message IdentityAction { + oneof kind { + CreateInbox create_inbox = 1; + AddAssociation add = 2; + RevokeAssociation revoke = 3; + ChangeRecoveryAddress change_recovery_address = 4; + } +} + +// One or more identity actions that were signed together. +// Example: [CreateXid, AddAssociation, ChangeRecoveryAddress] +// 1. The batched signature text is created by concatenating the signature text +// of each association together with a separator, '\n\n\n'. +// 2. The user signs this concatenated result. +// 3. The resulting signature is added to each association proto where relevant. +// The same signature may be used for multiple associations in the array. +message IdentityUpdate { + repeated IdentityAction actions = 1; + uint64 client_timestamp_ns = 2; + string inbox_id = 3; +} diff --git a/proto/identity/associations/signature.proto b/proto/identity/associations/signature.proto new file mode 100644 index 00000000..76a0a8a7 --- /dev/null +++ b/proto/identity/associations/signature.proto @@ -0,0 +1,57 @@ +// Signing methods for identity associations +syntax = "proto3"; + +package xmtp.identity.associations; + +import "message_contents/public_key.proto"; + +option go_package = "github.com/xmtp/proto/v3/go/identity/associations"; +option java_package = "org.xmtp.proto.identity.associations"; + +// RecoverableEcdsaSignature for EIP-191 and V2 signatures +message RecoverableEcdsaSignature { + // 65-bytes [ R || S || V ], with recovery id as the last byte + bytes bytes = 1; +} + +// EdDSA signature for 25519 +message RecoverableEd25519Signature { + bytes bytes = 1; +} + +// Smart wallet signature +message Erc1271Signature { + // CAIP-10 contract address + // https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md + string contract_address = 1; + // Specify the block height to verify the signature against + int64 block_height = 2; + // The actual signature bytes + bytes signature = 3; +} + +// An existing address on xmtpv2 may have already signed a legacy identity key +// of type SignedPublicKey via the 'Create Identity' signature. +// For migration to xmtpv3, the legacy key is permitted to sign on behalf of the +// address to create a matching xmtpv3 installation key. +// This signature type can ONLY be used for CreateXid and AddAssociation +// payloads, and can only be used once in xmtpv3. +message LegacyDelegatedSignature { + xmtp.message_contents.SignedPublicKey delegated_key = 1; + RecoverableEcdsaSignature signature = 2; +} + +// A wrapper for all possible signature types +message Signature { + // Must have two properties: + // 1. An identifier (address or public key) for the signer must either be + // recoverable, or specified as a field. + // 2. The signer certifies that the signing payload is correct. The payload + // must be inferred from the context in which the signature is provided. + oneof signature { + RecoverableEcdsaSignature erc_191 = 1; + Erc1271Signature erc_1271 = 2; + RecoverableEd25519Signature installation_key = 3; + LegacyDelegatedSignature delegated_erc_191 = 4; + } +}