Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SCW Verification #211

Merged
merged 23 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion dev/kotlin/generate
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,6 @@ docker run --platform linux/x86_64 --rm -i -v${PWD}:/code xmtp/protoc-kotlin \
mls/message_contents/group_metadata.proto \
mls/message_contents/group_mutable_metadata.proto \
mls/message_contents/content.proto \
mls/message_contents/transcript_messages.proto
mls/message_contents/transcript_messages.proto \
mls/message_contents/credential.proto \
mls/message_contents/association.proto
2 changes: 2 additions & 0 deletions dev/ts/generate
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ docker run --rm -i -v${PWD}:/code xmtp/protoc \
message_contents/ecies.proto \
mls/api/v1/mls.proto \
mls/database/intents.proto \
mls/message_contents/association.proto \
mls/message_contents/content.proto \
mls/message_contents/credential.proto \
mls/message_contents/group_membership.proto \
mls/message_contents/group_metadata.proto \
mls/message_contents/group_mutable_metadata.proto \
Expand Down
27 changes: 27 additions & 0 deletions proto/identity/api/v1/identity.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package xmtp.identity.api.v1;

import "google/api/annotations.proto";
import "identity/associations/association.proto";
import "identity/associations/signature.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

option go_package = "github.com/xmtp/proto/v3/go/mls/api/v1";
Expand Down Expand Up @@ -43,6 +44,32 @@ service IdentityApi {
body: "*"
};
}

// Verify an unverified smart contract wallet signature
rpc VerifySmartContractWalletSignatures(VerifySmartContractWalletSignaturesRequest) returns (VerifySmartContractWalletSignaturesResponse) {
option (google.api.http) = {
post: "/identity/v1/verify-smart-contract-wallet-signatures"
body: "*"
};
}
}

message VerifySmartContractWalletSignaturesRequest {
repeated UnverifiedSmartContractWalletSignature signatures = 1;
}

message UnverifiedSmartContractWalletSignature {
xmtp.identity.associations.SmartContractWalletSignature scw_signature = 1;
// SHA256 hash of the signature payload
bytes hash = 5;
}

message VerifySmartContractWalletSignaturesResponse {
message ValidationResponse {
bool is_valid = 1;
}

repeated ValidationResponse responses = 1;
}

// Publishes an identity update to the network
Expand Down
2 changes: 0 additions & 2 deletions proto/identity/associations/signature.proto
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ message SmartContractWalletSignature {
uint64 block_number = 2;
// The actual signature bytes
bytes signature = 3;
// The RPC URL specifies a chain to verify the signature against
string chain_rpc_url = 4;
}

// An existing address on xmtpv2 may have already signed a legacy identity key
Expand Down
92 changes: 89 additions & 3 deletions proto/mls/api/v1/mls.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ package xmtp.mls.api.v1;

import "google/api/annotations.proto";
import "google/protobuf/empty.proto";
import "message_contents/signature.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: "MlsApi"
version: "1.0"
}
title: "MlsApi";
version: "1.0";
};
};

// RPCs for the new MLS API
Expand All @@ -34,6 +35,14 @@ service MlsApi {
};
}

// Register a new installation, which would be validated before storage
rpc RegisterInstallation(RegisterInstallationRequest) returns (RegisterInstallationResponse) {
option (google.api.http) = {
post: "/mls/v1/register-installation"
body: "*"
};
}

// Upload a new KeyPackage, which would be validated before storage
rpc UploadKeyPackage(UploadKeyPackageRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {
Expand All @@ -50,6 +59,25 @@ service MlsApi {
};
}

// Would delete all key packages associated with the installation and mark
// the installation as having been revoked
rpc RevokeInstallation(RevokeInstallationRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {
post: "/mls/v1/revoke-installation"
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: "/mls/v1/get-identity-updates"
body: "*"
};
}

// Query stored group messages
rpc QueryGroupMessages(QueryGroupMessagesRequest) returns (QueryGroupMessagesResponse) {
option (google.api.http) = {
Expand Down Expand Up @@ -162,6 +190,18 @@ message KeyPackageUpload {
bytes key_package_tls_serialized = 1;
}

// Register a new installation
message RegisterInstallationRequest {
// The Key Package contains all information needed to register an installation
KeyPackageUpload key_package = 1;
bool is_inbox_id_credential= 2;
}

// The response to a RegisterInstallationRequest
message RegisterInstallationResponse {
bytes installation_key = 1;
}

// Upload a new key packages
message UploadKeyPackageRequest {
// An individual key package upload request
Expand Down Expand Up @@ -190,6 +230,52 @@ message FetchKeyPackagesResponse {
repeated KeyPackage key_packages = 1;
}

// Revoke an installation
message RevokeInstallationRequest {
bytes installation_key = 1;
// All revocations must be validated with a wallet signature over the
// installation_id being revoked (and some sort of standard prologue)
xmtp.message_contents.Signature wallet_signature = 2;
}

// Get all updates for an identity since the specified time
message GetIdentityUpdatesRequest {
repeated string account_addresses = 1;
uint64 start_time_ns = 2;
}

// Used to get any new or revoked installations for a list of wallet addresses
message GetIdentityUpdatesResponse {
// A new installation key was seen for the first time by the nodes
message NewInstallationUpdate {
bytes installation_key = 1;
bytes credential_identity = 2;
}

// An installation was revoked
message RevokedInstallationUpdate {
bytes installation_key = 1;
}

// A wrapper for any update to the wallet
message Update {
uint64 timestamp_ns = 1;
oneof kind {
NewInstallationUpdate new_installation = 2;
RevokedInstallationUpdate revoked_installation = 3;
}
}

// A wrapper for the updates for a single wallet
message WalletUpdates {
repeated Update updates = 1;
}

// A list of updates (or empty objects if no changes) in the original order
// of the request
repeated WalletUpdates updates = 1;
}

// Sort direction for queries
enum SortDirection {
SORT_DIRECTION_UNSPECIFIED = 0;
Expand Down
54 changes: 54 additions & 0 deletions proto/mls/message_contents/association.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Associations and signatures
codabrink marked this conversation as resolved.
Show resolved Hide resolved
syntax = "proto3";

package xmtp.mls.message_contents;

import "message_contents/public_key.proto";

option go_package = "github.com/xmtp/proto/v3/go/mls/message_contents";
option java_package = "org.xmtp.proto.mls.message.contents";

// Allows for us to update the format of the association text without
// incrementing the entire proto
enum AssociationTextVersion {
ASSOCIATION_TEXT_VERSION_UNSPECIFIED = 0;
ASSOCIATION_TEXT_VERSION_1 = 1;
}

// Used for "Grant Messaging Access" associations
message GrantMessagingAccessAssociation {
AssociationTextVersion association_text_version = 1;
RecoverableEcdsaSignature signature = 2; // EIP-191 signature
string account_address = 3;
uint64 created_ns = 4;
}

// Used for "Revoke Messaging Access" associations
message RevokeMessagingAccessAssociation {
AssociationTextVersion association_text_version = 1;
RecoverableEcdsaSignature signature = 2; // EIP-191 signature
string account_address = 3;
uint64 created_ns = 4;
}

// LegacyCreateIdentityAssociation is used when a v3 installation key
// is signed by a v2 identity key, which in turn is signed via a
// 'CreateIdentity' wallet signature
message LegacyCreateIdentityAssociation {
// Signs SHA-256 hash of installation key
RecoverableEcdsaSignature signature = 1;
// created_ns is encoded inside serialized key, account_address is recoverable
// from the SignedPublicKey signature
xmtp.message_contents.SignedPublicKey signed_legacy_create_identity_key = 2;
}

// RecoverableEcdsaSignature
message RecoverableEcdsaSignature {
// 65-bytes [ R || S || V ], with recovery id as the last byte
bytes bytes = 1;
}

// EdDSA signature bytes matching RFC 8032
message EdDsaSignature {
bytes bytes = 1;
}
31 changes: 31 additions & 0 deletions proto/mls/message_contents/credential.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Credentials and revocations
codabrink marked this conversation as resolved.
Show resolved Hide resolved
syntax = "proto3";

package xmtp.mls.message_contents;

import "mls/message_contents/association.proto";

option go_package = "github.com/xmtp/proto/v3/go/mls/message_contents";
option java_package = "org.xmtp.proto.mls.message.contents";

// A credential that can be used in MLS leaf nodes
message MlsCredential {
bytes installation_public_key = 1;
oneof association {
GrantMessagingAccessAssociation messaging_access = 2;
LegacyCreateIdentityAssociation legacy_create_identity = 3;
}
}

// A declaration and proof that a credential is no longer valid
message CredentialRevocation {
oneof public_key {
// The 'installation_public_key' field of the MlsCredential proto
bytes installation_key = 1;
// The 'key_bytes' field of the legacy SignedPublicKey proto
bytes unsigned_legacy_create_identity_key = 2;
}
oneof association {
RevokeMessagingAccessAssociation messaging_access = 3;
}
}
70 changes: 69 additions & 1 deletion proto/mls_validation/v1/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
syntax = "proto3";
package xmtp.mls_validation.v1;

import "identity/api/v1/identity.proto";
import "identity/associations/association.proto";
import "identity/associations/signature.proto";
import "identity/credential.proto";

option go_package = "github.com/xmtp/proto/v3/go/mls_validation/v1";

// RPCs for the new MLS API
service ValidationApi {
// Validates and parses a batch of key packages and returns relevant details
rpc ValidateKeyPackages(ValidateKeyPackagesRequest) returns (ValidateKeyPackagesResponse) {}

// Validates and parses a group message and returns relevant details
rpc ValidateGroupMessages(ValidateGroupMessagesRequest) returns (ValidateGroupMessagesResponse) {}

Expand All @@ -17,7 +22,19 @@ service ValidationApi {

// Validates InboxID key packages and returns credential information for them, without checking
// whether an InboxId <> InstallationPublicKey pair is really valid.
rpc ValidateInboxIdKeyPackages(ValidateInboxIdKeyPackagesRequest) returns (ValidateInboxIdKeyPackagesResponse) {}
rpc ValidateInboxIdKeyPackages(ValidateKeyPackagesRequest) returns (ValidateInboxIdKeyPackagesResponse) {}

// Validate an InboxID Key Package
// need public key possibly
rpc ValidateInboxIds(ValidateInboxIdsRequest) returns (ValidateInboxIdsResponse) {}

// Verifies smart contracts
// This request is proxied from the node, so we'll reuse those messgaes.
rpc VerifySmartContractWalletSignatures(
xmtp.identity.api.v1.VerifySmartContractWalletSignaturesRequest
) returns (
xmtp.identity.api.v1.VerifySmartContractWalletSignaturesResponse
) {}
}

// Contains a batch of serialized Key Packages
Expand Down Expand Up @@ -45,6 +62,32 @@ message ValidateInboxIdKeyPackagesResponse {
repeated Response responses = 1;
}

// Contains a batch of serialized Key Packages
message ValidateKeyPackagesRequest {
// Wrapper for each key package
message KeyPackage {
bytes key_package_bytes_tls_serialized = 1;
bool is_inbox_id_credential = 2;
}

repeated KeyPackage key_packages = 1;
}

// Response to ValidateKeyPackagesRequest
message ValidateKeyPackagesResponse {
// An individual response to one key package
message ValidationResponse {
bool is_ok = 1;
string error_message = 2;
bytes installation_id = 3;
string account_address = 4;
bytes credential_identity_bytes = 5;
uint64 expiration = 6;
}

repeated ValidationResponse responses = 1;
}

// Contains a batch of serialized Group Messages
message ValidateGroupMessagesRequest {
// Wrapper for each message
Expand Down Expand Up @@ -80,3 +123,28 @@ message GetAssociationStateResponse {
xmtp.identity.associations.AssociationState association_state = 1;
xmtp.identity.associations.AssociationStateDiff state_diff = 2;
}

// Request to validate an InboxID with the backend service. Ensures an Inbox Id <> Installation key are valid.
message ValidateInboxIdsRequest {
// a single validation request
message ValidationRequest {
xmtp.identity.MlsCredential credential = 1;
bytes installation_public_key = 2;
repeated xmtp.identity.associations.IdentityUpdate identity_updates = 3;
}

// list of validation requests
repeated ValidationRequest requests = 1;
}

// Response to ValidateInboxIdRequest
message ValidateInboxIdsResponse {
// a single validation response
message ValidationResponse {
bool is_ok = 1;
string error_message = 2;
string inbox_id = 3;
}
// List of validation responses
repeated ValidationResponse responses = 1;
}
Loading
Loading