diff --git a/pkg/api/message/publish_test.go b/pkg/api/message/publish_test.go index 740dcbed..3e8cc309 100644 --- a/pkg/api/message/publish_test.go +++ b/pkg/api/message/publish_test.go @@ -22,7 +22,10 @@ func TestPublishEnvelope(t *testing.T) { api, db, _, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() - payerEnvelope := envelopeTestUtils.CreatePayerEnvelope(t) + payerEnvelope := envelopeTestUtils.CreatePayerEnvelope( + t, + envelopeTestUtils.DefaultClientEnvelopeNodeId, + ) resp, err := api.PublishPayerEnvelopes( context.Background(), @@ -70,7 +73,10 @@ func TestUnmarshalErrorOnPublish(t *testing.T) { api, _, _, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() - envelope := envelopeTestUtils.CreatePayerEnvelope(t) + envelope := envelopeTestUtils.CreatePayerEnvelope( + t, + envelopeTestUtils.DefaultClientEnvelopeNodeId, + ) envelope.UnsignedClientEnvelope = []byte("invalidbytes") _, err := api.PublishPayerEnvelopes( context.Background(), @@ -81,19 +87,42 @@ func TestUnmarshalErrorOnPublish(t *testing.T) { require.ErrorContains(t, err, "invalid wire-format data") } -func TestMismatchingOriginatorOnPublish(t *testing.T) { +func TestMismatchingAADOriginatorOnPublishNoLongerFails(t *testing.T) { api, _, _, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() + nid := envelopeTestUtils.DefaultClientEnvelopeNodeId + 100 + clientEnv := envelopeTestUtils.CreateClientEnvelope() - nodeId := uint32(2) // nolint:staticcheck - clientEnv.Aad.TargetOriginator = &nodeId + clientEnv.Aad.TargetOriginator = &nid + _, err := api.PublishPayerEnvelopes( + context.Background(), + &message_api.PublishPayerEnvelopesRequest{ + PayerEnvelopes: []*envelopes.PayerEnvelope{ + envelopeTestUtils.CreatePayerEnvelope( + t, + envelopeTestUtils.DefaultClientEnvelopeNodeId, + clientEnv, + ), + }, + }, + ) + require.NoError(t, err) +} + +func TestMismatchingOriginatorOnPublish(t *testing.T) { + api, _, _, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) + defer cleanup() + + nid := envelopeTestUtils.DefaultClientEnvelopeNodeId + 100 + + clientEnv := envelopeTestUtils.CreateClientEnvelope() _, err := api.PublishPayerEnvelopes( context.Background(), &message_api.PublishPayerEnvelopesRequest{ PayerEnvelopes: []*envelopes.PayerEnvelope{ - envelopeTestUtils.CreatePayerEnvelope(t, clientEnv), + envelopeTestUtils.CreatePayerEnvelope(t, nid, clientEnv), }, }, ) @@ -110,7 +139,11 @@ func TestMissingTopicOnPublish(t *testing.T) { context.Background(), &message_api.PublishPayerEnvelopesRequest{ PayerEnvelopes: []*envelopes.PayerEnvelope{ - envelopeTestUtils.CreatePayerEnvelope(t, clientEnv), + envelopeTestUtils.CreatePayerEnvelope( + t, + envelopeTestUtils.DefaultClientEnvelopeNodeId, + clientEnv, + ), }, }, ) @@ -120,11 +153,12 @@ func TestMissingTopicOnPublish(t *testing.T) { func TestKeyPackageValidationSuccess(t *testing.T) { api, _, apiMocks, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() - nodeId := uint32(100) + + nid := envelopeTestUtils.DefaultClientEnvelopeNodeId clientEnv := envelopeTestUtils.CreateClientEnvelope(&envelopes.AuthenticatedData{ TargetTopic: topic.NewTopic(topic.TOPIC_KIND_KEY_PACKAGES_V1, []byte{1, 2, 3}).Bytes(), - TargetOriginator: &nodeId, + TargetOriginator: &nid, DependsOn: &envelopes.Cursor{}, }) clientEnv.Payload = &envelopes.ClientEnvelope_UploadKeyPackage{ @@ -150,7 +184,11 @@ func TestKeyPackageValidationSuccess(t *testing.T) { context.Background(), &message_api.PublishPayerEnvelopesRequest{ PayerEnvelopes: []*envelopes.PayerEnvelope{ - envelopeTestUtils.CreatePayerEnvelope(t, clientEnv), + envelopeTestUtils.CreatePayerEnvelope( + t, + envelopeTestUtils.DefaultClientEnvelopeNodeId, + clientEnv, + ), }, }, ) @@ -160,11 +198,12 @@ func TestKeyPackageValidationSuccess(t *testing.T) { func TestKeyPackageValidationFail(t *testing.T) { api, _, apiMocks, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() - nodeId := uint32(100) + + nid := envelopeTestUtils.DefaultClientEnvelopeNodeId clientEnv := envelopeTestUtils.CreateClientEnvelope(&envelopes.AuthenticatedData{ TargetTopic: topic.NewTopic(topic.TOPIC_KIND_KEY_PACKAGES_V1, []byte{1, 2, 3}).Bytes(), - TargetOriginator: &nodeId, + TargetOriginator: &nid, DependsOn: &envelopes.Cursor{}, }) clientEnv.Payload = &envelopes.ClientEnvelope_UploadKeyPackage{ @@ -190,7 +229,7 @@ func TestKeyPackageValidationFail(t *testing.T) { context.Background(), &message_api.PublishPayerEnvelopesRequest{ PayerEnvelopes: []*envelopes.PayerEnvelope{ - envelopeTestUtils.CreatePayerEnvelope(t, clientEnv), + envelopeTestUtils.CreatePayerEnvelope(t, nid, clientEnv), }, }, ) @@ -201,11 +240,16 @@ func TestPublishEnvelopeBlockchainCursorAhead(t *testing.T) { api, _, _, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() - err := publishPayerEnvelopeWithNodeIDAndCursor(t, api, 100, &envelopes.Cursor{ - NodeIdToSequenceId: map[uint32]uint64{ - 1: 105, + err := publishPayerEnvelopeWithNodeIDAndCursor( + t, + api, + envelopeTestUtils.DefaultClientEnvelopeNodeId, + &envelopes.Cursor{ + NodeIdToSequenceId: map[uint32]uint64{ + 1: 105, + }, }, - }) + ) require.Error(t, err) require.Contains(t, err.Error(), "DependsOn has not been seen by this node") } @@ -220,7 +264,7 @@ func publishPayerEnvelopeWithNodeIDAndCursor( context.Background(), &message_api.PublishPayerEnvelopesRequest{ PayerEnvelopes: []*envelopes.PayerEnvelope{envelopeTestUtils.CreatePayerEnvelope( - t, + t, nodeId, envelopeTestUtils.CreateClientEnvelope(&envelopes.AuthenticatedData{ TargetOriginator: &nodeId, TargetTopic: targetTopic, @@ -237,11 +281,16 @@ func TestPublishEnvelopeOriginatorUnknown(t *testing.T) { api, _, _, cleanup := apiTestUtils.NewTestReplicationAPIClient(t) defer cleanup() - err := publishPayerEnvelopeWithNodeIDAndCursor(t, api, 100, &envelopes.Cursor{ - NodeIdToSequenceId: map[uint32]uint64{ - 1600: 1, + err := publishPayerEnvelopeWithNodeIDAndCursor( + t, + api, + envelopeTestUtils.DefaultClientEnvelopeNodeId, + &envelopes.Cursor{ + NodeIdToSequenceId: map[uint32]uint64{ + 1600: 1, + }, }, - }) + ) require.Error(t, err) require.Contains(t, err.Error(), "DependsOn has not been seen by this node") } diff --git a/pkg/api/message/service.go b/pkg/api/message/service.go index 64a2c331..aabefefb 100644 --- a/pkg/api/message/service.go +++ b/pkg/api/message/service.go @@ -407,6 +407,14 @@ func (s *Service) validatePayerEnvelope( return nil, err } + if payerEnv.TargetOriginator != s.registrant.NodeID() { + return nil, status.Errorf(codes.InvalidArgument, "invalid target originator") + } + + if _, err = payerEnv.RecoverSigner(); err != nil { + return nil, err + } + if err := s.validateClientInfo(&payerEnv.ClientEnvelope); err != nil { return nil, err } @@ -444,10 +452,6 @@ func (s *Service) validateKeyPackage( func (s *Service) validateClientInfo(clientEnv *envelopes.ClientEnvelope) error { aad := clientEnv.Aad() - // nolint:staticcheck - if aad.GetTargetOriginator() != s.registrant.NodeID() { - return status.Errorf(codes.InvalidArgument, "invalid target originator") - } if !clientEnv.TopicMatchesPayload() { return status.Errorf(codes.InvalidArgument, "topic does not match payload") diff --git a/pkg/api/payer/nodeSelector.go b/pkg/api/payer/nodeSelector.go index 043eb05f..29f8d793 100644 --- a/pkg/api/payer/nodeSelector.go +++ b/pkg/api/payer/nodeSelector.go @@ -10,7 +10,7 @@ import ( ) type NodeSelectorAlgorithm interface { - GetNode(topic topic.Topic) (uint32, error) + GetNode(topic topic.Topic, banlist ...[]uint32) (uint32, error) } type StableHashingNodeSelectorAlgorithm struct { @@ -30,7 +30,10 @@ func HashKey(topic topic.Topic) uint32 { } // GetNode selects a node for a given topic using stable hashing -func (s *StableHashingNodeSelectorAlgorithm) GetNode(topic topic.Topic) (uint32, error) { +func (s *StableHashingNodeSelectorAlgorithm) GetNode( + topic topic.Topic, + banlist ...[]uint32, +) (uint32, error) { nodes, err := s.reg.GetNodes() if err != nil { return 0, err @@ -60,5 +63,23 @@ func (s *StableHashingNodeSelectorAlgorithm) GetNode(topic topic.Topic) (uint32, return topicHash < nodeLocations[i] }) - return nodes[idx%len(nodeLocations)].NodeID, nil + // Flatten banlist + banned := make(map[uint32]struct{}) + for _, list := range banlist { + for _, id := range list { + banned[id] = struct{}{} + } + } + + // Find the next available node + for i := 0; i < len(nodes); i++ { + candidateIdx := (idx + i) % len(nodeLocations) + candidateNodeID := nodes[candidateIdx].NodeID + + if _, exists := banned[candidateNodeID]; !exists { + return candidateNodeID, nil + } + } + + return 0, errors.New("no available nodes after considering banlist") } diff --git a/pkg/api/payer/nodeSelector_test.go b/pkg/api/payer/nodeSelector_test.go index 2cabdf69..3a397924 100644 --- a/pkg/api/payer/nodeSelector_test.go +++ b/pkg/api/payer/nodeSelector_test.go @@ -226,3 +226,40 @@ func TestGetNode_ConfirmTopicBalance(t *testing.T) { } } + +func TestGetNode_NodeGetNextIfBanned(t *testing.T) { + mockRegistry := mocks.NewMockNodeRegistry(t) + mockRegistry.On("GetNodes").Return([]registry.Node{ + {NodeID: 100}, + {NodeID: 200}, + {NodeID: 300}, + }, nil) + tpc1 := *topic.NewTopic(topic.TOPIC_KIND_IDENTITY_UPDATES_V1, []byte("stable_key")) + + selector := payer.NewStableHashingNodeSelectorAlgorithm(mockRegistry) + + node1, err := selector.GetNode(tpc1) + require.NoError(t, err) + require.EqualValues(t, 200, node1) + + banlist := []uint32{node1} + + reselectedNode, err := selector.GetNode(tpc1, banlist) + require.NoError(t, err) + require.NotEqualValues(t, node1, reselectedNode) + require.EqualValues(t, 300, reselectedNode) + + banlist = append(banlist, reselectedNode) + + reselectedNode, err = selector.GetNode(tpc1, banlist) + require.NoError(t, err) + require.NotEqualValues(t, node1, reselectedNode) + require.EqualValues(t, 100, reselectedNode) + + banlist = append(banlist, reselectedNode) + + // now we are out of nodes to try + reselectedNode, err = selector.GetNode(tpc1, banlist) + require.Error(t, err) + require.EqualValues(t, 0, reselectedNode) +} diff --git a/pkg/api/payer/publish_test.go b/pkg/api/payer/publish_test.go index 82f69c09..3373db2a 100644 --- a/pkg/api/payer/publish_test.go +++ b/pkg/api/payer/publish_test.go @@ -181,11 +181,14 @@ func TestPublishToNodes(t *testing.T) { HttpAddress: formatAddress(originatorServer.Addr().String()), }, nil) + mockRegistry.On("GetNodes").Return([]registry.Node{ + {NodeID: 100}, + }, 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( @@ -203,6 +206,8 @@ func TestPublishToNodes(t *testing.T) { require.NoError(t, err) targetTopic := parsedOriginatorEnvelope.UnsignedOriginatorEnvelope.PayerEnvelope.ClientEnvelope.TargetTopic() - require.Equal(t, targetTopic.Identifier(), groupId[:]) + + targetOriginator := parsedOriginatorEnvelope.UnsignedOriginatorEnvelope.PayerEnvelope.TargetOriginator + require.EqualValues(t, 100, targetOriginator) } diff --git a/pkg/api/payer/service.go b/pkg/api/payer/service.go index 4d9eca0d..92f84cd3 100644 --- a/pkg/api/payer/service.go +++ b/pkg/api/payer/service.go @@ -76,7 +76,7 @@ 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) + originatorEnvelopes, err := s.publishToNodeWithRetry(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") @@ -165,6 +165,42 @@ func (s *Service) groupEnvelopes( return &out, nil } +func (s *Service) publishToNodeWithRetry( + ctx context.Context, + originatorID uint32, + indexedEnvelopes []clientEnvelopeWithIndex, +) ([]*envelopesProto.OriginatorEnvelope, error) { + var banlist []uint32 + var result []*envelopesProto.OriginatorEnvelope + var err error + var nodeID = originatorID + + topic := indexedEnvelopes[0].payload.TargetTopic() + + for retries := 0; retries < 5; retries++ { + result, err = s.publishToNodes(ctx, nodeID, indexedEnvelopes) + if err == nil { + return result, nil + } + + s.log.Error( + "error publishing to node. Retrying with the next one", + zap.Uint32("failed_node", nodeID), + zap.Error(err), + ) + + // Add failed node to banlist and retry + banlist = append(banlist, nodeID) + + nodeID, err = s.nodeSelector.GetNode(topic, banlist) + if err != nil { + return nil, err + } + } + + return nil, err +} + func (s *Service) publishToNodes( ctx context.Context, originatorID uint32, @@ -177,7 +213,7 @@ func (s *Service) publishToNodes( } client := message_api.NewReplicationApiClient(conn) - payerEnvelopes, err := s.signAllClientEnvelopes(indexedEnvelopes) + payerEnvelopes, err := s.signAllClientEnvelopes(originatorID, indexedEnvelopes) if err != nil { return nil, status.Errorf(codes.Internal, "error signing payer envelopes: %v", err) } @@ -199,7 +235,7 @@ func (s *Service) publishToBlockchain( targetTopic := clientEnvelope.TargetTopic() identifier := targetTopic.Identifier() desiredOriginatorId := uint32(1) //TODO: determine this from the chain - desiredSequenceId := uint64(0) + var desiredSequenceId uint64 kind := targetTopic.Kind() // Get the group ID as [32]byte @@ -296,7 +332,10 @@ func (s *Service) publishToBlockchain( desiredSequenceId, ) if err != nil { - return nil, err + s.log.Error( + "Chosen node for cursor check is unreachable", + zap.Uint32("targetNodeId", targetNodeId), + ) } return &envelopesProto.OriginatorEnvelope{ @@ -324,12 +363,12 @@ func buildUnsignedOriginatorEnvelopeFromChain( } } -func (s *Service) signAllClientEnvelopes( +func (s *Service) signAllClientEnvelopes(originatorID uint32, indexedEnvelopes []clientEnvelopeWithIndex, ) ([]*envelopesProto.PayerEnvelope, error) { out := make([]*envelopesProto.PayerEnvelope, len(indexedEnvelopes)) for i, indexedEnvelope := range indexedEnvelopes { - envelope, err := s.signClientEnvelope(indexedEnvelope.payload) + envelope, err := s.signClientEnvelope(originatorID, indexedEnvelope.payload) if err != nil { return nil, err } @@ -338,7 +377,7 @@ func (s *Service) signAllClientEnvelopes( return out, nil } -func (s *Service) signClientEnvelope( +func (s *Service) signClientEnvelope(originatorID uint32, clientEnvelope *envelopes.ClientEnvelope, ) (*envelopesProto.PayerEnvelope, error) { envelopeBytes, err := clientEnvelope.Bytes() @@ -346,7 +385,7 @@ func (s *Service) signClientEnvelope( return nil, err } - payerSignature, err := utils.SignClientEnvelope(envelopeBytes, s.payerPrivateKey) + payerSignature, err := utils.SignClientEnvelope(originatorID, envelopeBytes, s.payerPrivateKey) if err != nil { return nil, err } @@ -356,6 +395,7 @@ func (s *Service) signClientEnvelope( PayerSignature: &associations.RecoverableEcdsaSignature{ Bytes: payerSignature, }, + TargetOriginator: originatorID, }, nil } diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index ce6d5df2..46d881ec 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -3,6 +3,7 @@ package constants const ( JWT_DOMAIN_SEPARATION_LABEL = "jwt|" PAYER_DOMAIN_SEPARATION_LABEL = "payer|" + TARGET_ORIGINATOR_SEPARATION_LABEL = "target|" ORIGINATOR_DOMAIN_SEPARATION_LABEL = "originator|" NODE_AUTHORIZATION_HEADER_NAME = "node-authorization" MAX_BLOCKCHAIN_ORIGINATOR_ID = 100 diff --git a/pkg/envelopes/envelopes_test.go b/pkg/envelopes/envelopes_test.go index 9d7a7711..99844171 100644 --- a/pkg/envelopes/envelopes_test.go +++ b/pkg/envelopes/envelopes_test.go @@ -19,7 +19,7 @@ func TestValidOriginatorEnvelope(t *testing.T) { originatorSequenceId := uint64(1) clientEnv := envelopeTestUtils.CreateClientEnvelope() - payerEnvelope := envelopeTestUtils.CreatePayerEnvelope(t, clientEnv) + payerEnvelope := envelopeTestUtils.CreatePayerEnvelope(t, originatorNodeId, clientEnv) originatorEnvelope := envelopeTestUtils.CreateOriginatorEnvelope( t, originatorNodeId, @@ -48,7 +48,7 @@ func TestSerialize(t *testing.T) { originatorSequenceId := uint64(1) clientEnv := envelopeTestUtils.CreateClientEnvelope() - payerEnvelope := envelopeTestUtils.CreatePayerEnvelope(t, clientEnv) + payerEnvelope := envelopeTestUtils.CreatePayerEnvelope(t, originatorNodeId, clientEnv) originatorEnvelope := envelopeTestUtils.CreateOriginatorEnvelope( t, originatorNodeId, @@ -138,10 +138,12 @@ func TestPayloadType(t *testing.T) { } func TestRecoverSigner(t *testing.T) { + nodeId := envelopeTestUtils.DefaultClientEnvelopeNodeId payerPrivateKey := testutils.RandomPrivateKey(t) - rawPayerEnv := envelopeTestUtils.CreatePayerEnvelope(t) + rawPayerEnv := envelopeTestUtils.CreatePayerEnvelope(t, nodeId) payerSignature, err := utils.SignClientEnvelope( + nodeId, rawPayerEnv.UnsignedClientEnvelope, payerPrivateKey, ) @@ -159,6 +161,7 @@ func TestRecoverSigner(t *testing.T) { // Now test with an incorrect signature wrongPayerSignature, err := utils.SignClientEnvelope( + nodeId, testutils.RandomBytes(128), payerPrivateKey, ) diff --git a/pkg/envelopes/payer.go b/pkg/envelopes/payer.go index 13cf638f..83125a25 100644 --- a/pkg/envelopes/payer.go +++ b/pkg/envelopes/payer.go @@ -12,8 +12,9 @@ import ( ) type PayerEnvelope struct { - proto *envelopesProto.PayerEnvelope - ClientEnvelope ClientEnvelope + proto *envelopesProto.PayerEnvelope + ClientEnvelope ClientEnvelope + TargetOriginator uint32 } func NewPayerEnvelope(proto *envelopesProto.PayerEnvelope) (*PayerEnvelope, error) { @@ -25,7 +26,11 @@ func NewPayerEnvelope(proto *envelopesProto.PayerEnvelope) (*PayerEnvelope, erro if err != nil { return nil, err } - return &PayerEnvelope{proto: proto, ClientEnvelope: *clientEnv}, nil + return &PayerEnvelope{ + proto: proto, + ClientEnvelope: *clientEnv, + TargetOriginator: proto.GetTargetOriginator(), + }, nil } func (p *PayerEnvelope) Proto() *envelopesProto.PayerEnvelope { @@ -46,7 +51,7 @@ func (p *PayerEnvelope) RecoverSigner() (*common.Address, error) { return nil, errors.New("payer signature is missing") } - hash := utils.HashPayerSignatureInput(p.proto.UnsignedClientEnvelope) + hash := utils.HashPayerSignatureInput(p.proto.TargetOriginator, p.proto.UnsignedClientEnvelope) signer, err := ethcrypto.SigToPub(hash, payerSignature.Bytes) if err != nil { return nil, err diff --git a/pkg/indexer/e2e_test.go b/pkg/indexer/e2e_test.go index 2e4232d4..e4739c18 100644 --- a/pkg/indexer/e2e_test.go +++ b/pkg/indexer/e2e_test.go @@ -62,9 +62,9 @@ func TestStoreMessages(t *testing.T) { message := testutils.RandomBytes(78) groupID := testutils.RandomGroupID() - topic := topic.NewTopic(topic.TOPIC_KIND_GROUP_MESSAGES_V1, groupID[:]).Bytes() + msgTopic := topic.NewTopic(topic.TOPIC_KIND_GROUP_MESSAGES_V1, groupID[:]).Bytes() - clientEnvelope := envelopesTestUtils.CreateGroupMessageClientEnvelope(groupID, message, 0) + clientEnvelope := envelopesTestUtils.CreateGroupMessageClientEnvelope(groupID, message) clientEnvelopeBytes, err := proto.Marshal(clientEnvelope) require.NoError(t, err) @@ -77,7 +77,7 @@ func TestStoreMessages(t *testing.T) { results, err := querier.SelectGatewayEnvelopes( context.Background(), queries.SelectGatewayEnvelopesParams{ - Topics: [][]byte{topic}, + Topics: [][]byte{msgTopic}, }, ) require.NoError(t, err) @@ -91,7 +91,7 @@ func TestStoreMessages(t *testing.T) { firstEnvelope.OriginatorEnvelope, ) require.NoError(t, err) - require.Equal(t, firstEnvelope.Topic, topic) + require.Equal(t, firstEnvelope.Topic, msgTopic) return true }, 5*time.Second, 100*time.Millisecond, "Failed to find indexed envelope") diff --git a/pkg/indexer/storer/groupMessage_test.go b/pkg/indexer/storer/groupMessage_test.go index 6e82ef6a..f164eae5 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, 0) + clientEnvelope := envelopesTestUtils.CreateGroupMessageClientEnvelope(groupID, message) 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, 0) + clientEnvelope := envelopesTestUtils.CreateGroupMessageClientEnvelope(groupID, message) logMessage := testutils.BuildMessageSentLog(t, groupID, clientEnvelope, sequenceID) diff --git a/pkg/proto/openapi/xmtpv4/message_api/message_api.swagger.json b/pkg/proto/openapi/xmtpv4/message_api/message_api.swagger.json index 9e15df25..1b29f962 100644 --- a/pkg/proto/openapi/xmtpv4/message_api/message_api.swagger.json +++ b/pkg/proto/openapi/xmtpv4/message_api/message_api.swagger.json @@ -203,6 +203,10 @@ }, "payerSignature": { "$ref": "#/definitions/associationsRecoverableEcdsaSignature" + }, + "targetOriginator": { + "type": "integer", + "format": "int64" } }, "title": "Wraps client envelope with payer signature" diff --git a/pkg/proto/openapi/xmtpv4/message_api/misbehavior_api.swagger.json b/pkg/proto/openapi/xmtpv4/message_api/misbehavior_api.swagger.json index f05c70ab..aa1f2d7e 100644 --- a/pkg/proto/openapi/xmtpv4/message_api/misbehavior_api.swagger.json +++ b/pkg/proto/openapi/xmtpv4/message_api/misbehavior_api.swagger.json @@ -130,6 +130,10 @@ }, "payerSignature": { "$ref": "#/definitions/associationsRecoverableEcdsaSignature" + }, + "targetOriginator": { + "type": "integer", + "format": "int64" } }, "title": "Wraps client envelope with payer signature" diff --git a/pkg/proto/xmtpv4/envelopes/envelopes.pb.go b/pkg/proto/xmtpv4/envelopes/envelopes.pb.go index 9b9e24ad..04a10881 100644 --- a/pkg/proto/xmtpv4/envelopes/envelopes.pb.go +++ b/pkg/proto/xmtpv4/envelopes/envelopes.pb.go @@ -268,6 +268,7 @@ type PayerEnvelope struct { state protoimpl.MessageState `protogen:"open.v1"` UnsignedClientEnvelope []byte `protobuf:"bytes,1,opt,name=unsigned_client_envelope,json=unsignedClientEnvelope,proto3" json:"unsigned_client_envelope,omitempty"` // Protobuf serialized PayerSignature *associations.RecoverableEcdsaSignature `protobuf:"bytes,2,opt,name=payer_signature,json=payerSignature,proto3" json:"payer_signature,omitempty"` + TargetOriginator uint32 `protobuf:"varint,3,opt,name=target_originator,json=targetOriginator,proto3" json:"target_originator,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -316,6 +317,13 @@ func (x *PayerEnvelope) GetPayerSignature() *associations.RecoverableEcdsaSignat return nil } +func (x *PayerEnvelope) GetTargetOriginator() uint32 { + if x != nil { + return x.TargetOriginator + } + return 0 +} + // For blockchain envelopes, these fields are set by the smart contract type UnsignedOriginatorEnvelope struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -586,7 +594,7 @@ var file_xmtpv4_envelopes_envelopes_proto_rawDesc = string([]byte{ 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x22, 0xa9, 0x01, 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, 0x76, + 0x6f, 0x61, 0x64, 0x22, 0xd6, 0x01, 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x38, 0x0a, 0x18, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x16, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, @@ -596,59 +604,61 @@ var file_xmtpv4_envelopes_envelopes_proto_rawDesc = string([]byte{ 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x0e, 0x70, 0x61, 0x79, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, - 0xf2, 0x01, 0x0a, 0x1a, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, - 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x2c, - 0x0a, 0x12, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6e, 0x6f, 0x64, - 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x6f, 0x72, 0x69, 0x67, - 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x16, - 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, - 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x6f, 0x72, - 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, - 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, - 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x4e, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x61, 0x79, 0x65, 0x72, - 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x24, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x65, 0x6e, - 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x50, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, 0x76, - 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, 0x76, 0x65, - 0x6c, 0x6f, 0x70, 0x65, 0x22, 0x3c, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x61, - 0x73, 0x68, 0x22, 0xa0, 0x02, 0x0a, 0x12, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, - 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x40, 0x0a, 0x1c, 0x75, 0x6e, 0x73, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, - 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x1a, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, - 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x6a, 0x0a, 0x14, 0x6f, - 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 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, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, - 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x48, 0x00, 0x52, 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, - 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x48, 0x00, 0x52, 0x0f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x07, 0x0a, 0x05, - 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0xd3, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, - 0x70, 0x65, 0x73, 0x42, 0x0e, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 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, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2f, 0x65, 0x6e, - 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x58, 0x45, 0xaa, 0x02, 0x15, - 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x45, 0x6e, 0x76, 0x65, - 0x6c, 0x6f, 0x70, 0x65, 0x73, 0xca, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x58, 0x6d, 0x74, - 0x70, 0x76, 0x34, 0x5c, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0xe2, 0x02, 0x21, - 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x5c, 0x45, 0x6e, 0x76, 0x65, - 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0xea, 0x02, 0x17, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, - 0x3a, 0x3a, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x0e, 0x70, 0x61, 0x79, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, + 0x2b, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, + 0x61, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x22, 0xf2, 0x01, 0x0a, + 0x1a, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x6f, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x16, 0x6f, 0x72, 0x69, + 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x6f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, + 0x23, 0x0a, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6e, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, + 0x6f, 0x72, 0x4e, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x65, 0x6e, + 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x65, 0x6e, 0x76, 0x65, 0x6c, + 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x50, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, + 0x70, 0x65, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x65, 0x22, 0x3c, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, + 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x22, + 0xa0, 0x02, 0x0a, 0x12, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, + 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x40, 0x0a, 0x1c, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x65, 0x6e, + 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x1a, 0x75, 0x6e, + 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, + 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x6a, 0x0a, 0x14, 0x6f, 0x72, 0x69, 0x67, + 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 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, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, + 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x48, 0x00, 0x52, + 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x65, 0x6e, 0x76, + 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x48, 0x00, 0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x07, 0x0a, 0x05, 0x70, 0x72, 0x6f, + 0x6f, 0x66, 0x42, 0xd3, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, + 0x42, 0x0e, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x30, 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, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2f, 0x65, 0x6e, 0x76, 0x65, 0x6c, + 0x6f, 0x70, 0x65, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x58, 0x45, 0xaa, 0x02, 0x15, 0x58, 0x6d, 0x74, + 0x70, 0x2e, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x65, 0x73, 0xca, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, + 0x5c, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0xe2, 0x02, 0x21, 0x58, 0x6d, 0x74, + 0x70, 0x5c, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x5c, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x65, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x17, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x3a, 0x3a, 0x45, + 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go index 41aab841..aac1b60a 100644 --- a/pkg/server/server_test.go +++ b/pkg/server/server_test.go @@ -154,6 +154,7 @@ func TestCreateServer(t *testing.T) { &message_api.PublishPayerEnvelopesRequest{ PayerEnvelopes: []*envelopes.PayerEnvelope{envelopeTestUtils.CreatePayerEnvelope( t, + nodeId1, envelopeTestUtils.CreateClientEnvelope(&envelopes.AuthenticatedData{ TargetOriginator: &nodeId1, TargetTopic: targetTopic, @@ -168,6 +169,7 @@ func TestCreateServer(t *testing.T) { &message_api.PublishPayerEnvelopesRequest{ PayerEnvelopes: []*envelopes.PayerEnvelope{envelopeTestUtils.CreatePayerEnvelope( t, + nodeId2, envelopeTestUtils.CreateClientEnvelope(&envelopes.AuthenticatedData{ TargetOriginator: &nodeId2, TargetTopic: targetTopic, @@ -259,10 +261,10 @@ func TestReadOwnWritesGuarantee(t *testing.T) { &message_api.PublishPayerEnvelopesRequest{ PayerEnvelopes: []*envelopes.PayerEnvelope{envelopeTestUtils.CreatePayerEnvelope( t, + nodeId1, envelopeTestUtils.CreateClientEnvelope(&envelopes.AuthenticatedData{ - TargetOriginator: &nodeId1, - TargetTopic: targetTopic, - DependsOn: &envelopes.Cursor{}, + TargetTopic: targetTopic, + DependsOn: &envelopes.Cursor{}, }), )}, }, diff --git a/pkg/testutils/envelopes/envelopes.go b/pkg/testutils/envelopes/envelopes.go index 810652b6..71eafa2a 100644 --- a/pkg/testutils/envelopes/envelopes.go +++ b/pkg/testutils/envelopes/envelopes.go @@ -1,6 +1,8 @@ package testutils import ( + "github.com/ethereum/go-ethereum/crypto" + "github.com/xmtp/xmtpd/pkg/utils" "testing" "github.com/stretchr/testify/require" @@ -11,6 +13,8 @@ import ( "google.golang.org/protobuf/proto" ) +const DefaultClientEnvelopeNodeId = uint32(100) + func UnmarshalUnsignedOriginatorEnvelope( t *testing.T, bytes []byte, @@ -25,7 +29,7 @@ func UnmarshalUnsignedOriginatorEnvelope( } func CreateClientEnvelope(aad ...*envelopes.AuthenticatedData) *envelopes.ClientEnvelope { - nodeId := uint32(100) + nodeId := DefaultClientEnvelopeNodeId if len(aad) == 0 { aad = append(aad, &envelopes.AuthenticatedData{ TargetOriginator: &nodeId, @@ -43,13 +47,11 @@ 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: &targetOriginator, }, Payload: &envelopes.ClientEnvelope_GroupMessage{ GroupMessage: &mlsv1.GroupMessageInput{ @@ -81,6 +83,7 @@ func CreateIdentityUpdateClientEnvelope( func CreatePayerEnvelope( t *testing.T, + nodeID uint32, clientEnv ...*envelopes.ClientEnvelope, ) *envelopes.PayerEnvelope { if len(clientEnv) == 0 { @@ -89,9 +92,18 @@ func CreatePayerEnvelope( clientEnvBytes, err := proto.Marshal(clientEnv[0]) require.NoError(t, err) + key, err := crypto.GenerateKey() + require.NoError(t, err) + + payerSignature, err := utils.SignClientEnvelope(nodeID, clientEnvBytes, key) + require.NoError(t, err) + return &envelopes.PayerEnvelope{ UnsignedClientEnvelope: clientEnvBytes, - PayerSignature: &associations.RecoverableEcdsaSignature{}, + PayerSignature: &associations.RecoverableEcdsaSignature{ + Bytes: payerSignature, + }, + TargetOriginator: nodeID, } } @@ -102,7 +114,7 @@ func CreateOriginatorEnvelope( payerEnv ...*envelopes.PayerEnvelope, ) *envelopes.OriginatorEnvelope { if len(payerEnv) == 0 { - payerEnv = append(payerEnv, CreatePayerEnvelope(t)) + payerEnv = append(payerEnv, CreatePayerEnvelope(t, originatorNodeID)) } unsignedEnv := &envelopes.UnsignedOriginatorEnvelope{ @@ -127,7 +139,7 @@ func CreateOriginatorEnvelopeWithTopic( originatorSequenceID uint64, topic []byte, ) *envelopes.OriginatorEnvelope { - payerEnv := CreatePayerEnvelope(t, CreateClientEnvelope( + payerEnv := CreatePayerEnvelope(t, originatorNodeID, CreateClientEnvelope( &envelopes.AuthenticatedData{ TargetTopic: topic, TargetOriginator: &originatorNodeID, diff --git a/pkg/utils/hash.go b/pkg/utils/hash.go index 75d0886b..bc6fc396 100644 --- a/pkg/utils/hash.go +++ b/pkg/utils/hash.go @@ -1,12 +1,17 @@ package utils import ( + "encoding/binary" ethcrypto "github.com/ethereum/go-ethereum/crypto" "github.com/xmtp/xmtpd/pkg/constants" ) -func HashPayerSignatureInput(unsignedClientEnvelope []byte) []byte { +func HashPayerSignatureInput(originatorID uint32, unsignedClientEnvelope []byte) []byte { + targetBytes := make([]byte, 4) + binary.BigEndian.PutUint32(targetBytes, originatorID) return ethcrypto.Keccak256( + []byte(constants.TARGET_ORIGINATOR_SEPARATION_LABEL), + targetBytes, []byte(constants.PAYER_DOMAIN_SEPARATION_LABEL), unsignedClientEnvelope, ) diff --git a/pkg/utils/signature.go b/pkg/utils/signature.go index f4dc1360..5b072d01 100644 --- a/pkg/utils/signature.go +++ b/pkg/utils/signature.go @@ -7,10 +7,11 @@ import ( ) func SignClientEnvelope( + originatorID uint32, unsignedClientEnvelope []byte, payerPrivateKey *ecdsa.PrivateKey, ) ([]byte, error) { - hash := HashPayerSignatureInput(unsignedClientEnvelope) + hash := HashPayerSignatureInput(originatorID, unsignedClientEnvelope) signature, err := ethcrypto.Sign(hash, payerPrivateKey) if err != nil { return nil, err