From 9dac9eb6e42b5b172c59ea27e5f23d65103053a6 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Wed, 23 Oct 2024 12:25:07 -0700 Subject: [PATCH 1/4] Wait for logs in blockchain publisher (#249) ## tl;dr - Gets the full logs of the transaction when submitting to the blockchain, so we can construct a valid `OriginatorEnvelope` that includes the `sequence_id` ## Notes Once this is in I will update https://github.com/xmtp/xmtpd/pull/248 to take advantage of it ## Summary by CodeRabbit ## Release Notes - **New Features** - Enhanced blockchain message publishing with improved error handling and structured responses. - Introduced new methods for parsing transaction receipts related to message sending and identity updates. - Added a utility function to create a cancelled context for testing purposes. - **Bug Fixes** - Refined error handling in blockchain publishing methods to provide clearer error messages and logging. - **Tests** - Added unit tests for `BlockchainPublisher` methods to ensure expected functionality and error handling. - **Documentation** - Updated method signatures to reflect new return types for blockchain publishing operations. --- pkg/api/payer/service.go | 26 ++-- pkg/blockchain/blockchainPublisher.go | 60 +++++++- pkg/blockchain/blockchainPublisher_test.go | 142 ++++++++++++++++++ pkg/blockchain/client.go | 20 ++- pkg/blockchain/interface.go | 9 +- .../blockchain/mock_IBlockchainPublisher.go | 32 ++-- pkg/testutils/context.go | 9 ++ 7 files changed, 258 insertions(+), 40 deletions(-) create mode 100644 pkg/blockchain/blockchainPublisher_test.go create mode 100644 pkg/testutils/context.go diff --git a/pkg/api/payer/service.go b/pkg/api/payer/service.go index a25794d5..f800a7f2 100644 --- a/pkg/api/payer/service.go +++ b/pkg/api/payer/service.go @@ -5,6 +5,7 @@ import ( "crypto/ecdsa" "github.com/ethereum/go-ethereum/common" + "github.com/xmtp/xmtpd/pkg/abis" "github.com/xmtp/xmtpd/pkg/blockchain" "github.com/xmtp/xmtpd/pkg/constants" "github.com/xmtp/xmtpd/pkg/envelopes" @@ -188,9 +189,23 @@ func (s *Service) publishToBlockchain( var hash common.Hash switch kind { case topic.TOPIC_KIND_GROUP_MESSAGES_V1: - hash, err = s.blockchainPublisher.PublishGroupMessage(ctx, idBytes, payload) + var logMessage *abis.GroupMessagesMessageSent + if logMessage, err = s.blockchainPublisher.PublishGroupMessage(ctx, idBytes, payload); err != nil { + return nil, status.Errorf(codes.Internal, "error publishing group message: %v", err) + } + if logMessage == nil { + return nil, status.Errorf(codes.Internal, "received nil logMessage") + } + hash = logMessage.Raw.TxHash case topic.TOPIC_KIND_IDENTITY_UPDATES_V1: - hash, err = s.blockchainPublisher.PublishIdentityUpdate(ctx, idBytes, payload) + var logMessage *abis.IdentityUpdatesIdentityUpdateCreated + if logMessage, err = s.blockchainPublisher.PublishIdentityUpdate(ctx, idBytes, payload); err != nil { + return nil, status.Errorf(codes.Internal, "error publishing identity update: %v", err) + } + if logMessage == nil { + return nil, status.Errorf(codes.Internal, "received nil logMessage") + } + hash = logMessage.Raw.TxHash default: return nil, status.Errorf( codes.InvalidArgument, @@ -198,13 +213,6 @@ func (s *Service) publishToBlockchain( targetTopic.String(), ) } - if err != nil { - return nil, status.Errorf( - codes.Internal, - "error publishing group message: %v", - err, - ) - } return &envelopesProto.OriginatorEnvelope{ UnsignedOriginatorEnvelope: payload, diff --git a/pkg/blockchain/blockchainPublisher.go b/pkg/blockchain/blockchainPublisher.go index 9c53ef94..63e17b8f 100644 --- a/pkg/blockchain/blockchainPublisher.go +++ b/pkg/blockchain/blockchainPublisher.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/xmtp/xmtpd/pkg/abis" "github.com/xmtp/xmtpd/pkg/config" @@ -37,6 +38,7 @@ func NewBlockchainPublisher( common.HexToAddress(contractOptions.MessagesContractAddress), client, ) + if err != nil { return nil, err } @@ -62,17 +64,20 @@ func (m *BlockchainPublisher) PublishGroupMessage( ctx context.Context, groupID [32]byte, message []byte, -) (common.Hash, error) { +) (*abis.GroupMessagesMessageSent, error) { + if len(message) == 0 { + return nil, errors.New("message is empty") + } tx, err := m.messagesContract.AddMessage(&bind.TransactOpts{ Context: ctx, From: m.signer.FromAddress(), Signer: m.signer.SignerFunc(), }, groupID, message) if err != nil { - return common.Hash{}, err + return nil, err } - return WaitForTransaction( + receipt, err := WaitForTransaction( ctx, m.logger, m.client, @@ -80,23 +85,35 @@ func (m *BlockchainPublisher) PublishGroupMessage( 250*time.Millisecond, tx.Hash(), ) + if err != nil { + return nil, err + } + + if receipt == nil { + return nil, errors.New("transaction receipt is nil") + } + + return findLog(receipt, m.messagesContract.ParseMessageSent, "no message sent log found") } func (m *BlockchainPublisher) PublishIdentityUpdate( ctx context.Context, inboxId [32]byte, identityUpdate []byte, -) (common.Hash, error) { +) (*abis.IdentityUpdatesIdentityUpdateCreated, error) { + if len(identityUpdate) == 0 { + return nil, errors.New("identity update is empty") + } tx, err := m.identityUpdateContract.AddIdentityUpdate(&bind.TransactOpts{ Context: ctx, From: m.signer.FromAddress(), Signer: m.signer.SignerFunc(), }, inboxId, identityUpdate) if err != nil { - return common.Hash{}, err + return nil, err } - return WaitForTransaction( + receipt, err := WaitForTransaction( ctx, m.logger, m.client, @@ -104,4 +121,35 @@ func (m *BlockchainPublisher) PublishIdentityUpdate( 250*time.Millisecond, tx.Hash(), ) + if err != nil { + return nil, err + } + if receipt == nil { + return nil, errors.New("transaction receipt is nil") + } + + return findLog( + receipt, + m.identityUpdateContract.ParseIdentityUpdateCreated, + "no identity update log found", + ) +} + +func findLog[T any]( + receipt *types.Receipt, + parse func(types.Log) (*T, error), + errorMsg string, +) (*T, error) { + for _, logEntry := range receipt.Logs { + if logEntry == nil { + continue + } + event, err := parse(*logEntry) + if err != nil { + continue + } + return event, nil + } + + return nil, errors.New(errorMsg) } diff --git a/pkg/blockchain/blockchainPublisher_test.go b/pkg/blockchain/blockchainPublisher_test.go new file mode 100644 index 00000000..8d60c16c --- /dev/null +++ b/pkg/blockchain/blockchainPublisher_test.go @@ -0,0 +1,142 @@ +package blockchain + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "github.com/xmtp/xmtpd/pkg/testutils" +) + +func buildPublisher(t *testing.T) (*BlockchainPublisher, func()) { + ctx, cancel := context.WithCancel(context.Background()) + logger := testutils.NewLog(t) + contractsOptions := testutils.GetContractsOptions(t) + // Set the nodes contract address to a random smart contract instead of the fixed deployment + contractsOptions.NodesContractAddress = testutils.DeployNodesContract(t) + + signer, err := NewPrivateKeySigner( + testutils.GetPayerOptions(t).PrivateKey, + contractsOptions.ChainID, + ) + require.NoError(t, err) + + client, err := NewClient(ctx, contractsOptions.RpcUrl) + require.NoError(t, err) + + publisher, err := NewBlockchainPublisher(logger, client, signer, contractsOptions) + require.NoError(t, err) + + return publisher, func() { + cancel() + client.Close() + } +} + +func TestPublishIdentityUpdate(t *testing.T) { + publisher, cleanup := buildPublisher(t) + defer cleanup() + tests := []struct { + name string + inboxId [32]byte + identityUpdate []byte + ctx context.Context + wantErr bool + }{ + { + name: "happy path", + inboxId: testutils.RandomGroupID(), + identityUpdate: testutils.RandomBytes(100), + ctx: context.Background(), + wantErr: false, + }, + { + name: "empty update", + inboxId: testutils.RandomGroupID(), + identityUpdate: []byte{}, + ctx: context.Background(), + wantErr: true, + }, + { + name: "cancelled context", + inboxId: testutils.RandomGroupID(), + identityUpdate: testutils.RandomBytes(100), + ctx: testutils.CancelledContext(), + wantErr: true, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + logMessage, err := publisher.PublishIdentityUpdate( + tt.ctx, + tt.inboxId, + tt.identityUpdate, + ) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.NotNil(t, logMessage) + require.Equal(t, tt.inboxId, logMessage.InboxId) + require.Equal(t, tt.identityUpdate, logMessage.Update) + require.Greater(t, logMessage.SequenceId, uint64(0)) + require.NotNil(t, logMessage.Raw.TxHash) + }) + } +} + +func TestPublishGroupMessage(t *testing.T) { + publisher, cleanup := buildPublisher(t) + defer cleanup() + + tests := []struct { + name string + groupID [32]byte + message []byte + ctx context.Context + wantErr bool + }{ + { + name: "happy path", + groupID: testutils.RandomGroupID(), + message: testutils.RandomBytes(100), + ctx: context.Background(), + wantErr: false, + }, + { + name: "empty message", + groupID: testutils.RandomGroupID(), + message: []byte{}, + ctx: context.Background(), + wantErr: true, + }, + { + name: "cancelled context", + groupID: testutils.RandomGroupID(), + message: testutils.RandomBytes(100), + ctx: testutils.CancelledContext(), + wantErr: true, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + logMessage, err := publisher.PublishGroupMessage(tt.ctx, tt.groupID, tt.message) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.NotNil(t, logMessage) + require.Equal(t, tt.groupID, logMessage.GroupId) + require.Equal(t, tt.message, logMessage.Message) + require.Greater(t, logMessage.SequenceId, uint64(0)) + require.NotNil(t, logMessage.Raw.TxHash) + }) + } +} diff --git a/pkg/blockchain/client.go b/pkg/blockchain/client.go index 658f84f7..bc35ba41 100644 --- a/pkg/blockchain/client.go +++ b/pkg/blockchain/client.go @@ -6,6 +6,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "go.uber.org/zap" ) @@ -22,7 +23,7 @@ func WaitForTransaction( timeout time.Duration, pollSleep time.Duration, hash common.Hash, -) (common.Hash, error) { +) (*types.Receipt, error) { // Enforce the timeout with a context so that slow requests get aborted if the function has // run out of time ctx, cancel := context.WithDeadline(ctx, time.Now().Add(timeout)) @@ -33,18 +34,23 @@ func WaitForTransaction( defer ticker.Stop() for { - _, isPending, err := client.TransactionByHash(ctx, hash) + receipt, err := client.TransactionReceipt(ctx, hash) if err != nil { - logger.Error("waiting for transaction", zap.String("hash", hash.String())) - } else if !isPending { - return hash, nil + if err.Error() != "not found" { + logger.Error("waiting for transaction", zap.String("hash", hash.String())) + } + } else if receipt != nil { + if receipt.Status == types.ReceiptStatusSuccessful { + return receipt, nil + } + return nil, fmt.Errorf("transaction failed") } + select { case <-ctx.Done(): - return common.Hash{}, fmt.Errorf("timed out") + return nil, fmt.Errorf("timed out") case <-ticker.C: continue } } - } diff --git a/pkg/blockchain/interface.go b/pkg/blockchain/interface.go index 39dabeca..78031b96 100644 --- a/pkg/blockchain/interface.go +++ b/pkg/blockchain/interface.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/xmtp/xmtpd/pkg/abis" ) // Construct a raw blockchain listener that can be used to listen for events across many contract event types @@ -49,6 +50,10 @@ type IBlockchainPublisher interface { ctx context.Context, inboxId [32]byte, identityUpdate []byte, - ) (common.Hash, error) - PublishGroupMessage(ctx context.Context, groupdId [32]byte, message []byte) (common.Hash, error) + ) (*abis.IdentityUpdatesIdentityUpdateCreated, error) + PublishGroupMessage( + ctx context.Context, + groupdId [32]byte, + message []byte, + ) (*abis.GroupMessagesMessageSent, error) } diff --git a/pkg/mocks/blockchain/mock_IBlockchainPublisher.go b/pkg/mocks/blockchain/mock_IBlockchainPublisher.go index 71e398e3..dba74b98 100644 --- a/pkg/mocks/blockchain/mock_IBlockchainPublisher.go +++ b/pkg/mocks/blockchain/mock_IBlockchainPublisher.go @@ -3,9 +3,9 @@ package blockchain import ( - context "context" + abis "github.com/xmtp/xmtpd/pkg/abis" - common "github.com/ethereum/go-ethereum/common" + context "context" mock "github.com/stretchr/testify/mock" ) @@ -24,23 +24,23 @@ func (_m *MockIBlockchainPublisher) EXPECT() *MockIBlockchainPublisher_Expecter } // PublishGroupMessage provides a mock function with given fields: ctx, groupdId, message -func (_m *MockIBlockchainPublisher) PublishGroupMessage(ctx context.Context, groupdId [32]byte, message []byte) (common.Hash, error) { +func (_m *MockIBlockchainPublisher) PublishGroupMessage(ctx context.Context, groupdId [32]byte, message []byte) (*abis.GroupMessagesMessageSent, error) { ret := _m.Called(ctx, groupdId, message) if len(ret) == 0 { panic("no return value specified for PublishGroupMessage") } - var r0 common.Hash + var r0 *abis.GroupMessagesMessageSent var r1 error - if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) (common.Hash, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) (*abis.GroupMessagesMessageSent, error)); ok { return rf(ctx, groupdId, message) } - if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) common.Hash); ok { + if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) *abis.GroupMessagesMessageSent); ok { r0 = rf(ctx, groupdId, message) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Hash) + r0 = ret.Get(0).(*abis.GroupMessagesMessageSent) } } @@ -73,34 +73,34 @@ func (_c *MockIBlockchainPublisher_PublishGroupMessage_Call) Run(run func(ctx co return _c } -func (_c *MockIBlockchainPublisher_PublishGroupMessage_Call) Return(_a0 common.Hash, _a1 error) *MockIBlockchainPublisher_PublishGroupMessage_Call { +func (_c *MockIBlockchainPublisher_PublishGroupMessage_Call) Return(_a0 *abis.GroupMessagesMessageSent, _a1 error) *MockIBlockchainPublisher_PublishGroupMessage_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockIBlockchainPublisher_PublishGroupMessage_Call) RunAndReturn(run func(context.Context, [32]byte, []byte) (common.Hash, error)) *MockIBlockchainPublisher_PublishGroupMessage_Call { +func (_c *MockIBlockchainPublisher_PublishGroupMessage_Call) RunAndReturn(run func(context.Context, [32]byte, []byte) (*abis.GroupMessagesMessageSent, error)) *MockIBlockchainPublisher_PublishGroupMessage_Call { _c.Call.Return(run) return _c } // PublishIdentityUpdate provides a mock function with given fields: ctx, inboxId, identityUpdate -func (_m *MockIBlockchainPublisher) PublishIdentityUpdate(ctx context.Context, inboxId [32]byte, identityUpdate []byte) (common.Hash, error) { +func (_m *MockIBlockchainPublisher) PublishIdentityUpdate(ctx context.Context, inboxId [32]byte, identityUpdate []byte) (*abis.IdentityUpdatesIdentityUpdateCreated, error) { ret := _m.Called(ctx, inboxId, identityUpdate) if len(ret) == 0 { panic("no return value specified for PublishIdentityUpdate") } - var r0 common.Hash + var r0 *abis.IdentityUpdatesIdentityUpdateCreated var r1 error - if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) (common.Hash, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) (*abis.IdentityUpdatesIdentityUpdateCreated, error)); ok { return rf(ctx, inboxId, identityUpdate) } - if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) common.Hash); ok { + if rf, ok := ret.Get(0).(func(context.Context, [32]byte, []byte) *abis.IdentityUpdatesIdentityUpdateCreated); ok { r0 = rf(ctx, inboxId, identityUpdate) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Hash) + r0 = ret.Get(0).(*abis.IdentityUpdatesIdentityUpdateCreated) } } @@ -133,12 +133,12 @@ func (_c *MockIBlockchainPublisher_PublishIdentityUpdate_Call) Run(run func(ctx return _c } -func (_c *MockIBlockchainPublisher_PublishIdentityUpdate_Call) Return(_a0 common.Hash, _a1 error) *MockIBlockchainPublisher_PublishIdentityUpdate_Call { +func (_c *MockIBlockchainPublisher_PublishIdentityUpdate_Call) Return(_a0 *abis.IdentityUpdatesIdentityUpdateCreated, _a1 error) *MockIBlockchainPublisher_PublishIdentityUpdate_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockIBlockchainPublisher_PublishIdentityUpdate_Call) RunAndReturn(run func(context.Context, [32]byte, []byte) (common.Hash, error)) *MockIBlockchainPublisher_PublishIdentityUpdate_Call { +func (_c *MockIBlockchainPublisher_PublishIdentityUpdate_Call) RunAndReturn(run func(context.Context, [32]byte, []byte) (*abis.IdentityUpdatesIdentityUpdateCreated, error)) *MockIBlockchainPublisher_PublishIdentityUpdate_Call { _c.Call.Return(run) return _c } diff --git a/pkg/testutils/context.go b/pkg/testutils/context.go new file mode 100644 index 00000000..0f023055 --- /dev/null +++ b/pkg/testutils/context.go @@ -0,0 +1,9 @@ +package testutils + +import "context" + +func CancelledContext() context.Context { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + return ctx +} From 88e7845c635f7799d36e0e9a9ada3b50e90879b1 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Wed, 23 Oct 2024 12:54:26 -0700 Subject: [PATCH 2/4] Add tests and fix bugs for payer API (#248) ## TL;DR Gets the Payer API service to a mostly working state. ## TODO - Error handling is not great here. What happens when you have a payload that is a mix of envelopes destined for the blockchain and for other nodes, and some of the requests fail. There's no way to roll back across the other services. I think we will need to return more fine-grained error responses that return errors per `ClientEnvelope` instead of having the entire request/response succeed or fail. ## AI Generated Summary ### What changed? - Added `publish_test.go` for the payer API, implementing tests for publishing identity updates and group messages. - Updated `service.go` in the payer package to implement the `PublishClientEnvelopes` method. - Modified existing test files to use `NewTestReplicationAPIClient` instead of `NewTestAPIClient`. - Updated envelope-related functions to provide more specific error messages. - Added `NewPayerAPIClient` function in the API test utilities. - Modified `CreateGroupMessageClientEnvelope` to include a `targetOriginator` parameter. ### How to test? 1. Run the new payer API tests in `publish_test.go`. 2. Verify that existing tests pass with the updated client creation methods. 3. Test the `PublishClientEnvelopes` method of the payer service with various input scenarios. ### Why make this change? This change implements the payer API service, which is crucial for handling client envelope publishing. It also improves test utilities and error messages, making the codebase more robust and easier to debug. The updates to existing tests ensure compatibility with the new payer API functionality. ## Summary by CodeRabbit ## Release Notes - **New Features** - Introduced a new Payer API client for enhanced functionality. - Added comprehensive unit tests for the Payer API service. - **Improvements** - Enhanced error messages for better clarity in envelope-related functions. - Improved logging and response handling in the PublishClientEnvelopes method. - **Bug Fixes** - Updated API client initialization in various test functions to ensure consistency and accuracy. - **Tests** - Expanded test coverage for group message and client envelope functionalities. - Modified existing tests to adapt to new API client structures and parameters. --- pkg/api/message/publish_test.go | 8 +- pkg/api/message/subscribe_test.go | 2 +- pkg/api/payer/publish_test.go | 144 ++++++++++++++++++++++++ pkg/api/payer/service.go | 56 ++++++++- pkg/api/query_test.go | 20 ++-- pkg/envelopes/client.go | 2 +- pkg/envelopes/originator.go | 2 +- pkg/envelopes/payer.go | 2 +- pkg/envelopes/unsignedOriginator.go | 2 +- pkg/indexer/e2e_test.go | 2 +- pkg/indexer/storer/groupMessage_test.go | 4 +- pkg/server/server_test.go | 4 +- pkg/testutils/api/api.go | 27 ++++- pkg/testutils/envelopes/envelopes.go | 5 +- pkg/topic/topic.go | 8 +- 15 files changed, 249 insertions(+), 39 deletions(-) create mode 100644 pkg/api/payer/publish_test.go diff --git a/pkg/api/message/publish_test.go b/pkg/api/message/publish_test.go index c5027240..a73bbc42 100644 --- a/pkg/api/message/publish_test.go +++ b/pkg/api/message/publish_test.go @@ -16,7 +16,7 @@ import ( ) func TestPublishEnvelope(t *testing.T) { - api, db, cleanup := apiTestUtils.NewTestAPIClient(t) + api, db, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() payerEnvelope := envelopeTestUtils.CreatePayerEnvelope(t) @@ -64,7 +64,7 @@ func TestPublishEnvelope(t *testing.T) { } func TestUnmarshalErrorOnPublish(t *testing.T) { - api, _, cleanup := apiTestUtils.NewTestAPIClient(t) + api, _, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() envelope := envelopeTestUtils.CreatePayerEnvelope(t) @@ -79,7 +79,7 @@ func TestUnmarshalErrorOnPublish(t *testing.T) { } func TestMismatchingOriginatorOnPublish(t *testing.T) { - api, _, cleanup := apiTestUtils.NewTestAPIClient(t) + api, _, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() clientEnv := envelopeTestUtils.CreateClientEnvelope() @@ -96,7 +96,7 @@ func TestMismatchingOriginatorOnPublish(t *testing.T) { } func TestMissingTopicOnPublish(t *testing.T) { - api, _, cleanup := apiTestUtils.NewTestAPIClient(t) + api, _, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() clientEnv := envelopeTestUtils.CreateClientEnvelope() diff --git a/pkg/api/message/subscribe_test.go b/pkg/api/message/subscribe_test.go index 938f419b..e79c4cc9 100644 --- a/pkg/api/message/subscribe_test.go +++ b/pkg/api/message/subscribe_test.go @@ -70,7 +70,7 @@ func setupTest(t *testing.T) (message_api.ReplicationApiClient, *sql.DB, func()) }, } - return testUtilsApi.NewTestAPIClient(t) + return testUtilsApi.NewTestReplicationAPIClient(t) } func insertInitialRows(t *testing.T, store *sql.DB) { diff --git a/pkg/api/payer/publish_test.go b/pkg/api/payer/publish_test.go new file mode 100644 index 00000000..a2164454 --- /dev/null +++ b/pkg/api/payer/publish_test.go @@ -0,0 +1,144 @@ +package payer_test + +import ( + "context" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/xmtp/xmtpd/pkg/abis" + "github.com/xmtp/xmtpd/pkg/api/payer" + "github.com/xmtp/xmtpd/pkg/envelopes" + blockchainMocks "github.com/xmtp/xmtpd/pkg/mocks/blockchain" + registryMocks "github.com/xmtp/xmtpd/pkg/mocks/registry" + "github.com/xmtp/xmtpd/pkg/proto/identity/associations" + envelopesProto "github.com/xmtp/xmtpd/pkg/proto/xmtpv4/envelopes" + "github.com/xmtp/xmtpd/pkg/proto/xmtpv4/payer_api" + "github.com/xmtp/xmtpd/pkg/registry" + "github.com/xmtp/xmtpd/pkg/testutils" + apiTestUtils "github.com/xmtp/xmtpd/pkg/testutils/api" + envelopesTestUtils "github.com/xmtp/xmtpd/pkg/testutils/envelopes" + "github.com/xmtp/xmtpd/pkg/utils" + "google.golang.org/protobuf/proto" +) + +func buildPayerService( + t *testing.T, +) (*payer.Service, *blockchainMocks.MockIBlockchainPublisher, *registryMocks.MockNodeRegistry, func()) { + ctx, cancel := context.WithCancel(context.Background()) + log := testutils.NewLog(t) + privKey, err := crypto.GenerateKey() + require.NoError(t, err) + mockRegistry := registryMocks.NewMockNodeRegistry(t) + + require.NoError(t, err) + mockMessagePublisher := blockchainMocks.NewMockIBlockchainPublisher(t) + + payerService, err := payer.NewPayerApiService( + ctx, + log, + mockRegistry, + privKey, + mockMessagePublisher, + ) + require.NoError(t, err) + + return payerService, mockMessagePublisher, mockRegistry, func() { + cancel() + } +} + +func TestPublishIdentityUpdate(t *testing.T) { + ctx := context.Background() + svc, mockMessagePublisher, _, cleanup := buildPayerService(t) + defer cleanup() + + inboxId := testutils.RandomInboxId() + inboxIdBytes, err := utils.ParseInboxId(inboxId) + require.NoError(t, err) + + txnHash := common.Hash{1, 2, 3} + sequenceId := uint64(99) + + identityUpdate := &associations.IdentityUpdate{ + InboxId: inboxId, + } + + envelope := envelopesTestUtils.CreateIdentityUpdateClientEnvelope(inboxIdBytes, identityUpdate) + envelopeBytes, err := proto.Marshal(envelope) + require.NoError(t, err) + + mockMessagePublisher.EXPECT(). + PublishIdentityUpdate(mock.Anything, mock.Anything, mock.Anything). + Return(&abis.IdentityUpdatesIdentityUpdateCreated{ + Raw: types.Log{ + TxHash: txnHash, + }, + SequenceId: sequenceId, + Update: envelopeBytes, + }, nil) + + publishResponse, err := svc.PublishClientEnvelopes( + ctx, + &payer_api.PublishClientEnvelopesRequest{ + Envelopes: []*envelopesProto.ClientEnvelope{envelope}, + }, + ) + require.NoError(t, err) + require.NotNil(t, publishResponse) + require.Len(t, publishResponse.OriginatorEnvelopes, 1) + + responseEnvelope := publishResponse.OriginatorEnvelopes[0] + parsedOriginatorEnvelope, err := envelopes.NewOriginatorEnvelope(responseEnvelope) + require.NoError(t, err) + + proof := parsedOriginatorEnvelope.Proto().Proof.(*envelopesProto.OriginatorEnvelope_BlockchainProof) + + require.Equal(t, proof.BlockchainProof.TransactionHash, txnHash[:]) + require.Equal( + t, + parsedOriginatorEnvelope.UnsignedOriginatorEnvelope.OriginatorSequenceID(), + sequenceId, + ) +} + +func TestPublishToNodes(t *testing.T) { + originatorServer, _, originatorCleanup := apiTestUtils.NewTestAPIServer(t) + defer originatorCleanup() + + ctx := context.Background() + svc, _, mockRegistry, cleanup := buildPayerService(t) + defer cleanup() + + mockRegistry.EXPECT().GetNode(mock.Anything).Return(®istry.Node{ + HttpAddress: formatAddress(originatorServer.Addr().String()), + }, nil) + + groupId := testutils.RandomGroupID() + testGroupMessage := envelopesTestUtils.CreateGroupMessageClientEnvelope( + groupId, + []byte("test message"), + 100, // This is the expected originator ID of the test server + ) + + publishResponse, err := svc.PublishClientEnvelopes( + ctx, + &payer_api.PublishClientEnvelopesRequest{ + Envelopes: []*envelopesProto.ClientEnvelope{testGroupMessage}, + }, + ) + require.NoError(t, err) + require.NotNil(t, publishResponse) + require.Len(t, publishResponse.OriginatorEnvelopes, 1) + + responseEnvelope := publishResponse.OriginatorEnvelopes[0] + parsedOriginatorEnvelope, err := envelopes.NewOriginatorEnvelope(responseEnvelope) + require.NoError(t, err) + + targetTopic := parsedOriginatorEnvelope.UnsignedOriginatorEnvelope.PayerEnvelope.ClientEnvelope.TargetTopic() + + require.Equal(t, targetTopic.Identifier(), groupId[:]) +} diff --git a/pkg/api/payer/service.go b/pkg/api/payer/service.go index f800a7f2..71bc57f7 100644 --- a/pkg/api/payer/service.go +++ b/pkg/api/payer/service.go @@ -3,6 +3,7 @@ package payer import ( "context" "crypto/ecdsa" + "time" "github.com/ethereum/go-ethereum/common" "github.com/xmtp/xmtpd/pkg/abis" @@ -19,6 +20,7 @@ import ( "go.uber.org/zap" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" ) type Service struct { @@ -60,8 +62,8 @@ func (s *Service) PublishClientEnvelopes( // For each originator found in the request, publish all matching envelopes to the node for originatorId, payloadsWithIndex := range grouped.forNodes { + s.log.Info("publishing to originator", zap.Uint32("originator_id", originatorId)) originatorEnvelopes, err := s.publishToNodes(ctx, originatorId, payloadsWithIndex) - if err != nil { s.log.Error("error publishing payer envelopes", zap.Error(err)) return nil, status.Error(codes.Internal, "error publishing payer envelopes") @@ -74,6 +76,10 @@ func (s *Service) PublishClientEnvelopes( } for _, payload := range grouped.forBlockchain { + s.log.Info( + "publishing to blockchain", + zap.String("topic", payload.payload.TargetTopic().String()), + ) var originatorEnvelope *envelopesProto.OriginatorEnvelope if originatorEnvelope, err = s.publishToBlockchain(ctx, payload.payload); err != nil { return nil, status.Errorf(codes.Internal, "error publishing group message: %v", err) @@ -81,7 +87,9 @@ func (s *Service) PublishClientEnvelopes( out[payload.originalIndex] = originatorEnvelope } - return nil, status.Errorf(codes.Unimplemented, "method PublishClientEnvelopes not implemented") + return &payer_api.PublishClientEnvelopesResponse{ + OriginatorEnvelopes: out, + }, nil } // A struct that groups client envelopes by their intended destination @@ -95,7 +103,7 @@ type groupedEnvelopes struct { func (s *Service) groupEnvelopes( rawEnvelopes []*envelopesProto.ClientEnvelope, ) (*groupedEnvelopes, error) { - out := groupedEnvelopes{} + out := groupedEnvelopes{forNodes: make(map[uint32][]clientEnvelopeWithIndex)} for i, rawClientEnvelope := range rawEnvelopes { clientEnvelope, err := envelopes.NewClientEnvelope(rawClientEnvelope) @@ -186,6 +194,7 @@ func (s *Service) publishToBlockchain( ) } + var unsignedOriginatorEnvelope *envelopesProto.UnsignedOriginatorEnvelope var hash common.Hash switch kind { case topic.TOPIC_KIND_GROUP_MESSAGES_V1: @@ -196,7 +205,14 @@ func (s *Service) publishToBlockchain( if logMessage == nil { return nil, status.Errorf(codes.Internal, "received nil logMessage") } + hash = logMessage.Raw.TxHash + unsignedOriginatorEnvelope = buildUnsignedOriginatorEnvelopeFromChain( + clientEnvelope.Aad().TargetOriginator, + logMessage.SequenceId, + logMessage.Message, + ) + case topic.TOPIC_KIND_IDENTITY_UPDATES_V1: var logMessage *abis.IdentityUpdatesIdentityUpdateCreated if logMessage, err = s.blockchainPublisher.PublishIdentityUpdate(ctx, idBytes, payload); err != nil { @@ -205,7 +221,13 @@ func (s *Service) publishToBlockchain( if logMessage == nil { return nil, status.Errorf(codes.Internal, "received nil logMessage") } + hash = logMessage.Raw.TxHash + unsignedOriginatorEnvelope = buildUnsignedOriginatorEnvelopeFromChain( + clientEnvelope.Aad().TargetOriginator, + logMessage.SequenceId, + logMessage.Update, + ) default: return nil, status.Errorf( codes.InvalidArgument, @@ -214,8 +236,17 @@ func (s *Service) publishToBlockchain( ) } + unsignedBytes, err := proto.Marshal(unsignedOriginatorEnvelope) + if err != nil { + return nil, status.Errorf( + codes.Internal, + "error marshalling unsigned originator envelope: %v", + err, + ) + } + return &envelopesProto.OriginatorEnvelope{ - UnsignedOriginatorEnvelope: payload, + UnsignedOriginatorEnvelope: unsignedBytes, Proof: &envelopesProto.OriginatorEnvelope_BlockchainProof{ BlockchainProof: &envelopesProto.BlockchainProof{ TransactionHash: hash.Bytes(), @@ -224,6 +255,21 @@ func (s *Service) publishToBlockchain( }, nil } +func buildUnsignedOriginatorEnvelopeFromChain( + targetOriginator uint32, + sequenceID uint64, + clientEnvelope []byte, +) *envelopesProto.UnsignedOriginatorEnvelope { + return &envelopesProto.UnsignedOriginatorEnvelope{ + OriginatorNodeId: targetOriginator, + OriginatorSequenceId: sequenceID, + OriginatorNs: time.Now().UnixNano(), // TODO: get this data from the chain + PayerEnvelope: &envelopesProto.PayerEnvelope{ + UnsignedClientEnvelope: clientEnvelope, + }, + } +} + func (s *Service) signAllClientEnvelopes( indexedEnvelopes []clientEnvelopeWithIndex, ) ([]*envelopesProto.PayerEnvelope, error) { @@ -264,7 +310,7 @@ func shouldSendToBlockchain(targetTopic topic.Topic, aad *envelopesProto.Authent case topic.TOPIC_KIND_IDENTITY_UPDATES_V1: return true case topic.TOPIC_KIND_GROUP_MESSAGES_V1: - return aad.TargetOriginator < constants.MAX_BLOCKCHAIN_ORIGINATOR_ID + return aad.TargetOriginator < uint32(constants.MAX_BLOCKCHAIN_ORIGINATOR_ID) default: return false } diff --git a/pkg/api/query_test.go b/pkg/api/query_test.go index 54eb6957..c1499772 100644 --- a/pkg/api/query_test.go +++ b/pkg/api/query_test.go @@ -68,7 +68,7 @@ func setupQueryTest(t *testing.T, db *sql.DB) []queries.InsertGatewayEnvelopePar } func TestQueryAllEnvelopes(t *testing.T) { - api, db, cleanup := apiTestUtils.NewTestAPIClient(t) + api, db, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() db_rows := setupQueryTest(t, db) @@ -84,7 +84,7 @@ func TestQueryAllEnvelopes(t *testing.T) { } func TestQueryPagedEnvelopes(t *testing.T) { - api, db, cleanup := apiTestUtils.NewTestAPIClient(t) + api, db, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() db_rows := setupQueryTest(t, db) @@ -100,7 +100,7 @@ func TestQueryPagedEnvelopes(t *testing.T) { } func TestQueryEnvelopesByOriginator(t *testing.T) { - api, db, cleanup := apiTestUtils.NewTestAPIClient(t) + api, db, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() db_rows := setupQueryTest(t, db) @@ -119,7 +119,7 @@ func TestQueryEnvelopesByOriginator(t *testing.T) { } func TestQueryEnvelopesByTopic(t *testing.T) { - api, store, cleanup := apiTestUtils.NewTestAPIClient(t) + api, store, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() db_rows := setupQueryTest(t, store) @@ -138,7 +138,7 @@ func TestQueryEnvelopesByTopic(t *testing.T) { } func TestQueryEnvelopesFromLastSeen(t *testing.T) { - api, db, cleanup := apiTestUtils.NewTestAPIClient(t) + api, db, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() db_rows := setupQueryTest(t, db) @@ -156,7 +156,7 @@ func TestQueryEnvelopesFromLastSeen(t *testing.T) { } func TestQueryTopicFromLastSeen(t *testing.T) { - api, store, cleanup := apiTestUtils.NewTestAPIClient(t) + api, store, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() db_rows := setupQueryTest(t, store) @@ -177,7 +177,7 @@ func TestQueryTopicFromLastSeen(t *testing.T) { } func TestQueryMultipleTopicsFromLastSeen(t *testing.T) { - api, store, cleanup := apiTestUtils.NewTestAPIClient(t) + api, store, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() db_rows := setupQueryTest(t, store) @@ -198,7 +198,7 @@ func TestQueryMultipleTopicsFromLastSeen(t *testing.T) { } func TestQueryMultipleOriginatorsFromLastSeen(t *testing.T) { - api, store, cleanup := apiTestUtils.NewTestAPIClient(t) + api, store, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() db_rows := setupQueryTest(t, store) @@ -219,7 +219,7 @@ func TestQueryMultipleOriginatorsFromLastSeen(t *testing.T) { } func TestQueryEnvelopesWithEmptyResult(t *testing.T) { - api, store, cleanup := apiTestUtils.NewTestAPIClient(t) + api, store, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() db_rows := setupQueryTest(t, store) @@ -237,7 +237,7 @@ func TestQueryEnvelopesWithEmptyResult(t *testing.T) { } func TestInvalidQuery(t *testing.T) { - api, store, cleanup := apiTestUtils.NewTestAPIClient(t) + api, store, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() _ = setupQueryTest(t, store) diff --git a/pkg/envelopes/client.go b/pkg/envelopes/client.go index 80178598..7ff94bb9 100644 --- a/pkg/envelopes/client.go +++ b/pkg/envelopes/client.go @@ -16,7 +16,7 @@ type ClientEnvelope struct { func NewClientEnvelope(proto *envelopesProto.ClientEnvelope) (*ClientEnvelope, error) { if proto == nil { - return nil, errors.New("proto is nil") + return nil, errors.New("client envelope proto is nil") } if proto.Aad == nil { diff --git a/pkg/envelopes/originator.go b/pkg/envelopes/originator.go index 9a79cd08..76286bcd 100644 --- a/pkg/envelopes/originator.go +++ b/pkg/envelopes/originator.go @@ -15,7 +15,7 @@ type OriginatorEnvelope struct { func NewOriginatorEnvelope(proto *envelopesProto.OriginatorEnvelope) (*OriginatorEnvelope, error) { if proto == nil { - return nil, errors.New("proto is nil") + return nil, errors.New("originator envelope proto is nil") } unsigned, err := NewUnsignedOriginatorEnvelopeFromBytes(proto.UnsignedOriginatorEnvelope) diff --git a/pkg/envelopes/payer.go b/pkg/envelopes/payer.go index c7ea76f3..22ec7183 100644 --- a/pkg/envelopes/payer.go +++ b/pkg/envelopes/payer.go @@ -17,7 +17,7 @@ type PayerEnvelope struct { func NewPayerEnvelope(proto *envelopesProto.PayerEnvelope) (*PayerEnvelope, error) { if proto == nil { - return nil, errors.New("proto is nil") + return nil, errors.New("payer envelope proto is nil") } clientEnv, err := NewClientEnvelopeFromBytes(proto.UnsignedClientEnvelope) diff --git a/pkg/envelopes/unsignedOriginator.go b/pkg/envelopes/unsignedOriginator.go index 9d00a199..a98517e7 100644 --- a/pkg/envelopes/unsignedOriginator.go +++ b/pkg/envelopes/unsignedOriginator.go @@ -18,7 +18,7 @@ func NewUnsignedOriginatorEnvelope( proto *envelopesProto.UnsignedOriginatorEnvelope, ) (*UnsignedOriginatorEnvelope, error) { if proto == nil { - return nil, errors.New("proto is nil") + return nil, errors.New("unsigned originator envelopeproto is nil") } payer, err := NewPayerEnvelope(proto.PayerEnvelope) diff --git a/pkg/indexer/e2e_test.go b/pkg/indexer/e2e_test.go index 239d68af..2c76eed8 100644 --- a/pkg/indexer/e2e_test.go +++ b/pkg/indexer/e2e_test.go @@ -62,7 +62,7 @@ func TestStoreMessages(t *testing.T) { groupID := testutils.RandomGroupID() topic := topic.NewTopic(topic.TOPIC_KIND_GROUP_MESSAGES_V1, groupID[:]).Bytes() - clientEnvelope := envelopesTestUtils.CreateGroupMessageClientEnvelope(groupID, message) + clientEnvelope := envelopesTestUtils.CreateGroupMessageClientEnvelope(groupID, message, 0) clientEnvelopeBytes, err := proto.Marshal(clientEnvelope) require.NoError(t, err) diff --git a/pkg/indexer/storer/groupMessage_test.go b/pkg/indexer/storer/groupMessage_test.go index 5540b1f5..3499486c 100644 --- a/pkg/indexer/storer/groupMessage_test.go +++ b/pkg/indexer/storer/groupMessage_test.go @@ -49,7 +49,7 @@ func TestStoreGroupMessages(t *testing.T) { message := testutils.RandomBytes(30) sequenceID := uint64(1) - clientEnvelope := envelopesTestUtils.CreateGroupMessageClientEnvelope(groupID, message) + clientEnvelope := envelopesTestUtils.CreateGroupMessageClientEnvelope(groupID, message, 0) logMessage := testutils.BuildMessageSentLog(t, groupID, clientEnvelope, sequenceID) var err error @@ -92,7 +92,7 @@ func TestStoreGroupMessageDuplicate(t *testing.T) { message := testutils.RandomBytes(30) sequenceID := uint64(1) - clientEnvelope := envelopesTestUtils.CreateGroupMessageClientEnvelope(groupID, message) + clientEnvelope := envelopesTestUtils.CreateGroupMessageClientEnvelope(groupID, message, 0) logMessage := testutils.BuildMessageSentLog(t, groupID, clientEnvelope, sequenceID) diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go index 4d00af06..6539e945 100644 --- a/pkg/server/server_test.go +++ b/pkg/server/server_test.go @@ -90,9 +90,9 @@ func TestCreateServer(t *testing.T) { server2 := NewTestServer(t, server2Port, dbs[1], registry, privateKey2) require.NotEqual(t, server1.Addr(), server2.Addr()) - client1, cleanup1 := apiTestUtils.NewAPIClient(t, ctx, server1.Addr().String()) + client1, cleanup1 := apiTestUtils.NewReplicationAPIClient(t, ctx, server1.Addr().String()) defer cleanup1() - client2, cleanup2 := apiTestUtils.NewAPIClient(t, ctx, server2.Addr().String()) + client2, cleanup2 := apiTestUtils.NewReplicationAPIClient(t, ctx, server2.Addr().String()) defer cleanup2() targetTopic := topic.NewTopic(topic.TOPIC_KIND_GROUP_MESSAGES_V1, []byte{1, 2, 3}). diff --git a/pkg/testutils/api/api.go b/pkg/testutils/api/api.go index 824f0adb..11862f84 100644 --- a/pkg/testutils/api/api.go +++ b/pkg/testutils/api/api.go @@ -24,7 +24,7 @@ import ( "google.golang.org/grpc/credentials/insecure" ) -func NewAPIClient( +func NewReplicationAPIClient( t *testing.T, ctx context.Context, addr string, @@ -44,6 +44,25 @@ func NewAPIClient( } } +func NewPayerAPIClient( + t *testing.T, + ctx context.Context, + addr string, +) (payer_api.PayerApiClient, func()) { + dialAddr := fmt.Sprintf("passthrough://localhost/%s", addr) + conn, err := grpc.NewClient( + dialAddr, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithDefaultCallOptions(), + ) + require.NoError(t, err) + client := payer_api.NewPayerApiClient(conn) + return client, func() { + err := conn.Close() + require.NoError(t, err) + } +} + func NewTestAPIServer(t *testing.T) (*api.ApiServer, *sql.DB, func()) { ctx, cancel := context.WithCancel(context.Background()) log := testutils.NewLog(t) @@ -53,7 +72,7 @@ func NewTestAPIServer(t *testing.T) (*api.ApiServer, *sql.DB, func()) { privKeyStr := "0x" + utils.HexEncode(crypto.FromECDSA(privKey)) mockRegistry := mocks.NewMockNodeRegistry(t) mockRegistry.EXPECT().GetNodes().Return([]registry.Node{ - {NodeID: 1, SigningKey: &privKey.PublicKey}, + {NodeID: 100, SigningKey: &privKey.PublicKey}, }, nil) registrant, err := registrant.NewRegistrant(ctx, log, queries.New(db), mockRegistry, privKeyStr) require.NoError(t, err) @@ -98,9 +117,9 @@ func NewTestAPIServer(t *testing.T) (*api.ApiServer, *sql.DB, func()) { } } -func NewTestAPIClient(t *testing.T) (message_api.ReplicationApiClient, *sql.DB, func()) { +func NewTestReplicationAPIClient(t *testing.T) (message_api.ReplicationApiClient, *sql.DB, func()) { svc, db, svcCleanup := NewTestAPIServer(t) - client, clientCleanup := NewAPIClient(t, context.Background(), svc.Addr().String()) + client, clientCleanup := NewReplicationAPIClient(t, context.Background(), svc.Addr().String()) return client, db, func() { clientCleanup() svcCleanup() diff --git a/pkg/testutils/envelopes/envelopes.go b/pkg/testutils/envelopes/envelopes.go index 648d8a5e..b1a41699 100644 --- a/pkg/testutils/envelopes/envelopes.go +++ b/pkg/testutils/envelopes/envelopes.go @@ -27,7 +27,7 @@ func UnmarshalUnsignedOriginatorEnvelope( func CreateClientEnvelope(aad ...*envelopes.AuthenticatedData) *envelopes.ClientEnvelope { if len(aad) == 0 { aad = append(aad, &envelopes.AuthenticatedData{ - TargetOriginator: 1, + TargetOriginator: 100, TargetTopic: topic.NewTopic(topic.TOPIC_KIND_GROUP_MESSAGES_V1, []byte{1, 2, 3}). Bytes(), LastSeen: &envelopes.VectorClock{}, @@ -42,12 +42,13 @@ func CreateClientEnvelope(aad ...*envelopes.AuthenticatedData) *envelopes.Client func CreateGroupMessageClientEnvelope( groupID [32]byte, message []byte, + targetOriginator uint32, ) *envelopes.ClientEnvelope { return &envelopes.ClientEnvelope{ Aad: &envelopes.AuthenticatedData{ TargetTopic: topic.NewTopic(topic.TOPIC_KIND_GROUP_MESSAGES_V1, groupID[:]). Bytes(), - TargetOriginator: 0, + TargetOriginator: targetOriginator, }, Payload: &envelopes.ClientEnvelope_GroupMessage{ GroupMessage: &mlsv1.GroupMessageInput{ diff --git a/pkg/topic/topic.go b/pkg/topic/topic.go index 69af1fcf..9e1dbf4b 100644 --- a/pkg/topic/topic.go +++ b/pkg/topic/topic.go @@ -41,14 +41,14 @@ func NewTopic(kind TopicKind, identifier []byte) *Topic { } } -func (t *Topic) Bytes() []byte { +func (t Topic) Bytes() []byte { result := make([]byte, 1+len(t.identifier)) result[0] = byte(t.kind) copy(result[1:], t.identifier) return result } -func (t *Topic) String() string { +func (t Topic) String() string { return fmt.Sprintf("%s/%x", t.kind.String(), t.identifier) } @@ -69,10 +69,10 @@ func ParseTopic(topic []byte) (*Topic, error) { return newTopic, nil } -func (t *Topic) Kind() TopicKind { +func (t Topic) Kind() TopicKind { return t.kind } -func (t *Topic) Identifier() []byte { +func (t Topic) Identifier() []byte { return t.identifier } From 7519602afe8cb4cd6095ff41d431b291b7797434 Mon Sep 17 00:00:00 2001 From: Martin Kysel Date: Thu, 24 Oct 2024 08:31:43 -0700 Subject: [PATCH 3/4] Pin Foundry to the latest working version (#257) --- .github/workflows/lint.yml | 2 ++ .github/workflows/test.yml | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 48216973..9074580b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -37,6 +37,8 @@ jobs: submodules: recursive - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 + with: + version: 'nightly-2044faec64f99a21f0e5f0094458a973612d0712' - run: forge --version - name: Run Forge fmt # only format code, we do not want to format LIB diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 960d4e3c..b685aaed 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,6 +18,8 @@ jobs: - run: dev/docker/up - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 + with: + version: 'nightly-2044faec64f99a21f0e5f0094458a973612d0712' - run: dev/contracts/deploy-local - name: Run Tests run: | @@ -48,6 +50,8 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 + with: + version: 'nightly-2044faec64f99a21f0e5f0094458a973612d0712' - name: Run Forge build working-directory: contracts From 06f6e291bd81acd93e28db676a95cbccf10fd725 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 08:39:33 -0700 Subject: [PATCH 4/4] Update Protos (#256) - Nightly Proto Update Auto-generated by [create-pull-request][1] [1]: https://github.com/peter-evans/create-pull-request Co-authored-by: mkysel <7513948+mkysel@users.noreply.github.com> --- .../identity/associations/association.pb.go | 270 +++++++++--------- .../mls_validation/v1/service.swagger.json | 4 + 2 files changed, 145 insertions(+), 129 deletions(-) diff --git a/pkg/proto/identity/associations/association.pb.go b/pkg/proto/identity/associations/association.pb.go index 73d76550..58ff4e90 100644 --- a/pkg/proto/identity/associations/association.pb.go +++ b/pkg/proto/identity/associations/association.pb.go @@ -111,6 +111,7 @@ type Member struct { Identifier *MemberIdentifier `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"` AddedByEntity *MemberIdentifier `protobuf:"bytes,2,opt,name=added_by_entity,json=addedByEntity,proto3,oneof" json:"added_by_entity,omitempty"` ClientTimestampNs *uint64 `protobuf:"varint,3,opt,name=client_timestamp_ns,json=clientTimestampNs,proto3,oneof" json:"client_timestamp_ns,omitempty"` + AddedOnChainId *uint64 `protobuf:"varint,4,opt,name=added_on_chain_id,json=addedOnChainId,proto3,oneof" json:"added_on_chain_id,omitempty"` } func (x *Member) Reset() { @@ -164,6 +165,13 @@ func (x *Member) GetClientTimestampNs() uint64 { return 0 } +func (x *Member) GetAddedOnChainId() uint64 { + if x != nil && x.AddedOnChainId != nil { + return *x.AddedOnChainId + } + return 0 +} + // 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 @@ -774,7 +782,7 @@ var file_identity_associations_association_proto_rawDesc = []byte{ 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x92, + 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0xd8, 0x02, 0x0a, 0x06, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x4c, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, @@ -789,146 +797,150 @@ var file_identity_associations_association_proto_rawDesc = []byte{ 0x01, 0x01, 0x12, 0x33, 0x0a, 0x13, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x48, 0x01, 0x52, 0x11, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x4e, 0x73, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x61, 0x64, 0x64, 0x65, + 0x6d, 0x70, 0x4e, 0x73, 0x88, 0x01, 0x01, 0x12, 0x2e, 0x0a, 0x11, 0x61, 0x64, 0x64, 0x65, 0x64, + 0x5f, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x04, 0x48, 0x02, 0x52, 0x0e, 0x61, 0x64, 0x64, 0x65, 0x64, 0x4f, 0x6e, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x5f, 0x6e, 0x73, 0x22, 0xaf, 0x01, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, - 0x62, 0x6f, 0x78, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, - 0x69, 0x74, 0x69, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, - 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6e, 0x6f, 0x6e, - 0x63, 0x65, 0x12, 0x61, 0x0a, 0x19, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x17, 0x69, 0x6e, - 0x69, 0x74, 0x69, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xae, 0x02, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x41, 0x73, 0x73, - 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x60, 0x0a, 0x15, 0x6e, 0x65, 0x77, 0x5f, - 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x13, 0x6e, 0x65, 0x77, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x61, 0x0a, 0x19, 0x65, 0x78, - 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, - 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x17, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x57, 0x0a, - 0x14, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, + 0x5f, 0x6e, 0x73, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x6f, 0x6e, + 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0xaf, 0x01, 0x0a, 0x0b, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x69, + 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x61, 0x0a, 0x19, 0x69, 0x6e, 0x69, 0x74, + 0x69, 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x12, 0x6e, 0x65, 0x77, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xd0, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x76, 0x6f, 0x6b, - 0x65, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x56, 0x0a, 0x10, - 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x52, 0x0e, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x54, 0x6f, 0x52, 0x65, - 0x76, 0x6f, 0x6b, 0x65, 0x12, 0x63, 0x0a, 0x1a, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, + 0x72, 0x65, 0x52, 0x17, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xae, 0x02, 0x0a, 0x0e, + 0x41, 0x64, 0x64, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x60, + 0x0a, 0x15, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, + 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x13, 0x6e, 0x65, 0x77, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x12, 0x61, 0x0a, 0x19, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x17, 0x65, 0x78, 0x69, 0x73, + 0x74, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x12, 0x57, 0x0a, 0x14, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x12, 0x6e, 0x65, 0x77, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xd0, 0x01, 0x0a, + 0x11, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x56, 0x0a, 0x10, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x5f, + 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, + 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0e, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x54, 0x6f, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x12, 0x63, 0x0a, 0x1a, 0x72, 0x65, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, + 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x18, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, + 0xbf, 0x01, 0x0a, 0x15, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x6e, 0x65, 0x77, + 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6e, 0x65, 0x77, 0x52, 0x65, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x74, 0x0a, 0x23, 0x65, + 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x18, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xbf, 0x01, 0x0a, 0x15, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x12, 0x6e, 0x65, 0x77, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x74, 0x0a, 0x23, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, - 0x67, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0xdc, 0x02, 0x0a, 0x0e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4c, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x69, + 0x6e, 0x62, 0x6f, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, + 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, + 0x62, 0x6f, 0x78, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, + 0x6f, 0x78, 0x12, 0x3e, 0x0a, 0x03, 0x61, 0x64, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, + 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x41, 0x64, 0x64, + 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x03, 0x61, + 0x64, 0x64, 0x12, 0x47, 0x0a, 0x06, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, - 0x69, 0x6e, 0x67, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xdc, 0x02, 0x0a, 0x0e, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4c, - 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x48, 0x00, 0x52, - 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x12, 0x3e, 0x0a, 0x03, - 0x61, 0x64, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x03, 0x61, 0x64, 0x64, 0x12, 0x47, 0x0a, 0x06, - 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x78, + 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x12, 0x6b, 0x0a, 0x17, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, - 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, - 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, - 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x12, 0x6b, 0x0a, 0x17, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, - 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, + 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, + 0x00, 0x52, 0x15, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, + 0x22, 0xa1, 0x01, 0x0a, 0x0e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x12, 0x44, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4e, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x62, + 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, 0x62, + 0x6f, 0x78, 0x49, 0x64, 0x22, 0x85, 0x01, 0x0a, 0x09, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4d, + 0x61, 0x70, 0x12, 0x3e, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, + 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x38, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc2, 0x01, 0x0a, + 0x10, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x3f, 0x0a, 0x07, + 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, + 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, + 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x4d, 0x61, 0x70, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x29, 0x0a, + 0x10, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x65, 0x6e, + 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0c, 0x52, 0x0e, 0x73, 0x65, 0x65, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x73, 0x22, 0xbc, 0x01, 0x0a, 0x14, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x66, 0x66, 0x12, 0x4d, 0x0a, 0x0b, 0x6e, 0x65, + 0x77, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, + 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0a, 0x6e, + 0x65, 0x77, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x52, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x42, 0xf3, 0x01, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x15, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0xa1, 0x01, 0x0a, 0x0e, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x44, 0x0a, - 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, - 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x11, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x4e, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x22, 0x85, - 0x01, 0x0a, 0x09, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x12, 0x3e, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x38, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, - 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc2, 0x01, 0x0a, 0x10, 0x41, 0x73, 0x73, 0x6f, 0x63, - 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, - 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, - 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x3f, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x52, 0x07, - 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x65, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0e, 0x73, 0x65, 0x65, - 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0xbc, 0x01, 0x0a, 0x14, - 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x44, 0x69, 0x66, 0x66, 0x12, 0x4d, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x65, 0x77, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, - 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, - 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0e, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x42, 0xf3, 0x01, 0x0a, 0x1e, 0x63, - 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x10, 0x41, - 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, - 0x74, 0x70, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x64, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x73, 0x73, 0x6f, - 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x49, 0x41, 0xaa, 0x02, - 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x41, - 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xca, 0x02, 0x1a, 0x58, 0x6d, - 0x74, 0x70, 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x41, 0x73, 0x73, 0x6f, - 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xe2, 0x02, 0x26, 0x58, 0x6d, 0x74, 0x70, 0x5c, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0xea, 0x02, 0x1c, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x3a, 0x3a, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x6e, 0x73, 0x42, 0x10, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x64, 0x2f, 0x70, + 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa2, 0x02, + 0x03, 0x58, 0x49, 0x41, 0xaa, 0x02, 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x49, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x2e, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0xca, 0x02, 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x5c, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xe2, 0x02, + 0x26, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x41, + 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1c, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x3a, 0x3a, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/proto/openapi/mls_validation/v1/service.swagger.json b/pkg/proto/openapi/mls_validation/v1/service.swagger.json index e9d2bebd..d1bb324c 100644 --- a/pkg/proto/openapi/mls_validation/v1/service.swagger.json +++ b/pkg/proto/openapi/mls_validation/v1/service.swagger.json @@ -221,6 +221,10 @@ "clientTimestampNs": { "type": "string", "format": "uint64" + }, + "addedOnChainId": { + "type": "string", + "format": "uint64" } }, "title": "single member that optionally indicates the member that added them"