Skip to content

Commit

Permalink
split v2 and v3 verification
Browse files Browse the repository at this point in the history
  • Loading branch information
vmidyllic committed Feb 22, 2024
1 parent de77170 commit 8a7ec13
Show file tree
Hide file tree
Showing 11 changed files with 367 additions and 285 deletions.
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ require (
github.com/golang/mock v1.6.0
github.com/google/uuid v1.3.0
github.com/iden3/contracts-abi/state/go/abi v1.0.0-beta.3
github.com/iden3/go-circuits/v2 v2.0.2-0.20240216144730-74af9e108017
github.com/iden3/go-circuits/v2 v2.0.2-0.20240131165639-deb061a1b3e6
github.com/iden3/go-circuits/v2 v2.0.2-0.20240222121329-c549fb9a0bde
github.com/iden3/go-iden3-core/v2 v2.0.3
github.com/iden3/go-iden3-crypto v0.0.15
github.com/iden3/go-jwz/v2 v2.0.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
github.com/iden3/contracts-abi/state/go/abi v1.0.0-beta.3 h1:ZHFnK2dU3NJglY+igY48JLHWtNGN/Vhf5/L/qrFk/tM=
github.com/iden3/contracts-abi/state/go/abi v1.0.0-beta.3/go.mod h1:TxgIrXCvxms3sbOdsy8kTvffUCIpEEifNy0fSXdkU4w=
github.com/iden3/go-circuits/v2 v2.0.2-0.20240131165639-deb061a1b3e6 h1:DoyzPqOZWkUBGAQc2UQbddWAD3HYF5QX1zP9b+KmSH8=
github.com/iden3/go-circuits/v2 v2.0.2-0.20240131165639-deb061a1b3e6/go.mod h1:VIFIp51+IH0hOzjnKhb84bCeyq7hq76zX/C14ua6zh4=
github.com/iden3/go-circuits/v2 v2.0.2-0.20240216144730-74af9e108017 h1:FGQ58mmZWCEHgnXqmpBD5+oTlYLjaa5AkC4M5Fwf7Zw=
github.com/iden3/go-circuits/v2 v2.0.2-0.20240216144730-74af9e108017/go.mod h1:VIFIp51+IH0hOzjnKhb84bCeyq7hq76zX/C14ua6zh4=
github.com/iden3/go-circuits/v2 v2.0.2-0.20240222121329-c549fb9a0bde h1:/PF8qkQSj/MvMO9xnagGmc5hFq2/+NxPEsLpb7hF0yo=
github.com/iden3/go-circuits/v2 v2.0.2-0.20240222121329-c549fb9a0bde/go.mod h1:VIFIp51+IH0hOzjnKhb84bCeyq7hq76zX/C14ua6zh4=
github.com/iden3/go-iden3-core/v2 v2.0.3 h1:ce9Jbw10zDsinWXFc05SiK2Hof/wu4zV4/ai5gQy29k=
github.com/iden3/go-iden3-core/v2 v2.0.3/go.mod h1:L9PxhWPvoS9qTb3inEkZBm1RpjHBt+VTwvxssdzbAdw=
github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4=
Expand Down
2 changes: 1 addition & 1 deletion pubsignals/atomicMtpV2.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (c *AtomicQueryMTPV2) VerifyQuery(
IsRevocationChecked: c.IsRevocationChecked,
}

err := query.Check(ctx, schemaLoader, &pubSig, verifiablePresentation, false, opts...)
err := query.Check(ctx, schemaLoader, &pubSig, verifiablePresentation, circuits.AtomicQueryMTPV2CircuitID, opts...)
return CircuitVerificationResult{}, err
}

Expand Down
2 changes: 1 addition & 1 deletion pubsignals/atomicSigV2.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (c *AtomicQuerySigV2) VerifyQuery(
ValueArraySize: c.ValueArraySize,
IsRevocationChecked: c.IsRevocationChecked,
}
err := query.Check(ctx, schemaLoader, &pubSig, verifiablePresentation, false, opts...)
err := query.Check(ctx, schemaLoader, &pubSig, verifiablePresentation, circuits.AtomicQuerySigV2CircuitID, opts...)
return CircuitVerificationResult{}, err
}

Expand Down
2 changes: 1 addition & 1 deletion pubsignals/atomicV3.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (c *AtomicQueryV3) VerifyQuery(
Nullifier: c.Nullifier,
ProofType: c.ProofType,
}
err := query.Check(ctx, schemaLoader, &pubSig, verifiablePresentation, true, opts...)
err := query.Check(ctx, schemaLoader, &pubSig, verifiablePresentation, circuits.AtomicQueryV3CircuitID, opts...)
if err != nil {
return output, err
}
Expand Down
65 changes: 64 additions & 1 deletion pubsignals/common.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package pubsignals

import (
"bytes"
"context"
"encoding/json"
"fmt"
"math/big"
"strconv"

"github.com/iden3/go-circuits/v2"
"github.com/iden3/go-iden3-crypto/poseidon"
Expand Down Expand Up @@ -173,7 +175,7 @@ func ParseQueriesMetadata(ctx context.Context, credentialType, ldContextJSON str

func transformQueryValueToBigInts(_ context.Context, value any, ldType string) (out []*big.Int, err error) {
if value == nil {
return out, nil
return make([]*big.Int, 0), nil
}

listOfValues, ok := value.([]interface{})
Expand Down Expand Up @@ -201,6 +203,33 @@ func transformQueryValueToBigInts(_ context.Context, value any, ldType string) (
return []*big.Int{hashValue}, err
}

func isPositiveInteger(v interface{}) bool {
number, err := strconv.ParseFloat(fmt.Sprintf("%v", v), 64)
if err != nil {
// value is not a number
return true
}
return number >= 0
}

// IsValidOperation checks if operation and type are supported.
func IsValidOperation(typ string, op int) bool {
if op == circuits.NOOP {
return true
}

ops, ok := availableTypesOperations[typ]
if !ok {
// by default all unknown types will be considered as string
ops = availableTypesOperations[ld.XSDString]
_, ok = ops[op]
return ok
}

_, ok = ops[op]
return ok
}

func getKeyByValue(m map[string]int, targetValue int) (string, bool) {
for key, value := range m {
if value == targetValue {
Expand Down Expand Up @@ -237,3 +266,37 @@ func CalculateQueryHash(
})

}

func fieldValueFromVerifiablePresentation(ctx context.Context, verifiablePresentation json.RawMessage, schemaLoader ld.DocumentLoader, key string) (*big.Int, error) {
if verifiablePresentation == nil {
return nil, errors.New("selective disclosure value is missed")
}

mz, err := merklize.MerklizeJSONLD(ctx,
bytes.NewBuffer(verifiablePresentation),
merklize.WithDocumentLoader(schemaLoader))
if err != nil {
return nil, errors.Errorf("failed to merklize doc: %v", err)
}

merklizedPath, err := merklize.Options{DocumentLoader: schemaLoader}.
NewPathFromDocument(verifiablePresentation,
fmt.Sprintf("verifiableCredential.credentialSubject.%s", key))
if err != nil {
return nil, errors.Errorf("failed build path to '%s' key: %v", key, err)
}

proof, valueByPath, err := mz.Proof(ctx, merklizedPath)
if err != nil {
return nil, errors.Errorf("failed get raw value: %v", err)
}
if !proof.Existence {
return nil, errors.Errorf("path '%v' doesn't exist in document", merklizedPath.Parts())
}

mvBig, err := valueByPath.MtEntry()
if err != nil {
return nil, errors.Errorf("failed to hash value: %v", err)
}
return mvBig, nil
}
75 changes: 58 additions & 17 deletions pubsignals/linkedMultiQuery.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/iden3/go-schema-processor/v2/merklize"
"github.com/iden3/go-schema-processor/v2/utils"
"github.com/piprate/json-gold/ld"
"github.com/pkg/errors"
)

// LinkedMultiQuery is a wrapper for circuits.LinkedMultiQueryPubSignals.
Expand All @@ -23,7 +24,7 @@ func (c *LinkedMultiQuery) VerifyQuery(
ctx context.Context,
query Query,
schemaLoader ld.DocumentLoader,
_ json.RawMessage,
vp json.RawMessage,
_ map[string]interface{},
_ ...VerifyOpt,
) (CircuitVerificationResult, error) {
Expand Down Expand Up @@ -57,10 +58,21 @@ func (c *LinkedMultiQuery) VerifyQuery(
return outputs, err
}

queryHashes := []*big.Int{}
requests := []QueryRequest{}
querySignalsMeta := make(queryMetaPubSignals, len(c.CircuitQueryHash))
for i, q := range c.CircuitQueryHash {
querySignalsMeta[i] = struct {
OperatorOutput *big.Int
QueryHash *big.Int
}{OperatorOutput: c.OperatorOutput[i], QueryHash: q}
}

for i := 0; i < circuits.LinkedMultiQueryLength; i++ {
if i >= len(queriesMetadata) {
queryHashes = append(queryHashes, big.NewInt(0))
requests = append(requests, struct {
QueryMetadata *QueryMetadata
QueryHash *big.Int
}{QueryMetadata: nil, QueryHash: big.NewInt(0)})
continue
}

Expand All @@ -81,25 +93,40 @@ func (c *LinkedMultiQuery) VerifyQuery(
return outputs, err
}

queryHashes = append(queryHashes, queryHash)
requests = append(requests, struct {
QueryMetadata *QueryMetadata
QueryHash *big.Int
}{QueryMetadata: &queriesMetadata[i], QueryHash: queryHash})
}

circuitQueryHashArray := make(bigIntArray, len(c.CircuitQueryHash))
copy(circuitQueryHashArray, c.CircuitQueryHash)
sort.Sort(circuitQueryHashArray)
sortedPubsignalsMetadata := make(queryMetaPubSignals, len(c.CircuitQueryHash))
copy(sortedPubsignalsMetadata, querySignalsMeta)
sort.Sort(sortedPubsignalsMetadata)

calcQueryHashArray := make(bigIntArray, len(queryHashes))
copy(calcQueryHashArray, queryHashes)
sort.Sort(calcQueryHashArray)
sortedRequests := make(queryRequests, len(requests))
copy(sortedRequests, requests)
sort.Sort(sortedRequests)

if circuitQueryHashArray.Len() != calcQueryHashArray.Len() {
if sortedPubsignalsMetadata.Len() != sortedRequests.Len() {
return outputs, fmt.Errorf("query hashes do not match")
}

for i := 0; i < circuitQueryHashArray.Len(); i++ {
if circuitQueryHashArray[i].Cmp(calcQueryHashArray[i]) != 0 {
for i := 0; i < sortedPubsignalsMetadata.Len(); i++ {
if sortedPubsignalsMetadata[i].QueryHash.Cmp(sortedRequests[i].QueryHash) != 0 {
return outputs, fmt.Errorf("query hashes do not match")
}

if sortedRequests[i].QueryMetadata != nil && sortedRequests[i].QueryMetadata.Operator == circuits.SD {
disclosedValue, err2 := fieldValueFromVerifiablePresentation(ctx, vp, schemaLoader, sortedRequests[i].QueryMetadata.FieldName)
if err2 != nil {
return outputs, err2
}
if disclosedValue.Cmp(sortedPubsignalsMetadata[i].OperatorOutput) != 0 {
return outputs, errors.New("disclosed value is not in the proof outputs")

}
}

}

outputs = CircuitVerificationResult{
Expand All @@ -109,11 +136,25 @@ func (c *LinkedMultiQuery) VerifyQuery(
return outputs, nil
}

type bigIntArray []*big.Int
type QueryRequest struct {
QueryMetadata *QueryMetadata
QueryHash *big.Int
}
type QueryMetaPubSignals struct {
OperatorOutput *big.Int
QueryHash *big.Int
}
type queryMetaPubSignals []QueryMetaPubSignals

func (q queryMetaPubSignals) Len() int { return len(q) }
func (q queryMetaPubSignals) Swap(i, j int) { q[i], q[j] = q[j], q[i] }
func (q queryMetaPubSignals) Less(i, j int) bool { return q[i].QueryHash.Cmp(q[j].QueryHash) < 0 }

type queryRequests []QueryRequest

func (a bigIntArray) Len() int { return len(a) }
func (a bigIntArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a bigIntArray) Less(i, j int) bool { return a[i].Cmp(a[j]) < 0 }
func (q queryRequests) Len() int { return len(q) }
func (q queryRequests) Swap(i, j int) { q[i], q[j] = q[j], q[i] }
func (q queryRequests) Less(i, j int) bool { return q[i].QueryHash.Cmp(q[j].QueryHash) < 0 }

// VerifyStates verifies user state and issuer auth claim state in the smart contract.
func (c *LinkedMultiQuery) VerifyStates(_ context.Context, _ map[string]StateResolver, _ ...VerifyOpt) error {
Expand Down
Loading

0 comments on commit 8a7ec13

Please sign in to comment.