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

Payer API Refactor #223

Merged
merged 5 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
64 changes: 64 additions & 0 deletions proto/xmtpv4/envelopes/envelopes.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Message API for XMTP V4
syntax = "proto3";

package xmtp.xmtpv4.envelopes;

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

option go_package = "github.com/xmtp/proto/v3/go/xmtpv4/envelopes";

// The last seen entry per originator. Originators that have not been seen are omitted.
// Entries MUST be sorted in ascending order, so that smaller node ID's appear first.
message VectorClock {
map<uint32, uint64> node_id_to_sequence_id = 1;
}

// Data visible to the server that has been authenticated by the client.
message AuthenticatedData {
uint32 target_originator = 1;
bytes target_topic = 2;
VectorClock last_seen = 3;
}

message ClientEnvelope {
AuthenticatedData aad = 1;

oneof payload {
xmtp.mls.api.v1.GroupMessageInput group_message = 2;
xmtp.mls.api.v1.WelcomeMessageInput welcome_message = 3;
xmtp.mls.api.v1.UploadKeyPackageRequest upload_key_package = 4;
xmtp.identity.associations.IdentityUpdate identity_update = 5;
}
}

// Wraps client envelope with payer signature
message PayerEnvelope {
bytes unsigned_client_envelope = 1; // Protobuf serialized
xmtp.identity.associations.RecoverableEcdsaSignature payer_signature = 2;
}

// For blockchain envelopes, the originator_sid is set by the smart contract,
// but the originator_ns is set by the publishing node
message UnsignedOriginatorEnvelope {
uint32 originator_node_id = 1;
uint64 originator_sequence_id = 2;
int64 originator_ns = 3;
PayerEnvelope payer_envelope = 4;
}

// An alternative to a signature for blockchain payloads
message BlockchainProof {
uint64 block_number = 1;
uint32 publisher_node_id = 2;
}

// Signed originator envelope
message OriginatorEnvelope {
bytes unsigned_originator_envelope = 1; // Protobuf serialized
oneof proof {
xmtp.identity.associations.RecoverableEcdsaSignature originator_signature = 2;
BlockchainProof blockchain_proof = 3;
}
}
81 changes: 12 additions & 69 deletions proto/xmtpv4/message_api/message_api.proto
Original file line number Diff line number Diff line change
@@ -1,70 +1,13 @@
// Message API for XMTP V4
syntax = "proto3";

package xmtp.xmtpv4;
package xmtp.xmtpv4.message_api;

import "google/api/annotations.proto";
import "identity/associations/association.proto";
import "identity/associations/signature.proto";
import "mls/api/v1/mls.proto";
import "xmtpv4/envelopes/envelopes.proto";

option go_package = "github.com/xmtp/proto/v3/go/xmtpv4/message_api";

// The last seen entry per originator. Originators that have not been seen are omitted.
// Entries MUST be sorted in ascending order, so that smaller node ID's appear first.
message VectorClock {
map<uint32, uint64> node_id_to_sequence_id = 1;
}

// Data visible to the server that has been authenticated by the client.
message AuthenticatedData {
uint32 target_originator = 1;
bytes target_topic = 2;
VectorClock last_seen = 3;
}

message ClientEnvelope {
oneof payload {
xmtp.mls.api.v1.GroupMessageInput group_message = 1;
xmtp.mls.api.v1.WelcomeMessageInput welcome_message = 2;
xmtp.mls.api.v1.RegisterInstallationRequest register_installation = 3;
xmtp.mls.api.v1.UploadKeyPackageRequest upload_key_package = 4;
xmtp.mls.api.v1.RevokeInstallationRequest revoke_installation = 5;
xmtp.identity.associations.IdentityUpdate identity_update = 7;
}
AuthenticatedData aad = 6;
}

// Wraps client envelope with payer signature
message PayerEnvelope {
bytes unsigned_client_envelope = 1; // Protobuf serialized
xmtp.identity.associations.RecoverableEcdsaSignature payer_signature = 2;
}

// For blockchain envelopes, the originator_sid is set by the smart contract,
// but the originator_ns is set by the publishing node
message UnsignedOriginatorEnvelope {
uint32 originator_node_id = 1;
uint64 originator_sequence_id = 2;
int64 originator_ns = 3;
PayerEnvelope payer_envelope = 4;
}

// An alternative to a signature for blockchain payloads
message BlockchainProof {
uint64 block_number = 1;
uint32 publisher_node_id = 2;
}

// Signed originator envelope
message OriginatorEnvelope {
bytes unsigned_originator_envelope = 1; // Protobuf serialized
oneof proof {
xmtp.identity.associations.RecoverableEcdsaSignature originator_signature = 2;
BlockchainProof blockchain_proof = 3;
}
}

// Misbehavior types
enum Misbehavior {
MISBEHAVIOR_UNSPECIFIED = 0;
Expand All @@ -77,7 +20,7 @@ enum Misbehavior {
// Reports node misbehavior, submittable by nodes or by clients
message MisbehaviorReport {
Misbehavior type = 1;
repeated OriginatorEnvelope envelopes = 2;
repeated xmtp.xmtpv4.envelopes.OriginatorEnvelope envelopes = 2;
}

// Query for envelopes, shared by query and subscribe endpoints
Expand All @@ -87,7 +30,7 @@ message EnvelopesQuery {
repeated bytes topics = 1;
// Node queries
repeated uint32 originator_node_ids = 2;
VectorClock last_seen = 3;
xmtp.xmtpv4.envelopes.VectorClock last_seen = 3;
}

// Batch subscribe to envelopes
Expand All @@ -97,7 +40,7 @@ message SubscribeEnvelopesRequest {

// Streamed response for batch subscribe - can be multiple envelopes at once
message SubscribeEnvelopesResponse {
repeated OriginatorEnvelope envelopes = 1;
repeated xmtp.xmtpv4.envelopes.OriginatorEnvelope envelopes = 1;
}

// Query envelopes request
Expand All @@ -108,15 +51,15 @@ message QueryEnvelopesRequest {

// Query envelopes response
message QueryEnvelopesResponse {
repeated OriginatorEnvelope envelopes = 1;
repeated xmtp.xmtpv4.envelopes.OriginatorEnvelope envelopes = 1;
}

message PublishEnvelopesRequest {
repeated PayerEnvelope payer_envelopes = 1;
message PublishPaidEnvelopesRequest {
repeated xmtp.xmtpv4.envelopes.PayerEnvelope payer_envelopes = 1;
}

message PublishEnvelopesResponse {
repeated OriginatorEnvelope originator_envelopes = 1;
message PublishPaidEnvelopesResponse {
repeated xmtp.xmtpv4.envelopes.OriginatorEnvelope originator_envelopes = 1;
}

// Request to retrieve the XIDs for the given addresses
Expand Down Expand Up @@ -159,9 +102,9 @@ service ReplicationApi {
}

// Publish envelope
rpc PublishEnvelopes(PublishEnvelopesRequest) returns (PublishEnvelopesResponse) {
rpc PublishPaidEnvelopes(PublishPaidEnvelopesRequest) returns (PublishPaidEnvelopesResponse) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to have two APIs named PublishEnvelopes that expect different request/response types. That feels like a footgun.

This is the best name I could come up with.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if PublishPayerEnvelopes and PublishClientEnvelopes would be more consistent?

option (google.api.http) = {
post: "/mls/v2/publish-envelopes"
post: "/mls/v2/publish-paid-envelopes"
body: "*"
};
}
Expand Down
28 changes: 28 additions & 0 deletions proto/xmtpv4/payer_api/payer_api.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Payer API
syntax = "proto3";

package xmtp.xmtpv4.payer_api;

import "google/api/annotations.proto";
import "xmtpv4/envelopes/envelopes.proto";

option go_package = "github.com/xmtp/proto/v3/go/xmtpv4/payer_api";

message PublishUnpaidEnvelopesRequest {
repeated xmtp.xmtpv4.envelopes.ClientEnvelope envelopes = 1;
}

message PublishUnpaidEnvelopesResponse {
repeated xmtp.xmtpv4.envelopes.OriginatorEnvelope originator_envelopes = 1;
}

// A narrowly scoped API for publishing messages through a payer
service PayerApi {
// Publish envelope
rpc PublishUnpaidEnvelopes(PublishUnpaidEnvelopesRequest) returns (PublishUnpaidEnvelopesResponse) {
option (google.api.http) = {
post: "/mls/v2/payer/publish-envelopes"
neekolas marked this conversation as resolved.
Show resolved Hide resolved
body: "*"
};
}
}
Loading