Skip to content

Commit 26b388d

Browse files
authored
Don't retry real MLS validation errors (#1602)
1 parent 5352fa2 commit 26b388d

File tree

1 file changed

+65
-2
lines changed

1 file changed

+65
-2
lines changed

pkg/indexer/app_chain/contracts/identity_update_storer.go

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"database/sql"
66
"errors"
77
"math"
8+
"strings"
89
"time"
910

1011
"github.com/ethereum/go-ethereum/common"
@@ -25,7 +26,26 @@ import (
2526
"google.golang.org/protobuf/proto"
2627
)
2728

28-
var (
29+
const (
30+
// https://github.com/xmtp/libxmtp/blob/main/crates/xmtp_id/src/associations/association_log.rs#L10
31+
associationErrorGeneric = "Error creating association"
32+
associationErrorMultipleCreate = "Multiple create operations detected"
33+
associationErrorNotCreated = "XID not yet created"
34+
associationErrorSignature = "Signature validation failed"
35+
associationErrorMemberNotAllowed = "not allowed to add"
36+
associationErrorMissingExistingMember = "Missing existing member"
37+
associationErrorLegacySignatureReuse = "Legacy key is only allowed to be associated using a legacy signature with nonce 0"
38+
associationErrorNewMemberIDSignatureMismatch = "The new member identifier does not match the signer"
39+
associationErrorWrongInboxID = "Wrong inbox_id specified on association"
40+
associationErrorSignatureNotAllowed = "Signature not allowed for role"
41+
associationErrorReplay = "Replay detected"
42+
associationErrorDeserialization = "Deserialization error"
43+
associationErrorMissingIdentityUpdate = "Missing identity update"
44+
associationErrorChainIDMismatch = "Wrong chain id."
45+
associationErrorInvalidAccountAddress = "Invalid account address: Must be 42 hex characters, starting with '0x'."
46+
associationErrorNotIdentifier = "are not a public identifier"
47+
associationErrorConvert = "Conversion error"
48+
2949
ErrAdvisoryLockSequence = "advisory lock failed"
3050
ErrParseIdentityUpdate = "error parsing identity update"
3151
ErrGetLatestSequenceID = "get latest sequence id failed"
@@ -34,6 +54,26 @@ var (
3454
ErrRevokeAddressFromLog = "revoke address from log failed"
3555
)
3656

57+
var associationErrorPatterns = []string{
58+
associationErrorGeneric,
59+
associationErrorMultipleCreate,
60+
associationErrorNotCreated,
61+
associationErrorSignature,
62+
associationErrorMemberNotAllowed,
63+
associationErrorMissingExistingMember,
64+
associationErrorLegacySignatureReuse,
65+
associationErrorNewMemberIDSignatureMismatch,
66+
associationErrorWrongInboxID,
67+
associationErrorSignatureNotAllowed,
68+
associationErrorReplay,
69+
associationErrorDeserialization,
70+
associationErrorMissingIdentityUpdate,
71+
associationErrorChainIDMismatch,
72+
associationErrorInvalidAccountAddress,
73+
associationErrorNotIdentifier,
74+
associationErrorConvert,
75+
}
76+
3777
type IdentityUpdateStorer struct {
3878
contract *iu.IdentityUpdateBroadcaster
3979
db *sql.DB
@@ -156,6 +196,7 @@ func (s *IdentityUpdateStorer) StoreLog(
156196

157197
inboxID := utils.HexEncode(msgSent.InboxId[:])
158198

199+
// TODO: Batch insert address log entries
159200
for _, newMember := range associationState.StateDiff.NewMembers {
160201
if s.logger.Core().Enabled(zap.DebugLevel) {
161202
s.logger.Debug("new member", utils.BodyField(newMember))
@@ -185,6 +226,7 @@ func (s *IdentityUpdateStorer) StoreLog(
185226
}
186227
}
187228

229+
// TODO: Batch revoke address log entries
188230
for _, removedMember := range associationState.StateDiff.RemovedMembers {
189231
if s.logger.Core().Enabled(zap.DebugLevel) {
190232
s.logger.Debug("removed member", utils.BodyField(removedMember))
@@ -325,7 +367,14 @@ func (s *IdentityUpdateStorer) validateIdentityUpdate(
325367
identityUpdate.IdentityUpdate,
326368
)
327369
if err != nil {
328-
return nil, re.NewRecoverableError(
370+
if shouldRetryValidationError(err) {
371+
return nil, re.NewRecoverableError(
372+
"could not get association state from envelopes",
373+
err,
374+
)
375+
}
376+
377+
return nil, re.NewNonRecoverableError(
329378
"could not get association state from envelopes",
330379
err,
331380
)
@@ -373,3 +422,17 @@ func buildSignedOriginatorEnvelope(
373422
},
374423
}, nil
375424
}
425+
426+
// shouldRetryValidationError returns true if the error is a validation error that should be retried.
427+
// Note: this approach is fragile as it depends on us creating new error messages for new validation errors.
428+
// This function should rely on gRPC error codes instead, but it's not possible at the moment.
429+
// Read https://github.com/xmtp/libxmtp/issues/3130
430+
func shouldRetryValidationError(err error) bool {
431+
errMsg := err.Error()
432+
for _, pattern := range associationErrorPatterns {
433+
if strings.Contains(errMsg, pattern) {
434+
return false
435+
}
436+
}
437+
return true
438+
}

0 commit comments

Comments
 (0)