Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

Commit

Permalink
docs: Presentation Exchange - adds samples
Browse files Browse the repository at this point in the history
Signed-off-by: Andrii Soluk <[email protected]>
  • Loading branch information
soluchok committed Jan 8, 2021
1 parent b23388a commit 226502b
Show file tree
Hide file tree
Showing 7 changed files with 709 additions and 275 deletions.
104 changes: 104 additions & 0 deletions pkg/doc/presexch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Presentation Exchange

This document shows how to use [Presentation Exchange](https://identity.foundation/presentation-exchange) by examples.
Code examples can be found [here](example_test.go).

1. This example demonstrates `predicate` and `limit_disclosure` usage.
The `presentation definition` below requires field `age` to be greater or equal to 18.
Also, we have `limit_disclosure=true` which requires that output data is limited to the entries specified in the `fields` property.
The `predicate` means that the result should be expressed as a boolean value.
```json
{
"id": "31e2f0f1-6b70-411d-b239-56aed5321884",
"purpose": "To sell you a drink we need to know that you are an adult.",
"input_descriptors": [
{
"id": "867bfe7a-5b91-46b2-9ba4-70028b8d9cc8",
"purpose": "Your age should be greater or equal to 18.",
"schema": [
{
"uri": "https://www.w3.org/TR/vc-data-model/#types"
}
],
"constraints": {
"limit_disclosure": true,
"fields": [
{
"path": [
"$.age"
],
"filter": {
"type": "integer",
"minimum": 18
},
"predicate": "required"
}
]
}
}
]
}
```
Let's say we have such a credential in our database.
```json
{
"@context": [
"https://www.w3.org/2018/credentials/v1"
],
"age": 21,
"credentialSchema": [
{
"id": "https://www.w3.org/TR/vc-data-model/#types"
}
],
"first_name": "Jesse",
"id": "2dc74354-e965-4883-be5e-bfec48bf60c7",
"issuer": "",
"last_name": "Pinkman",
"type": "VerifiableCredential"
}
```
As a result, we will have the following `verifiable presentation`:
```json
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://identity.foundation/presentation-exchange/submission/v1"
],
"presentation_submission": {
"id": "accd5adf-1dbf-4ed9-9ba2-d687476126cb",
"definition_id": "31e2f0f1-6b70-411d-b239-56aed5321884",
"descriptor_map": [
{
"id": "867bfe7a-5b91-46b2-9ba4-70028b8d9cc8",
"format": "ldp_vp",
"path": "$.verifiableCredential[0]"
}
]
},
"type": [
"VerifiablePresentation",
"PresentationSubmission"
],
"verifiableCredential": [
{
"@context": [
"https://www.w3.org/2018/credentials/v1"
],
"age": true,
"credentialSchema": [
{
"id": "https://www.w3.org/TR/vc-data-model/#types"
}
],
"credentialSubject": null,
"id": "2dc74354-e965-4883-be5e-bfec48bf60c7",
"issuer": "",
"type": "VerifiableCredential"
}
]
}
```

As you can see the VP has a credential without `first_name` and `last_name` (because of `limit_disclosure`).
Also, instead of `age`, we have a boolean value (because of `predicate`).
3 changes: 2 additions & 1 deletion pkg/doc/presexch/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package presexch
package presexch_test

import (
"encoding/json"
Expand All @@ -17,6 +17,7 @@ import (
"github.com/piprate/json-gold/ld"
"github.com/stretchr/testify/require"

. "github.com/hyperledger/aries-framework-go/pkg/doc/presexch"
"github.com/hyperledger/aries-framework-go/pkg/doc/util"
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
)
Expand Down
40 changes: 37 additions & 3 deletions pkg/doc/presexch/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"encoding/json"
"errors"
"fmt"
"sort"
"strings"

"github.com/PaesslerAG/jsonpath"
Expand All @@ -33,6 +34,8 @@ const (
Required Preference = "required"
// Preferred predicate`s value.
Preferred Preference = "preferred"

tmpEnding = "tmp_unique_id_"
)

// nolint: gochecknoglobals
Expand Down Expand Up @@ -318,7 +321,7 @@ func (pd *PresentationDefinition) CreateVP(credentials ...*verifiable.Credential

credentials, descriptors := merge(result)
vp.CustomFields = verifiable.CustomFields{
submissionProperty: PresentationSubmission{
submissionProperty: &PresentationSubmission{
ID: uuid.New().String(),
DefinitionID: pd.ID,
DescriptorMap: descriptors,
Expand Down Expand Up @@ -530,7 +533,7 @@ func filterConstraints(constraints *Constraints, creds []*verifiable.Credential)

if constraints.LimitDisclosure {
template, err = json.Marshal(map[string]interface{}{
"id": credential.ID,
"id": tmpID(credential.ID),
"credentialSchema": credential.Schemas,
"type": credential.Types,
"@context": credential.Context,
Expand All @@ -557,6 +560,19 @@ func filterConstraints(constraints *Constraints, creds []*verifiable.Credential)
return result, nil
}

func tmpID(id string) string {
return id + tmpEnding + uuid.New().String()
}

func trimTmpID(id string) string {
idx := strings.Index(id, tmpEnding)
if idx == -1 {
return id
}

return id[:idx]
}

func createNewCredential(fs []*Field, src, limitedCred []byte) (*verifiable.Credential, error) {
for _, f := range fs {
paths, err := jsonpathkeys.ParsePaths(f.Path...)
Expand Down Expand Up @@ -676,9 +692,19 @@ func merge(setOfCredentials map[string][]*verifiable.Credential) ([]*verifiable.
descriptors []*InputDescriptorMapping
)

for descriptorID, credentials := range setOfCredentials {
keys := make([]string, 0, len(setOfCredentials))
for k := range setOfCredentials {
keys = append(keys, k)
}

sort.Strings(keys)

for _, descriptorID := range keys {
credentials := setOfCredentials[descriptorID]

for _, credential := range credentials {
if _, ok := setOfCreds[credential.ID]; !ok {
credential.ID = trimTmpID(credential.ID)
result = append(result, credential)
setOfCreds[credential.ID] = len(descriptors)
}
Expand All @@ -694,9 +720,17 @@ func merge(setOfCredentials map[string][]*verifiable.Credential) ([]*verifiable.
}
}

sort.Sort(byID(descriptors))

return result, descriptors
}

type byID []*InputDescriptorMapping

func (a byID) Len() int { return len(a) }
func (a byID) Less(i, j int) bool { return a[i].ID < a[j].ID }
func (a byID) Swap(i, j int) { a[i], a[j] = a[j], a[i] }

func credentialsToInterface(credentials []*verifiable.Credential) []interface{} {
var result []interface{}
for i := range credentials {
Expand Down
Loading

0 comments on commit 226502b

Please sign in to comment.