From 629def9bab406f1c5e6d2f92ed08ec8771860c3d Mon Sep 17 00:00:00 2001 From: Oleh Lomaka Date: Mon, 14 Oct 2024 04:42:39 -0400 Subject: [PATCH] New error codes for credential status check (#83) --- caching_rev_status_resolver.go | 13 +- caching_rev_status_resolver_test.go | 2 +- cmd/polygonid/polygonid.go | 201 ++++++++++++---------- errors.go | 82 +++++++++ examples/testdata/auth_v2_inputs_out.json | 180 ++++++++++++++++++- inputs_sig.go | 45 +++-- inputs_sig_test.go | 6 +- 7 files changed, 416 insertions(+), 113 deletions(-) create mode 100644 errors.go diff --git a/caching_rev_status_resolver.go b/caching_rev_status_resolver.go index 056a29a..53f19d2 100644 --- a/caching_rev_status_resolver.go +++ b/caching_rev_status_resolver.go @@ -17,6 +17,14 @@ import ( "github.com/iden3/iden3comm/v2/resolvers" ) +type CredentialStatusOwner uint8 + +const ( + CredentialStatusOwnerUnset CredentialStatusOwner = iota + CredentialStatusOwnerIssuer CredentialStatusOwner = iota + CredentialStatusOwnerUser CredentialStatusOwner = iota +) + var revStatusCacheMutex sync.RWMutex const issuerStateTTL = 5 * time.Minute @@ -99,15 +107,14 @@ func resolveRevStatus(ctx context.Context, chainCfg PerChainConfig, if regBuilder == nil { return verifiable.RevocationStatus{}, - errors.New("registry builder is null") + errors.New("[assertion] registry builder is null") } if userDID == nil { return verifiable.RevocationStatus{}, errors.New("user DID is null") } - resolversRegistry, registryCleanupFn, err := regBuilder(ctx, - chainCfg) + resolversRegistry, registryCleanupFn, err := regBuilder(ctx, chainCfg) if err != nil { return verifiable.RevocationStatus{}, err } diff --git a/caching_rev_status_resolver_test.go b/caching_rev_status_resolver_test.go index de4e84c..65aa0cf 100644 --- a/caching_rev_status_resolver_test.go +++ b/caching_rev_status_resolver_test.go @@ -97,7 +97,7 @@ func TestCachedResolve(t *testing.T) { _, err = cachedResolve(ctx, PerChainConfig{}, issuerDID, nil, verifiable.CredentialStatus{}, nil) - require.EqualError(t, err, "registry builder is null") + require.EqualError(t, err, "[assertion] registry builder is null") credStatus := verifiable.CredentialStatus{ ID: "id1", diff --git a/cmd/polygonid/polygonid.go b/cmd/polygonid/polygonid.go index a09c27e..7bddf57 100644 --- a/cmd/polygonid/polygonid.go +++ b/cmd/polygonid/polygonid.go @@ -8,6 +8,22 @@ typedef enum { PLGNSTATUSCODE_ERROR, PLGNSTATUSCODE_NIL_POINTER, + // error extracting credential status from verifiable credential + PLGNSTATUSCODE_USER_CREDENTIAL_STATUS_EXTRACTION_ERROR, + // error resolving credential status (e.g. getting the status from chain of DHS) + PLGNSTATUSCODE_USER_CREDENTIAL_STATUS_RESOLVE_ERROR, + // error getting merkletree proof from credential status + PLGNSTATUSCODE_USER_CREDENTIAL_STATUS_MT_BUILD_ERROR, + // merkletree proof is invalid + PLGNSTATUSCODE_USER_CREDENTIAL_STATUS_MT_STATE_ERROR, + // credential is revoked + PLGNSTATUSCODE_USER_CREDENTIAL_STATUS_REVOKED_ERROR, + // the same as above but for issuer credential (for signature proofs) + PLGNSTATUSCODE_ISSUER_CREDENTIAL_STATUS_EXTRACTION_ERROR, + PLGNSTATUSCODE_ISSUER_CREDENTIAL_STATUS_RESOLVE_ERROR, + PLGNSTATUSCODE_ISSUER_CREDENTIAL_STATUS_MT_BUILD_ERROR, + PLGNSTATUSCODE_ISSUER_CREDENTIAL_STATUS_MT_STATE_ERROR, + PLGNSTATUSCODE_ISSUER_CREDENTIAL_STATUS_REVOKED_ERROR, } PLGNStatusCode; typedef struct _PLGNStatus @@ -22,6 +38,7 @@ import ( "context" "encoding/hex" "encoding/json" + "errors" "fmt" "math/big" "runtime" @@ -157,7 +174,7 @@ func PLGNAuthV2InputsMarshal(jsonResponse **C.char, in *C.char, var obj map[string]any err := json.Unmarshal([]byte(C.GoString(in)), &obj) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -236,13 +253,13 @@ func PLGNCalculateGenesisID(jsonResponse **C.char, in *C.char, resp, err := c_polygonid.NewGenesysID(ctx, c_polygonid.EnvConfig{}, []byte(inStr)) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } respB, err := json.Marshal(resp) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -297,7 +314,7 @@ func PLGNCreateClaim(jsonResponse **C.char, in *C.char, err := json.Unmarshal([]byte(C.GoString(in)), &req) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -312,7 +329,7 @@ func PLGNCreateClaim(jsonResponse **C.char, in *C.char, c, err := core.NewClaim(schema) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -327,7 +344,7 @@ func PLGNCreateClaim(jsonResponse **C.char, in *C.char, if req.IndexMerklizedRoot != nil { err = c.SetIndexMerklizedRoot(req.IndexMerklizedRoot.Int()) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } } @@ -335,7 +352,7 @@ func PLGNCreateClaim(jsonResponse **C.char, in *C.char, if req.ValueMerklizedRoot != nil { err = c.SetValueMerklizedRoot(req.ValueMerklizedRoot.Int()) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } } @@ -372,7 +389,7 @@ func PLGNCreateClaim(jsonResponse **C.char, in *C.char, } err = c.SetIndexDataInts(slotA, slotB) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } } @@ -388,14 +405,14 @@ func PLGNCreateClaim(jsonResponse **C.char, in *C.char, } err = c.SetValueDataInts(slotA, slotB) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } } respB, err := json.Marshal(c) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -423,19 +440,19 @@ func PLGNIDToInt(jsonResponse **C.char, in *C.char, var idStr string err := json.Unmarshal([]byte(C.GoString(in)), &idStr) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } id, err := core.IDFromString(idStr) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } resp, err := json.Marshal(id.BigInt().Text(10)) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -459,13 +476,13 @@ func PLGNProofFromSmartContract(jsonResponse **C.char, in *C.char, var scProof c_polygonid.SmartContractProof err := json.Unmarshal([]byte(C.GoString(in)), &scProof) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } proof, root, err := c_polygonid.ProofFromSmartContract(scProof) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -478,7 +495,7 @@ func PLGNProofFromSmartContract(jsonResponse **C.char, in *C.char, } respB, err := json.Marshal(resp) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -506,31 +523,31 @@ func PLGNProfileID(jsonResponse **C.char, in *C.char, err := json.Unmarshal([]byte(C.GoString(in)), &req) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } did, err := w3c.ParseDID(req.GenesisDID) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } id, err := core.IDFromDID(*did) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } id, err = core.ProfileID(id, req.Nonce.BigInt()) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } profileDID, err := core.ParseDIDFromID(id) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -583,33 +600,8 @@ func PLGNSigV2Inputs(jsonResponse **C.char, in *C.char, ctx, cancel := logAPITime() defer cancel() - if jsonResponse == nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_NIL_POINTER, - "jsonResponse pointer is nil") - return false - } - - ctx, ctxCancel := context.WithTimeout(ctx, defaultTimeout) - defer ctxCancel() - - inData := C.GoBytes(unsafe.Pointer(in), C.int(C.strlen(in))) - - aqInpResp, err := c_polygonid.AtomicQuerySigV2InputsFromJson(ctx, - c_polygonid.EnvConfig{}, inData) - if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) - return false - } - - resp, err := marshalInputsResponse(aqInpResp) - if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, - "error marshalling atomic query inputs: %v", err) - return false - } - - *jsonResponse = C.CString(resp) - return true + return prepareInputs(ctx, c_polygonid.AtomicQuerySigV2InputsFromJson, + jsonResponse, in, nil, status) } func marshalInputsResponse( @@ -671,33 +663,8 @@ func PLGNMtpV2Inputs(jsonResponse **C.char, in *C.char, ctx, cancel := logAPITime() defer cancel() - ctx, ctxCancel := context.WithTimeout(ctx, defaultTimeout) - defer ctxCancel() - - if jsonResponse == nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_NIL_POINTER, - "jsonResponse pointer is nil") - return false - } - - inData := C.GoBytes(unsafe.Pointer(in), C.int(C.strlen(in))) - - aqInpResp, err := c_polygonid.AtomicQueryMtpV2InputsFromJson(ctx, - c_polygonid.EnvConfig{}, inData) - if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) - return false - } - - resp, err := marshalInputsResponse(aqInpResp) - if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, - "error marshalling atomic query inputs: %v", err) - return false - } - - *jsonResponse = C.CString(resp) - return true + return prepareInputs(ctx, c_polygonid.AtomicQueryMtpV2InputsFromJson, + jsonResponse, in, nil, status) } // PLGNAtomicQuerySigV2OnChainInputs returns the inputs for the @@ -807,7 +774,7 @@ func PLGNCleanCache(status **C.PLGNStatus) bool { err := c_polygonid.CleanCache() if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -826,13 +793,13 @@ func PLGNCacheCredentials(in *C.char, cfg *C.char, status **C.PLGNStatus) bool { envCfg, err := createEnvConfig(cfg) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } err = c_polygonid.PreCacheVC(ctx, envCfg, inData) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -879,7 +846,7 @@ func PLGNW3CCredentialFromOnchainHex(jsonResponse **C.char, in *C.char, envCfg, err := createEnvConfig(cfg) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -889,13 +856,13 @@ func PLGNW3CCredentialFromOnchainHex(jsonResponse **C.char, in *C.char, inData, ) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } credentialJSON, err := json.Marshal(credential) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -936,20 +903,20 @@ func PLGNDescribeID(jsonResponse **C.char, in *C.char, cfg *C.char, envCfg, err := createEnvConfig(cfg) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } inStr := C.GoString(in) resp, err := c_polygonid.DescribeID(ctx, envCfg, []byte(inStr)) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } respB, err := json.Marshal(resp) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } @@ -986,13 +953,14 @@ func prepareInputs(ctx context.Context, fn atomicQueryInputsFn, envCfg, err := createEnvConfig(cfg) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } aqInpResp, err := fn(ctx, envCfg, inData) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + statusCode, errorMsg := statusFromError(err) + maybeCreateStatus(status, statusCode, "%s", errorMsg) return false } @@ -1007,6 +975,61 @@ func prepareInputs(ctx context.Context, fn atomicQueryInputsFn, return true } +func statusFromError(err error) (C.PLGNStatusCode, string) { + if err == nil { + return C.PLGNSTATUSCODE_ERROR, "" + } + + var csErr c_polygonid.ErrCredentialStatus + if errors.As(err, &csErr) { + err2 := csErr.Unwrap() + var errExtract c_polygonid.ErrCredentialStatusExtract + var errResolve c_polygonid.ErrCredentialStatusResolve + var errTreeBuild c_polygonid.ErrCredentialStatusTreeBuild + var errTreeState c_polygonid.ErrCredentialStatusTreeState + switch csErr.Owner() { + case c_polygonid.CredentialStatusOwnerUser: + if errors.As(err2, &errExtract) { + return C.PLGNSTATUSCODE_USER_CREDENTIAL_STATUS_EXTRACTION_ERROR, + err.Error() + } else if errors.As(err2, &errResolve) { + return C.PLGNSTATUSCODE_USER_CREDENTIAL_STATUS_RESOLVE_ERROR, + err.Error() + } else if errors.As(err2, &errTreeBuild) { + return C.PLGNSTATUSCODE_USER_CREDENTIAL_STATUS_MT_BUILD_ERROR, + err.Error() + } else if errors.As(err2, &errTreeState) { + return C.PLGNSTATUSCODE_USER_CREDENTIAL_STATUS_MT_STATE_ERROR, + err.Error() + } else if errors.Is(err2, c_polygonid.ErrCredentialStatusRevoked) { + return C.PLGNSTATUSCODE_USER_CREDENTIAL_STATUS_REVOKED_ERROR, + err.Error() + } + case c_polygonid.CredentialStatusOwnerIssuer: + if errors.As(err2, &errExtract) { + return C.PLGNSTATUSCODE_ISSUER_CREDENTIAL_STATUS_EXTRACTION_ERROR, + err.Error() + } else if errors.As(err2, &errResolve) { + return C.PLGNSTATUSCODE_ISSUER_CREDENTIAL_STATUS_RESOLVE_ERROR, + err.Error() + } else if errors.As(err2, &errTreeBuild) { + return C.PLGNSTATUSCODE_ISSUER_CREDENTIAL_STATUS_MT_BUILD_ERROR, + err.Error() + } else if errors.As(err2, &errTreeState) { + return C.PLGNSTATUSCODE_ISSUER_CREDENTIAL_STATUS_MT_STATE_ERROR, + err.Error() + } else if errors.Is(err2, c_polygonid.ErrCredentialStatusRevoked) { + return C.PLGNSTATUSCODE_ISSUER_CREDENTIAL_STATUS_REVOKED_ERROR, + err.Error() + } + default: + // lint error bypass + } + } + + return C.PLGNSTATUSCODE_ERROR, err.Error() +} + func callGenericFn[R any]( fn func(context.Context, c_polygonid.EnvConfig, []byte) (R, error), jsonResponse **C.char, in *C.char, cfg *C.char, @@ -1023,20 +1046,20 @@ func callGenericFn[R any]( envCfg, err := createEnvConfig(cfg) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } inStr := C.GoString(in) resp, err := fn(ctx, envCfg, []byte(inStr)) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } respB, err := json.Marshal(resp) if err != nil { - maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error()) return false } diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..46300db --- /dev/null +++ b/errors.go @@ -0,0 +1,82 @@ +package c_polygonid + +import ( + "errors" + "fmt" +) + +type ErrCredentialStatus struct { + err error + owner CredentialStatusOwner +} + +func (c ErrCredentialStatus) Error() string { + return fmt.Sprintf("credential status error: %v", c.err) +} + +func (c ErrCredentialStatus) Unwrap() error { + return c.err +} + +func (c ErrCredentialStatus) Owner() CredentialStatusOwner { + return c.owner +} + +type ErrCredentialStatusResolve struct { + err error +} + +func (e ErrCredentialStatusResolve) Error() string { + return fmt.Sprintf("credential status resolve error: %v", e.err) +} + +func (e ErrCredentialStatusResolve) Unwrap() error { + return e.err +} + +type ErrCredentialStatusExtract struct { + err error +} + +func (e ErrCredentialStatusExtract) Error() string { + return fmt.Sprintf( + "error extracting credential status from verifiable credential: %v", + e.err) +} + +func (e ErrCredentialStatusExtract) Unwrap() error { + return e.err +} + +type ErrCredentialStatusTreeBuild struct { + err error +} + +func (e ErrCredentialStatusTreeBuild) Error() string { + return fmt.Sprintf( + "error building tree proof from credential status: %v", + e.err) +} + +func (e ErrCredentialStatusTreeBuild) Unwrap() error { + return e.err +} + +type ErrCredentialStatusTreeState struct { + msg string + err error +} + +func (e ErrCredentialStatusTreeState) Error() string { + m := "error validating credential status merkletree proof: " + e.msg + if e.err != nil { + m += ": " + e.err.Error() + } + return m +} + +func (e ErrCredentialStatusTreeState) Unwrap() error { + return e.err +} + +var ErrCredentialStatusRevoked = errors.New("credential is revoked") diff --git a/examples/testdata/auth_v2_inputs_out.json b/examples/testdata/auth_v2_inputs_out.json index 155aafe..8de2c43 100644 --- a/examples/testdata/auth_v2_inputs_out.json +++ b/examples/testdata/auth_v2_inputs_out.json @@ -1 +1,179 @@ -{"genesisID":"20927206916516385762021045711373308484593551383318447051738793701319835649","profileNonce":"0","authClaim":["304427537360709784173770334266246861770","0","17640206035128972995519606214765283372613874593503528180869261482403155458945","20634138280259599560273310290025659992320584624461316485434108770067472477956","15930428023331155902","0","0","0"],"authClaimIncMtp":["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],"authClaimNonRevMtp":["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],"authClaimNonRevMtpAuxHi":"0","authClaimNonRevMtpAuxHv":"0","authClaimNonRevMtpNoAux":"1","challenge":"10","challengeSignatureR8x":"2436614617352067078274240654647841101298221663194055411539273018411814965042","challengeSignatureR8y":"18597752099468941062473075570139025288787892531282848931228194191266230422780","challengeSignatureS":"1642466479083925938589665711747519202726798003514101885795868643287098549939","claimsTreeRoot":"9763429684850732628215303952870004997159843236039795272605841029866455670219","revTreeRoot":"0","rootsTreeRoot":"0","state":"18656147546666944484453899241916469544090258810192803949522794490493271005313","gistRoot":"4924303677736085224554833340748086265406229626627819375177261957522622163007","gistMtp":["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],"gistMtpAuxHi":"24846663430375341177084327381366271031641225773947711007341346118923321345","gistMtpAuxHv":"6317996369756476782464660619835940615734517981889733696047139451453239145426","gistMtpNoAux":"0"} +{ + "genesisID": "20927206916516385762021045711373308484593551383318447051738793701319835649", + "profileNonce": "0", + "authClaim": [ + "304427537360709784173770334266246861770", + "0", + "17640206035128972995519606214765283372613874593503528180869261482403155458945", + "20634138280259599560273310290025659992320584624461316485434108770067472477956", + "15930428023331155902", + "0", + "0", + "0" + ], + "authClaimIncMtp": [ + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0" + ], + "authClaimNonRevMtp": [ + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0" + ], + "authClaimNonRevMtpAuxHi": "0", + "authClaimNonRevMtpAuxHv": "0", + "authClaimNonRevMtpNoAux": "1", + "challenge": "10", + "challengeSignatureR8x": "2436614617352067078274240654647841101298221663194055411539273018411814965042", + "challengeSignatureR8y": "18597752099468941062473075570139025288787892531282848931228194191266230422780", + "challengeSignatureS": "1642466479083925938589665711747519202726798003514101885795868643287098549939", + "claimsTreeRoot": "9763429684850732628215303952870004997159843236039795272605841029866455670219", + "revTreeRoot": "0", + "rootsTreeRoot": "0", + "state": "18656147546666944484453899241916469544090258810192803949522794490493271005313", + "gistRoot": "4924303677736085224554833340748086265406229626627819375177261957522622163007", + "gistMtp": [ + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0" + ], + "gistMtpAuxHi": "24846663430375341177084327381366271031641225773947711007341346118923321345", + "gistMtpAuxHv": "6317996369756476782464660619835940615734517981889733696047139451453239145426", + "gistMtpNoAux": "0" +} diff --git a/inputs_sig.go b/inputs_sig.go index 53da2ce..f2f8186 100644 --- a/inputs_sig.go +++ b/inputs_sig.go @@ -196,7 +196,10 @@ func claimWithSigProofFromObj(ctx context.Context, cfg EnvConfig, out.NonRevProof, err = buildAndValidateCredentialStatus(ctx, cfg, credStatus, issuerDID, userDID, skipClaimRevocationCheck) if err != nil { - return out, err + return out, ErrCredentialStatus{ + err: err, + owner: CredentialStatusOwnerUser, + } } out.SignatureProof, err = signatureProof(ctx, cfg, *proof, issuerDID, userDID) @@ -357,20 +360,18 @@ func buildAndValidateCredentialStatus(ctx context.Context, cfg EnvConfig, credStatus2, err := credStatusFromJsonObj(credStatus) if err != nil { - return circuits.MTProof{}, err + return circuits.MTProof{}, ErrCredentialStatusExtract{err: err} } revStatus, err := cachedResolve(ctx, cfg.ChainConfigs, issuerDID, userDID, credStatus2, getResolversRegistry) if err != nil { - return circuits.MTProof{}, - fmt.Errorf("error resolving revocation status: %w", err) + return circuits.MTProof{}, ErrCredentialStatusResolve{err: err} } cProof, err := revStatusToCircuitsMTPProof(revStatus) if err != nil { - return circuits.MTProof{}, fmt.Errorf( - "error converting revocation status to circuits MTP proof: %w", err) + return circuits.MTProof{}, ErrCredentialStatusTreeBuild{err: err} } if skipClaimRevocationCheck { @@ -380,10 +381,18 @@ func buildAndValidateCredentialStatus(ctx context.Context, cfg EnvConfig, treeStateOk, err := validateTreeState(cProof.TreeState) if err != nil { return circuits.MTProof{}, - fmt.Errorf("tree state validation failed: %w", err) + ErrCredentialStatusTreeState{ + msg: "tree state validation failed", + err: err, + } } if !treeStateOk { - return circuits.MTProof{}, errors.New("invalid tree state") + return circuits.MTProof{}, + ErrCredentialStatusTreeState{ + msg: "invalid tree state", + err: err, + } + } revNonce := new(big.Int).SetUint64(credStatus2.RevocationNonce) @@ -391,12 +400,13 @@ func buildAndValidateCredentialStatus(ctx context.Context, cfg EnvConfig, proofValid := merkletree.VerifyProof(cProof.TreeState.RevocationRoot, cProof.Proof, revNonce, big.NewInt(0)) if !proofValid { - return circuits.MTProof{}, - fmt.Errorf("proof validation failed. revNonce=%d", revNonce) + return circuits.MTProof{}, ErrCredentialStatusTreeState{ + msg: "proof validation failed", + } } if cProof.Proof.Existence { - return circuits.MTProof{}, errors.New("credential is revoked") + return circuits.MTProof{}, ErrCredentialStatusRevoked } return cProof, nil @@ -469,7 +479,10 @@ func signatureProof(ctx context.Context, cfg EnvConfig, buildAndValidateCredentialStatus(ctx, cfg, credStatus, issuerDID, userDID, false) if err != nil { - return out, err + return out, ErrCredentialStatus{ + err: err, + owner: CredentialStatusOwnerIssuer, + } } return out, nil @@ -1907,9 +1920,6 @@ func claimWithMtpProofFromObj(ctx context.Context, cfg EnvConfig, if err != nil { return out, err } - - } else if proofI = findProofByType(w3cCred, verifiable.ProofType(verifiable.Iden3OnchainSparseMerkleTreeProof2023)); proofI != nil { - } else { return out, errProofNotFound(verifiable.Iden3SparseMerkleTreeProofType) } @@ -1942,7 +1952,10 @@ func claimWithMtpProofFromObj(ctx context.Context, cfg EnvConfig, out.NonRevProof, err = buildAndValidateCredentialStatus(ctx, cfg, credStatus, issuerDID, userDID, skipClaimRevocationCheck) if err != nil { - return out, err + return out, ErrCredentialStatus{ + err: err, + owner: CredentialStatusOwnerUser, + } } return out, nil diff --git a/inputs_sig_test.go b/inputs_sig_test.go index de36950..b9a41d7 100644 --- a/inputs_sig_test.go +++ b/inputs_sig_test.go @@ -158,7 +158,7 @@ func TestPrepareInputs(t *testing.T) { doTest(t, "atomic_query_mtp_v2_on_chain_status_inputs.json", "", AtomicQueryMtpV2InputsFromJson, nil, cfg, - "error resolving revocation status: GetRevocationProof smart contract call [GetRevocationStatus]: roots were not saved to identity tree store") + "credential status error: credential status resolve error: GetRevocationProof smart contract call [GetRevocationStatus]: roots were not saved to identity tree store") }) t.Run("AtomicQueryMtpV2InputsFromJson", func(t *testing.T) { @@ -304,7 +304,7 @@ func TestPrepareInputs(t *testing.T) { doTest(t, "atomic_query_sig_v2_merklized_revoked_inputs.json", "", AtomicQuerySigV2InputsFromJson, nil, EnvConfig{}, - "credential is revoked") + "credential status error: credential is revoked") }) t.Run("AtomicQuerySigV2InputsFromJson - skip revocation check", @@ -482,7 +482,7 @@ func TestPrepareInputs(t *testing.T) { } doTest(t, "atomic_query_sig_v2_merklized_rhs_revoked_inputs.json", "", AtomicQuerySigV2InputsFromJson, nil, cfg, - "credential is revoked") + "credential status error: credential is revoked") }) t.Run("AtomicQuerySigV2InputsFromJson Nested Disclosure", func(t *testing.T) {