diff --git a/inputs_sig.go b/inputs_sig.go index 1b56c8e..f0cbc38 100644 --- a/inputs_sig.go +++ b/inputs_sig.go @@ -51,6 +51,8 @@ var credentialsV1JsonLDBytes []byte var errCredentialsRevoked = errors.New("credential is revoked") +var topLevelScalarDisclosureFields = []string{"expirationDate", "issuanceDate"} + func stringByPath(obj jsonObj, path string) (string, error) { v, err := getByPath(obj, path) if err != nil { @@ -645,13 +647,35 @@ type objEntry struct { value any } -func mkVPObj(tp string, kvs ...objEntry) (jsonObj, error) { - out := jsonObj{"type": tp} - for _, kv := range kvs { - err := insertKV(out, kv) +// mkVPCredentialStatus seeds a verifiable presentation credentialStatus object +// with the id and type taken from the credential itself, so disclosed status +// fields (e.g. revocationNonce) can be merged on top of it. +func mkVPCredentialStatus(w3cCred verifiable.W3CCredential) (jsonObj, error) { + out := jsonObj{} + + var m map[string]any + switch cs := w3cCred.CredentialStatus.(type) { + case nil: + return nil, errors.New( + "credential has no credentialStatus to disclose") + case map[string]any: + m = cs + default: + // best effort for a typed credentialStatus value + b, err := json.Marshal(cs) if err != nil { return nil, err } + if err = json.Unmarshal(b, &m); err != nil { + return nil, err + } + } + + if id, ok := m["id"]; ok { + out["id"] = id + } + if tp, ok := m["type"]; ok { + out["type"] = tp } return out, nil } @@ -689,8 +713,13 @@ func insertKV(obj jsonObj, kv objEntry) error { return insertKV(nestedObj, objEntry{key: kv.key[idx+1:], value: kv.value}) } -func fmtVerifiablePresentation(context string, tp string, - kvs ...objEntry) (map[string]any, error) { +// fmtVerifiablePresentation builds a verifiable presentation that discloses the +// given entries. Each entry key is a full dotted path rooted at a top-level +// credential field, e.g. "credentialSubject.placeOfBirth.countryCode", +// "credentialStatus.revocationNonce", "expirationDate" or "issuanceDate". +// Entries are routed to the matching location inside verifiableCredential. +func fmtVerifiablePresentation(w3cCred verifiable.W3CCredential, context string, + tp string, kvs ...objEntry) (map[string]any, error) { var ldContext any @@ -706,19 +735,64 @@ func fmtVerifiablePresentation(context string, tp string, vcTypes = append(vcTypes, tp) } - credSubject, err := mkVPObj(tp, kvs...) - if err != nil { - return nil, err + vc := jsonObj{ + "@context": ldContext, + "type": vcTypes, + } + + var credSubject jsonObj + var credStatus jsonObj + for _, kv := range kvs { + topField, rest, _ := strings.Cut(kv.key, ".") + switch topField { + case "credentialSubject": + if rest == "" { + return nil, fmt.Errorf( + "invalid credentialSubject disclosure key: %v", kv.key) + } + if credSubject == nil { + credSubject = jsonObj{"type": tp} + } + if err := insertKV(credSubject, + objEntry{key: rest, value: kv.value}); err != nil { + return nil, err + } + case "credentialStatus": + if rest == "" { + return nil, fmt.Errorf( + "invalid credentialStatus disclosure key: %v", kv.key) + } + if credStatus == nil { + var err error + credStatus, err = mkVPCredentialStatus(w3cCred) + if err != nil { + return nil, err + } + } + if err := insertKV(credStatus, + objEntry{key: rest, value: kv.value}); err != nil { + return nil, err + } + default: + // top-level W3C fields, e.g. expirationDate / issuanceDate + if _, ok := vc[topField]; ok { + return nil, fmt.Errorf("key already exists: %v", topField) + } + vc[topField] = kv.value + } + } + + if credSubject != nil { + vc["credentialSubject"] = credSubject + } + if credStatus != nil { + vc["credentialStatus"] = credStatus } return map[string]any{ - "@context": baseContext, - "type": "VerifiablePresentation", - "verifiableCredential": map[string]any{ - "@context": ldContext, - "type": vcTypes, - "credentialSubject": credSubject, - }, + "@context": baseContext, + "type": "VerifiablePresentation", + "verifiableCredential": vc, }, nil } @@ -1464,13 +1538,16 @@ func queriesFromObjNonMerklized(ctx context.Context, region := trace.StartRegion(ctx, "queryFromObjNonMerklized") defer region.End() + if err = rejectTopFieldDisclosure(requestObj); err != nil { + return nil, nil, err + } + pr := processor.InitProcessorOptions(&processor.Processor{ DocumentLoader: documentLoader, Parser: json2.Parser{}, }) var queries = make([]*circuits.Query, circuits.LinkedMultiQueryLength) - var queryIndex = 0 credSubjObj, err := objByBath(requestObj, "query.credentialSubject") if errors.As(err, &errPathNotFound{}) { @@ -1504,9 +1581,8 @@ func queriesFromObjNonMerklized(ctx context.Context, return nil, nil, err } - var vpEntries []objEntry - fields := sortedKeys(credSubjObj) - for _, field := range fields { + acc := &sdAccumulator{mz: mz, circuitID: circuitID, queries: queries} + for _, field := range sortedKeys(credSubjObj) { var slotIndex int slotIndex, err = pr.GetFieldSlotIndex(field, contextType, schema) if err != nil { @@ -1536,10 +1612,6 @@ func queriesFromObjNonMerklized(ctx context.Context, if len(ops) == 0 { // handle selective disclosure - if queryIndex >= circuits.LinkedMultiQueryLength { - return nil, nil, errors.New("too many queries") - } - query := circuits.Query{SlotIndex: slotIndex} var sdOp int @@ -1582,43 +1654,36 @@ func queriesFromObjNonMerklized(ctx context.Context, return nil, nil, errSDOperatorNotSupported{sdOp} } - queries[queryIndex] = &query - queryIndex++ - - vpEntry := objEntry{key: field} - vpEntry.value, err = mz.RawValue(path) - if err != nil { + if err = acc.addQuery(&query); err != nil { + return nil, nil, err + } + if err = acc.addVPEntry("credentialSubject."+field, + path); err != nil { return nil, nil, err } - vpEntries = append(vpEntries, vpEntry) } else { - sortedOps := sortedKeys(ops) - for _, op := range sortedOps { + for _, op := range sortedKeys(ops) { val := ops[op] - if queryIndex >= circuits.LinkedMultiQueryLength { - return nil, nil, errors.New("too many queries") - } - query := circuits.Query{SlotIndex: slotIndex} query.Operator, query.Values, err = unpackOperatorWithArgs(op, val, datatype, mz.Hasher()) if err != nil { return nil, nil, err } - - queries[queryIndex] = &query - queryIndex++ + if err = acc.addQuery(&query); err != nil { + return nil, nil, err + } } } } var verifiablePresentation jsonObj - if len(vpEntries) > 0 { - verifiablePresentation, err = fmtVerifiablePresentation(contextURL, - contextType, vpEntries...) + if len(acc.vpEntries) > 0 { + verifiablePresentation, err = fmtVerifiablePresentation(w3cCred, + contextURL, contextType, acc.vpEntries...) if err != nil { return nil, nil, err } @@ -1722,6 +1787,191 @@ func sortedKeys(m jsonObj) []string { return keys } +// mkSDQuery builds a selective-disclosure query for the given value proof, +// choosing the operator supported by the circuit (SD for V3/LinkedMultiQuery, +// EQ for V2). +func mkSDQuery(circuitID circuits.CircuitID, + valueProof *circuits.ValueProof) (circuits.Query, error) { + + sdOp, ok := sdOperator[circuitID] + if !ok { + return circuits.Query{}, errSDCircuitNotSupported{circuitID} + } + + query := circuits.Query{ValueProof: valueProof} + switch sdOp { + case circuits.SD: + query.Operator = circuits.SD + query.Values = []*big.Int{} + case circuits.EQ: + query.Operator = circuits.EQ + query.Values = []*big.Int{valueProof.Value} + default: + return circuits.Query{}, errSDOperatorNotSupported{sdOp} + } + return query, nil +} + +// mkVPEntry builds a verifiable-presentation entry holding the raw disclosed +// value at the given path. +func mkVPEntry(key string, mz *merklize.Merklizer, + path merklize.Path) (objEntry, error) { + + rawValue, err := mz.RawValue(path) + if err != nil { + return objEntry{}, err + } + return objEntry{key: key, value: rawValue}, nil +} + +// assertEmptyDisclosure verifies that a query field requirement is an empty +// object, i.e. a selective-disclosure marker. Predicate operators are not +// supported on the top-level fields handled here. +func assertEmptyDisclosure(key string, val any) error { + obj, ok := val.(jsonObj) + if !ok { + return fmt.Errorf( + "field '%v' must be an empty object for selective disclosure, got %T", + key, val) + } + if len(obj) != 0 { + return fmt.Errorf( + "predicate operators are not supported on field '%v'; only "+ + "selective disclosure (empty object) is allowed", key) + } + return nil +} + +// sdAccumulator collects selective-disclosure queries together with the +// matching verifiable-presentation entries, tracking the next free query slot. +// It is shared by the merklized and non-merklized query builders so the +// bookkeeping lives in one place. +type sdAccumulator struct { + mz *merklize.Merklizer + circuitID circuits.CircuitID + queries []*circuits.Query + queryIndex int + vpEntries []objEntry +} + +// addQuery stores a pre-built query in the next free slot. +func (a *sdAccumulator) addQuery(query *circuits.Query) error { + if a.queryIndex >= circuits.LinkedMultiQueryLength { + return errors.New("too many queries") + } + a.queries[a.queryIndex] = query + a.queryIndex++ + return nil +} + +// addVPEntry records the raw disclosed value at path under key. +func (a *sdAccumulator) addVPEntry(key string, path merklize.Path) error { + vpEntry, err := mkVPEntry(key, a.mz, path) + if err != nil { + return err + } + a.vpEntries = append(a.vpEntries, vpEntry) + return nil +} + +// disclose builds a selective-disclosure query for the value at path (which +// must exist in the credential) and records it under key. +func (a *sdAccumulator) disclose(ctx context.Context, key string, + path merklize.Path) error { + + valueProof, err := mkValueProof(ctx, a.mz, path) + if err != nil { + return err + } + if !valueProof.MTP.Existence { + return fmt.Errorf( + "value not found in verifiable credential for field '%v'", key) + } + + query, err := mkSDQuery(a.circuitID, valueProof) + if err != nil { + return err + } + if err = a.addQuery(&query); err != nil { + return err + } + return a.addVPEntry(key, path) +} + +// discloseTopField resolves a top-level credential field by its document path +// and discloses it. +func (a *sdAccumulator) discloseTopField(ctx context.Context, + docPath string) error { + + path, err := a.mz.ResolveDocPath(docPath) + if err != nil { + return fmt.Errorf( + "unable to resolve path for field '%v': %w", docPath, err) + } + return a.disclose(ctx, docPath, path) +} + +// topFields handles selective disclosure of the top-level credential fields +// credentialStatus.*, expirationDate and issuanceDate. +func (a *sdAccumulator) topFields(ctx context.Context, + requestObj jsonObj) error { + + // credentialStatus.: {} + csObj, err := objByBath(requestObj, "query.credentialStatus") + if err != nil && !errors.As(err, &errPathNotFound{}) { + return fmt.Errorf( + "unable to extract credentialStatus from query: %w", err) + } + if err == nil { + for _, field := range sortedKeys(csObj) { + key := "credentialStatus." + field + if err = assertEmptyDisclosure(key, csObj[field]); err != nil { + return err + } + if err = a.discloseTopField(ctx, key); err != nil { + return err + } + } + } + + // expirationDate: {} and issuanceDate: {} + for _, field := range topLevelScalarDisclosureFields { + val, gErr := getByPath(requestObj, "query."+field) + if errors.As(gErr, &errPathNotFound{}) { + continue + } + if gErr != nil { + return gErr + } + if err = assertEmptyDisclosure(field, val); err != nil { + return err + } + if err = a.discloseTopField(ctx, field); err != nil { + return err + } + } + + return nil +} + +// rejectTopFieldDisclosure returns an error if the request asks to disclose a +// top-level field that is only supported for merklized credentials. +func rejectTopFieldDisclosure(requestObj jsonObj) error { + fields := append([]string{"credentialStatus"}, topLevelScalarDisclosureFields...) + for _, field := range fields { + _, err := getByPath(requestObj, "query."+field) + if errors.As(err, &errPathNotFound{}) { + continue + } + if err != nil { + return err + } + return fmt.Errorf("selective disclosure of top-level field '%v' is "+ + "only supported for merklized credentials", field) + } + return nil +} + func queriesFromObjMerklized(ctx context.Context, w3cCred verifiable.W3CCredential, requestObj jsonObj, documentLoader ld.DocumentLoader, circuitID circuits.CircuitID, @@ -1755,102 +2005,50 @@ func queriesFromObjMerklized(ctx context.Context, } var queries = make([]*circuits.Query, circuits.LinkedMultiQueryLength) - var queryIndex = 0 + acc := &sdAccumulator{mz: mz, circuitID: circuitID, queries: queries} + + // credentialSubject queries (predicates and selective disclosure) var credSubjObj jsonObj credSubjObj, err = objByBath(requestObj, "query.credentialSubject") - if errors.As(err, &errPathNotFound{}) { - - queries[0] = new(circuits.Query) - - if circuitID == circuits.AtomicQueryV3CircuitID || - circuitID == circuits.AtomicQueryV3OnChainCircuitID || - circuitID == circuits.LinkedMultiQuery10CircuitID || - circuitID == circuits.AtomicQueryV3StableCircuitID || - circuitID == circuits.AtomicQueryV3OnChainStableCircuitID { - queries[0].Operator = circuits.NOOP - queries[0].Values = []*big.Int{} - } else { - var path merklize.Path - path, err = merklize.NewPath(iriCredentialSubject) - if err != nil { - return nil, nil, err - } - *queries[0], err = mkEqQuery(ctx, mz, path) - if err != nil { - return nil, nil, err - } - } - - return queries, nil, nil - } else if err != nil { + if err != nil && !errors.As(err, &errPathNotFound{}) { return nil, nil, fmt.Errorf("unable to extract field from query: %w", err) } + if err == nil { + fields := sortedKeys(credSubjObj) + for _, field := range fields { + ops, ok := credSubjObj[field].(jsonObj) + if !ok { + return nil, nil, fmt.Errorf( + "for query field '%v' the operator object is of incorrect type: %T", + field, credSubjObj[field]) - var vpEntries []objEntry - fields := sortedKeys(credSubjObj) - for _, field := range fields { - ops, ok := credSubjObj[field].(jsonObj) - if !ok { - return nil, nil, fmt.Errorf( - "for query field '%v' the operator object is of incorrect type: %T", - field, credSubjObj[field]) - - } - - var path merklize.Path - path, err = buildQueryPath(ctx, contextURL, contextType, field, - documentLoader) - if err != nil { - return nil, nil, err - } - - var valueProof *circuits.ValueProof - valueProof, err = mkValueProof(ctx, mz, path) - if err != nil { - return nil, nil, err - } - - if len(ops) == 0 { - - // Handle selective disclosure - - if queryIndex >= circuits.LinkedMultiQueryLength { - return nil, nil, errors.New("too many queries") } - var query = circuits.Query{ValueProof: valueProof} - var sdOp int - sdOp, ok = sdOperator[circuitID] - if !ok { - return nil, nil, errSDCircuitNotSupported{circuitID} + var path merklize.Path + path, err = buildQueryPath(ctx, contextURL, contextType, field, + documentLoader) + if err != nil { + return nil, nil, err } - switch sdOp { - case circuits.SD: - query.Operator = circuits.SD - query.Values = []*big.Int{} - case circuits.EQ: - query.Operator = circuits.EQ - query.Values = []*big.Int{query.ValueProof.Value} - default: - return nil, nil, errSDOperatorNotSupported{sdOp} + if len(ops) == 0 { + // selective disclosure + if err = acc.disclose(ctx, "credentialSubject."+field, + path); err != nil { + return nil, nil, err + } + continue } - queries[queryIndex] = &query - queryIndex++ - - vpEntry := objEntry{key: field} - vpEntry.value, err = mz.RawValue(path) + // predicate operators + var valueProof *circuits.ValueProof + valueProof, err = mkValueProof(ctx, mz, path) if err != nil { return nil, nil, err } - vpEntries = append(vpEntries, vpEntry) - } else { - - sortedOps := sortedKeys(ops) - for _, op := range sortedOps { + for _, op := range sortedKeys(ops) { val := ops[op] var fieldDatatype string @@ -1864,26 +2062,55 @@ func queriesFromObjMerklized(ctx context.Context, return nil, nil, err } - var query = circuits.Query{ValueProof: valueProof} + query := circuits.Query{ValueProof: valueProof} query.Operator, query.Values, err = unpackOperatorWithArgs(op, val, fieldDatatype, mz.Hasher()) if err != nil { return nil, nil, err } - - if queryIndex >= circuits.LinkedMultiQueryLength { - return nil, nil, errors.New("too many queries") + if err = acc.addQuery(&query); err != nil { + return nil, nil, err } - queries[queryIndex] = &query - queryIndex++ } } } + // selective disclosure of top-level fields: + // credentialStatus.*, expirationDate, issuanceDate + if err = acc.topFields(ctx, requestObj); err != nil { + return nil, nil, err + } + + if acc.queryIndex == 0 { + // nothing was queried: emit a single default query + queries[0] = new(circuits.Query) + + if circuitID == circuits.AtomicQueryV3CircuitID || + circuitID == circuits.AtomicQueryV3OnChainCircuitID || + circuitID == circuits.LinkedMultiQuery10CircuitID || + circuitID == circuits.AtomicQueryV3StableCircuitID || + circuitID == circuits.AtomicQueryV3OnChainStableCircuitID { + queries[0].Operator = circuits.NOOP + queries[0].Values = []*big.Int{} + } else { + var path merklize.Path + path, err = merklize.NewPath(iriCredentialSubject) + if err != nil { + return nil, nil, err + } + *queries[0], err = mkEqQuery(ctx, mz, path) + if err != nil { + return nil, nil, err + } + } + + return queries, nil, nil + } + var verifiablePresentation jsonObj - if len(vpEntries) > 0 { - verifiablePresentation, err = fmtVerifiablePresentation(contextURL, - contextType, vpEntries...) + if len(acc.vpEntries) > 0 { + verifiablePresentation, err = fmtVerifiablePresentation(w3cCred, + contextURL, contextType, acc.vpEntries...) if err != nil { return nil, nil, err } diff --git a/inputs_sig_test.go b/inputs_sig_test.go index 5e93241..300be7c 100644 --- a/inputs_sig_test.go +++ b/inputs_sig_test.go @@ -755,6 +755,65 @@ func TestPrepareInputs(t *testing.T) { EnvConfig{}, "", "") }) + t.Run("LinkedMultiQueryInputsFromJson - Sig - Selective Disclosure with meta field", func(t *testing.T) { + ipfsURL := os.Getenv("IPFS_URL") + if ipfsURL == "" { + t.Fatal("IPFS_URL is not set") + } + + defer preserveIPFSHttpCli()() + + cid := uploadIPFSFile(t, ipfsURL, "testdata/ipfs_QmZbsTnRwtCmbdg3r9o7Txid37LmvPcvmzVi1Abvqu1WKL.json") + require.Equal(t, "QmZbsTnRwtCmbdg3r9o7Txid37LmvPcvmzVi1Abvqu1WKL", cid) + + defer httpmock.MockHTTPClient(t, map[string]string{ + `http://localhost:8545%%%{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"from":"0x0000000000000000000000000000000000000000","input":"0xb4bdea55000e4309ebc549d974a1c8de06d5146790a53c667ed3a49f82079597ab781301","to":"0x1a4cc30f2aa0377b0c3bc9848766d90cb4404124"},"latest"]}`: "testdata/httpresp_eth_resp4.json", + "https://schema.iden3.io/core/jsonld/iden3proofs.jsonld": "testdata/httpresp_iden3proofs.jsonld", + "https://rhs-staging.polygonid.me/node/22963e52a4c04ef499f1d2930867ebdb5596a73dbcd77477b5519a299ff7b815": "testdata/httpresp_rhs_22963e52a4c04ef499f1d2930867ebdb5596a73dbcd77477b5519a299ff7b815.json", + "https://rhs-staging.polygonid.me/node/b2c723870c6b85698de19c06166d1159fb5082018430b15b1c00de9f38a34809": "testdata/httpresp_rhs_b2c723870c6b85698de19c06166d1159fb5082018430b15b1c00de9f38a34809.json", + })() + + wantVerifiablePresentation := map[string]any{ + "@context": []any{"https://www.w3.org/2018/credentials/v1"}, + "type": "VerifiablePresentation", + "verifiableCredential": map[string]any{ + "@context": []any{ + "https://www.w3.org/2018/credentials/v1", + "ipfs://QmZbsTnRwtCmbdg3r9o7Txid37LmvPcvmzVi1Abvqu1WKL", + }, + "type": []any{"VerifiableCredential", "BasicPerson"}, + "issuanceDate": "2026-06-09T17:14:29.328Z", + "expirationDate": "2058-07-10T11:33:20Z", + "credentialSubject": map[string]any{ + "type": "BasicPerson", + "placeOfBirth": map[string]any{ + "countryCode": "UA-ua", + }, + }, + "credentialStatus": map[string]any{ + "id": "https://rhs-staging.polygonid.me/node?state=ed17a07e8b78ab979507829fa4d37e663ca5906714d506dec8a174d949c5eb09", + "type": "Iden3ReverseSparseMerkleTreeProof", + "revocationNonce": float64(2837597946), + }, + }, + } + + cfg := EnvConfig{ + IPFSNodeURL: ipfsURL, + ChainConfigs: map[core.ChainID]ChainConfig{ + 80002: { + RPCUrl: "http://localhost:8545", + StateContractAddr: common.HexToAddress("0x1a4cC30f2aA0377b0c3bc9848766D90cb4404124"), + }, + }, + } + + doTest(t, "atomic_query_v3_sig_selective_disclosure_with_meta_fields_inputs.json", + "atomic_query_v3_sig_selective_disclosure_with_meta_fields_outputs.json", + LinkedMultiQueryInputsFromJson, wantVerifiablePresentation, + cfg, "", "") + }) + t.Run("AtomicQueryV3OnChainInputsFromJson - Transaction Data", func(t *testing.T) { defer httpmock.MockHTTPClient(t, map[string]string{ "http://localhost:8001/api/v1/identities/did%3Apolygonid%3Apolygon%3Amumbai%3A2qDnyCaxj4zdYmj6LbegYMjWSnkbKAyqtq31YeuyZV/claims/revocation/status/3972757": "testdata/httpresp_rev_status_3972757.json", @@ -1465,7 +1524,7 @@ func TestDescribeID(t *testing.T) { require.EqualError(t, err, "id and idAsInt are different") } -func TestMkVPObj(t *testing.T) { +func TestInsertKV(t *testing.T) { const tp = "tp" testCases := []struct { @@ -1518,7 +1577,13 @@ func TestMkVPObj(t *testing.T) { for i, tc := range testCases { t.Run(strconv.Itoa(i), func(t *testing.T) { - out, err := mkVPObj(tp, tc.in...) + out := jsonObj{"type": tp} + var err error + for _, kv := range tc.in { + if err = insertKV(out, kv); err != nil { + break + } + } if tc.wantErr != "" { require.EqualError(t, err, tc.wantErr) return diff --git a/testdata/atomic_query_v3_sig_selective_disclosure_with_meta_fields_inputs.json b/testdata/atomic_query_v3_sig_selective_disclosure_with_meta_fields_inputs.json new file mode 100644 index 0000000..5e700f4 --- /dev/null +++ b/testdata/atomic_query_v3_sig_selective_disclosure_with_meta_fields_inputs.json @@ -0,0 +1,90 @@ +{ + "id": "x1QQ78ktjAmia48pyEZENyurZhpRSdPMWmtv1zbsi", + "claimSubjectProfileNonce": "0", + "linkNonce": "559585013", + "verifiableCredentials": { + "id": "urn:e551891e-504f-41c4-83c3-e32f1b375c35", + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://schema.iden3.io/core/jsonld/iden3proofs.jsonld", + "ipfs://QmZbsTnRwtCmbdg3r9o7Txid37LmvPcvmzVi1Abvqu1WKL" + ], + "type": [ + "VerifiableCredential", + "BasicPerson" + ], + "expirationDate": "2058-07-10T11:33:20.000Z", + "issuanceDate": "2026-06-09T17:14:29.328Z", + "credentialSubject": { + "id": "did:iden3:polygon:amoy:xDLAgEFPZFhRbTyp8Xe3ob7Lm52Qk5XULGQgu7yBS", + "fullName": "John Doe", + "firstName": "John", + "familyName": "Doe", + "dateOfBirth": 838531598, + "governmentIdentifier": "RRRRR", + "governmentIdentifierType": "passport", + "placeOfBirth": { + "countryCode": "UA-ua" + }, + "type": "BasicPerson" + }, + "credentialStatus": { + "id": "https://rhs-staging.polygonid.me/node?state=ed17a07e8b78ab979507829fa4d37e663ca5906714d506dec8a174d949c5eb09", + "type": "Iden3ReverseSparseMerkleTreeProof", + "revocationNonce": 2837597946 + }, + "issuer": "did:iden3:polygon:amoy:xCRp75DgAdS63W65fmXHz6p9DwdonuRU9e46DifhX", + "credentialSchema": { + "id": "ipfs://QmTojMfyzxehCJVw7aUrdWuxdF68R7oLYooGHCUr9wwsef", + "type": "JsonSchema2023" + }, + "proof": [ + { + "issuerData": { + "id": "did:iden3:polygon:amoy:xCRp75DgAdS63W65fmXHz6p9DwdonuRU9e46DifhX", + "state": { + "rootOfRoots": "0000000000000000000000000000000000000000000000000000000000000000", + "revocationTreeRoot": "0000000000000000000000000000000000000000000000000000000000000000", + "claimsTreeRoot": "6091193ec58a6c020183c2d889a92c32410f31812595f228d67a2bf37e04a729", + "value": "ed17a07e8b78ab979507829fa4d37e663ca5906714d506dec8a174d949c5eb09" + }, + "mtp": { + "existence": true, + "siblings": [] + }, + "authCoreClaim": "cca3371a6cb1b715004407e325bd993c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bd045c3101b2a0bcd60106ff21a680d86af3dbbdec406764f93ab82849410e1c27eb6114eeff7eb030b34d1db28b46d61cb6d7efbec190a0b1c1664664ced80f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "credentialStatus": { + "id": "https://rhs-staging.polygonid.me/node?state=ed17a07e8b78ab979507829fa4d37e663ca5906714d506dec8a174d949c5eb09", + "type": "Iden3ReverseSparseMerkleTreeProof", + "revocationNonce": 0 + } + }, + "type": "BJJSignature2021", + "coreClaim": "7ed2bce3d6fab6efe706a7e76a0881dd2a00000000000000000000000000000001138c8ddaf071794a4cc9c9c43d596dcc8a1d9829f6946e14d90d166c780d00ec8f7ddaa4cd48bddfb308cc3f0bca5b220e29e197f410a481ac894bef7759150000000000000000000000000000000000000000000000000000000000000000fa4e22a90000000080d481a60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "signature": "5a9a14c1dbd446b1cd9b17dadba1d95681d819e2217163a6f90507e0819a100122fd96e5caea78a12813f4c8442e041e8b4e70a09552e7ad6931b727960f5501" + } + ] + }, + "request": { + "id": 1, + "circuitId": "linkedMultiQuery10-beta.1", + "optional": false, + "query": { + "groupId": 1, + "proofType": "BJJSignature2021", + "allowedIssuers": [ + "*" + ], + "type": "BasicPerson", + "context": "ipfs://QmZbsTnRwtCmbdg3r9o7Txid37LmvPcvmzVi1Abvqu1WKL", + "credentialStatus": { + "revocationNonce": {} + }, + "expirationDate": {}, + "issuanceDate": {}, + "credentialSubject": { + "placeOfBirth.countryCode": {} + } + } + } +} \ No newline at end of file diff --git a/testdata/atomic_query_v3_sig_selective_disclosure_with_meta_fields_outputs.json b/testdata/atomic_query_v3_sig_selective_disclosure_with_meta_fields_outputs.json new file mode 100644 index 0000000..6f15298 --- /dev/null +++ b/testdata/atomic_query_v3_sig_selective_disclosure_with_meta_fields_outputs.json @@ -0,0 +1,1114 @@ +{ + "linkNonce": "559585013", + "issuerClaim": [ + "14586288774771787882356214884390414373502", + "23800135400541056536823633859447677248145141854537695393088553065680474881", + "9656646968211449500609005531404556188721362388334715229416114075775964909548", + "0", + "51531466563951178374296260346", + "0", + "0", + "0" + ], + "claimSchema": "294429364092372416894481372256149492350", + "claimPathMtp": [ + [ + "12284214950501505893767639835780272666548512433450103259142303197925283759076", + "1221823123302030298459837438714707425038987979421135033022083307612056854658", + "20778350655227693949682469293670486574247823350068346047663057547698015794647", + "20839603439076278906657550418445743618230061078697331094875368389838456504839", + "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" + ], + [ + "10509781420913630578885545484012277164504234347956868162624198963776778962830", + "20190266361872252862066656060427881317401456882944776524737532533346610419650", + "8177406041181338567349987268578414762143361339469532528593369376640867281783", + "20613029142710671610196494376977753227010446702271592012466366835718644808291", + "16438302531244091127330509221983678827937538188975992501047449528503421437976", + "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" + ], + [ + "10509781420913630578885545484012277164504234347956868162624198963776778962830", + "15222377300056207214420796635537704230760666671535686130995416730793649815126", + "622030820393570186883296642303044503623716813549921290764974218171304087491", + "5006213176939221641606795624110551761842112843978402042786414648339360632257", + "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" + ], + [ + "10509781420913630578885545484012277164504234347956868162624198963776778962830", + "15222377300056207214420796635537704230760666671535686130995416730793649815126", + "16886774816287045129530197417994306378906146921924468179567355860076401485994", + "2256542626172918319834148003962035018437256580757509907967056364028960622933", + "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", + "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", + "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", + "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" + ] + ], + "claimPathMtpNoAux": [ + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0" + ], + "claimPathMtpAuxHi": [ + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0" + ], + "claimPathMtpAuxHv": [ + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0" + ], + "claimPathKey": [ + "21116855766168144865123128148428080348392973151373100599455098664650732275908", + "11349091637037031401903854318824290385480154274253159994163000841197580053679", + "13483382060079230067188057675928039600565406666878111320562435194759310415773", + "8713837106709436881047310678745516714551061952618778897121563913918335939585", + "0", + "0", + "0", + "0", + "0", + "0" + ], + "claimPathValue": [ + "20250596419242164930851226589381817556899469092097129576320700484927666673396", + "2837597946", + "2793526400000000000", + "1781025269328000000", + "0", + "0", + "0", + "0", + "0", + "0" + ], + "slotIndex": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "operator": [ + 16, + 16, + 16, + 16, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "value": [ + [ + "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" + ], + [ + "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" + ], + [ + "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" + ], + [ + "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" + ], + [ + "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" + ], + [ + "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" + ], + [ + "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" + ], + [ + "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" + ], + [ + "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" + ], + [ + "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" + ] + ], + "valueArraySize": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] +} \ No newline at end of file diff --git a/testdata/httpresp_eth_resp4.json b/testdata/httpresp_eth_resp4.json new file mode 100644 index 0000000..e864971 --- /dev/null +++ b/testdata/httpresp_eth_resp4.json @@ -0,0 +1,5 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": "0x000e4309ebc549d974a1c8de06d5146790a53c667ed3a49f82079597ab78130115b8f79f299a51b57774d7bc3da79655dbeb670893d2f199f44ec0a4523e9622000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000660c081600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000522e620000000000000000000000000000000000000000000000000000000000000000" +} \ No newline at end of file diff --git a/testdata/httpresp_rhs_22963e52a4c04ef499f1d2930867ebdb5596a73dbcd77477b5519a299ff7b815.json b/testdata/httpresp_rhs_22963e52a4c04ef499f1d2930867ebdb5596a73dbcd77477b5519a299ff7b815.json new file mode 100644 index 0000000..2e89a40 --- /dev/null +++ b/testdata/httpresp_rhs_22963e52a4c04ef499f1d2930867ebdb5596a73dbcd77477b5519a299ff7b815.json @@ -0,0 +1 @@ +{"node":{"children":["ce55058d892e201adf651796d4efa67c96d62102b77167e368e4720729f6fa19","b2c723870c6b85698de19c06166d1159fb5082018430b15b1c00de9f38a34809","fcdb5f9244780af8455bf3880dab1a2631ed26320394d017fdd1e76d9feb342e"],"hash":"22963e52a4c04ef499f1d2930867ebdb5596a73dbcd77477b5519a299ff7b815"},"status":"OK"} \ No newline at end of file diff --git a/testdata/httpresp_rhs_b2c723870c6b85698de19c06166d1159fb5082018430b15b1c00de9f38a34809.json b/testdata/httpresp_rhs_b2c723870c6b85698de19c06166d1159fb5082018430b15b1c00de9f38a34809.json new file mode 100644 index 0000000..897adb6 --- /dev/null +++ b/testdata/httpresp_rhs_b2c723870c6b85698de19c06166d1159fb5082018430b15b1c00de9f38a34809.json @@ -0,0 +1 @@ +{"node":{"children":["e903000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000","0100000000000000000000000000000000000000000000000000000000000000"],"hash":"b2c723870c6b85698de19c06166d1159fb5082018430b15b1c00de9f38a34809"},"status":"OK"} \ No newline at end of file diff --git a/testdata/ipfs_QmZbsTnRwtCmbdg3r9o7Txid37LmvPcvmzVi1Abvqu1WKL.json b/testdata/ipfs_QmZbsTnRwtCmbdg3r9o7Txid37LmvPcvmzVi1Abvqu1WKL.json new file mode 100644 index 0000000..52003a9 --- /dev/null +++ b/testdata/ipfs_QmZbsTnRwtCmbdg3r9o7Txid37LmvPcvmzVi1Abvqu1WKL.json @@ -0,0 +1 @@ +{"@context":[{"@protected":true,"@version":1.1,"id":"@id","type":"@type","BasicPerson":{"@context":{"@propagate":true,"@protected":true,"polygon-vocab":"urn:uuid:bd42bba2-1caa-48b9-ab85-9509d33016bc#","xsd":"http://www.w3.org/2001/XMLSchema#","fullName":{"@id":"polygon-vocab:fullName","@type":"xsd:string"},"firstName":{"@id":"polygon-vocab:firstName","@type":"xsd:string"},"familyName":{"@id":"polygon-vocab:familyName","@type":"xsd:string"},"middleName":{"@id":"polygon-vocab:middleName","@type":"xsd:string"},"alsoKnownAs":{"@id":"polygon-vocab:alsoKnownAs","@type":"xsd:string"},"dateOfBirth":{"@id":"polygon-vocab:dateOfBirth","@type":"xsd:integer"},"governmentIdentifier":{"@id":"polygon-vocab:governmentIdentifier","@type":"xsd:string"},"governmentIdentifierType":{"@id":"polygon-vocab:governmentIdentifierType","@type":"xsd:string"},"gender":{"@id":"polygon-vocab:gender","@type":"xsd:string"},"email":{"@id":"polygon-vocab:email","@type":"xsd:string"},"sex":{"@id":"polygon-vocab:sex","@type":"xsd:string"},"phoneNumber":{"@id":"polygon-vocab:phoneNumber","@type":"xsd:double"},"phoneNumberVerified":{"@id":"polygon-vocab:phoneNumberVerified","@type":"xsd:boolean"},"title":{"@id":"polygon-vocab:title","@type":"xsd:string"},"salutation":{"@id":"polygon-vocab:salutation","@type":"xsd:string"},"documentExpirationDate":{"@id":"polygon-vocab:documentExpirationDate","@type":"xsd:integer"},"nameAndFamilyNameAtBirth":{"@context":{"firstName":{"@id":"polygon-vocab:firstName","@type":"xsd:string"},"familyName":{"@id":"polygon-vocab:familyName","@type":"xsd:string"}},"@id":"polygon-vocab:nameAndFamilyNameAtBirth"},"placeOfBirth":{"@context":{"locality":{"@id":"polygon-vocab:locality","@type":"xsd:string"},"region":{"@id":"polygon-vocab:region","@type":"xsd:string"},"countryCode":{"@id":"polygon-vocab:countryCode","@type":"xsd:string"},"countryCodeNumber":{"@id":"polygon-vocab:countryCodeNumber","@type":"xsd:integer"}},"@id":"polygon-vocab:placeOfBirth"},"addresses":{"@context":{"primaryAddress":{"@context":{"addressLine1":{"@id":"polygon-vocab:addressLine1","@type":"xsd:string"},"addressLine2":{"@id":"polygon-vocab:addressLine2","@type":"xsd:string"},"locality":{"@id":"polygon-vocab:locality","@type":"xsd:string"},"region":{"@id":"polygon-vocab:region","@type":"xsd:string"},"countryCode":{"@id":"polygon-vocab:countryCode","@type":"xsd:string"},"postalCode":{"@id":"polygon-vocab:postalCode","@type":"xsd:string"},"countryCodeNumber":{"@id":"polygon-vocab:countryCodeNumber","@type":"xsd:integer"},"unstructuredAddress":{"@id":"polygon-vocab:unstructuredAddress","@type":"xsd:string"}},"@id":"polygon-vocab:primaryAddress"},"homeAddress":{"@context":{"addressLine1":{"@id":"polygon-vocab:addressLine1","@type":"xsd:string"},"addressLine2":{"@id":"polygon-vocab:addressLine2","@type":"xsd:string"},"locality":{"@id":"polygon-vocab:locality","@type":"xsd:string"},"region":{"@id":"polygon-vocab:region","@type":"xsd:string"},"countryCode":{"@id":"polygon-vocab:countryCode","@type":"xsd:string"},"postalCode":{"@id":"polygon-vocab:postalCode","@type":"xsd:string"},"countryCodeNumber":{"@id":"polygon-vocab:countryCodeNumber","@type":"xsd:integer"},"unstructuredAddress":{"@id":"polygon-vocab:unstructuredAddress","@type":"xsd:string"}},"@id":"polygon-vocab:homeAddress"},"businessAddress":{"@context":{"addressLine1":{"@id":"polygon-vocab:addressLine1","@type":"xsd:string"},"addressLine2":{"@id":"polygon-vocab:addressLine2","@type":"xsd:string"},"locality":{"@id":"polygon-vocab:locality","@type":"xsd:string"},"region":{"@id":"polygon-vocab:region","@type":"xsd:string"},"countryCode":{"@id":"polygon-vocab:countryCode","@type":"xsd:string"},"postalCode":{"@id":"polygon-vocab:postalCode","@type":"xsd:string"},"countryCodeNumber":{"@id":"polygon-vocab:countryCodeNumber","@type":"xsd:integer"},"unstructuredAddress":{"@id":"polygon-vocab:unstructuredAddress","@type":"xsd:string"}},"@id":"polygon-vocab:businessAddress"},"mailingAddress":{"@context":{"addressLine1":{"@id":"polygon-vocab:addressLine1","@type":"xsd:string"},"addressLine2":{"@id":"polygon-vocab:addressLine2","@type":"xsd:string"},"locality":{"@id":"polygon-vocab:locality","@type":"xsd:string"},"region":{"@id":"polygon-vocab:region","@type":"xsd:string"},"countryCode":{"@id":"polygon-vocab:countryCode","@type":"xsd:string"},"postalCode":{"@id":"polygon-vocab:postalCode","@type":"xsd:string"},"countryCodeNumber":{"@id":"polygon-vocab:countryCodeNumber","@type":"xsd:integer"},"unstructuredAddress":{"@id":"polygon-vocab:unstructuredAddress","@type":"xsd:string"}},"@id":"polygon-vocab:mailingAddress"}},"@id":"polygon-vocab:addresses"},"nationalities":{"@context":{"nationality1CountryCode":{"@id":"polygon-vocab:nationality1CountryCode","@type":"xsd:string"},"nationality2CountryCode":{"@id":"polygon-vocab:nationality2CountryCode","@type":"xsd:string"},"nationality3CountryCode":{"@id":"polygon-vocab:nationality3CountryCode","@type":"xsd:string"},"nationality1CountryCodeNumber":{"@id":"polygon-vocab:nationality1CountryCodeNumber","@type":"xsd:integer"},"nationality2CountryCodeNumber":{"@id":"polygon-vocab:nationality2CountryCodeNumber","@type":"xsd:integer"},"nationality3CountryCodeNumber":{"@id":"polygon-vocab:nationality3CountryCodeNumber","@type":"xsd:integer"}},"@id":"polygon-vocab:nationalities"},"customFields":{"@context":{"string1":{"@id":"polygon-vocab:string1","@type":"xsd:string"},"string2":{"@id":"polygon-vocab:string2","@type":"xsd:string"},"string3":{"@id":"polygon-vocab:string3","@type":"xsd:string"},"number1":{"@id":"polygon-vocab:number1","@type":"xsd:double"},"number2":{"@id":"polygon-vocab:number2","@type":"xsd:double"},"number3":{"@id":"polygon-vocab:number3","@type":"xsd:double"},"boolean1":{"@id":"polygon-vocab:boolean1","@type":"xsd:boolean"},"boolean2":{"@id":"polygon-vocab:boolean2","@type":"xsd:boolean"},"boolean3":{"@id":"polygon-vocab:boolean3","@type":"xsd:boolean"}},"@id":"polygon-vocab:customFields"}},"@id":"urn:uuid:0a9897de-0ec5-42df-9e19-dbbe410b2924"}}]} \ No newline at end of file