From 2feb516b9b79d594c381a51c73514baf2bfb8ada Mon Sep 17 00:00:00 2001 From: Oleg Lomaka Date: Fri, 3 Mar 2023 02:10:49 -0500 Subject: [PATCH] Iden3SparseMerkleTreeProof (#47) * new struct Iden3SparseMerkleTreeProof to unpack proofs of Iden3SparseMerkleTreeProofType type * fix lint errors --- .github/workflows/ci-lint.yaml | 2 +- go.mod | 4 +- go.sum | 8 ++-- loaders/http.go | 8 +++- verifiable/proof.go | 53 ++++++++++++++++++++++++++ verifiable/proof_test.go | 69 ++++++++++++++++++++++++++++++++++ 6 files changed, 135 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci-lint.yaml b/.github/workflows/ci-lint.yaml index c39dfd5..e72fc2f 100644 --- a/.github/workflows/ci-lint.yaml +++ b/.github/workflows/ci-lint.yaml @@ -15,4 +15,4 @@ jobs: go-version: 1.20.1 - uses: golangci/golangci-lint-action@v3 with: - version: v1.51.1 + version: v1.51.2 diff --git a/go.mod b/go.mod index f35e3de..34281e0 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/qri-io/jsonschema v0.2.1 github.com/stretchr/testify v1.8.1 - golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8 + golang.org/x/crypto v0.6.0 ) require ( @@ -47,6 +47,6 @@ require ( github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c // indirect go.opencensus.io v0.22.4 // indirect - golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect + golang.org/x/sys v0.5.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 0388f1c..773cb91 100644 --- a/go.sum +++ b/go.sum @@ -139,8 +139,8 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8 h1:kACShD3qhmr/3rLmg1yXyt+N4HcwutKyPRB93s54TIU= -golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -169,8 +169,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= diff --git a/loaders/http.go b/loaders/http.go index dbaf7d6..1b1c068 100644 --- a/loaders/http.go +++ b/loaders/http.go @@ -2,13 +2,14 @@ package loaders import ( "context" - "github.com/pkg/errors" "io" "log" "net/http" "net/url" "strings" "time" + + "github.com/pkg/errors" ) // ErrorURLEmpty is empty url error @@ -48,9 +49,12 @@ func (l HTTP) Load(ctx context.Context) (schema []byte, extension string, err er return nil, "", errors.WithMessage(err, "http request failed") } if resp.StatusCode != http.StatusOK { - return nil, "", errors.Errorf("request failed with status code %v", resp.StatusCode) + return nil, "", errors.Errorf("request failed with status code %v", + resp.StatusCode) } + //nolint:gosec //reason: remove it after fix for 49366 and uncomment + // following code defer resp.Body.Close() // TODO: https://github.com/golang/go/issues/49366 wait for fix diff --git a/verifiable/proof.go b/verifiable/proof.go index 2ad5abb..0a2a8c2 100644 --- a/verifiable/proof.go +++ b/verifiable/proof.go @@ -103,6 +103,8 @@ func (p *BJJSignatureProof2021) GetCoreClaim() (*core.Claim, error) { } // Iden3SparseMerkleProof JSON-LD structure +// +// Deprecated: replaced with Iden3SparseMerkleTreeProof type Iden3SparseMerkleProof struct { Type ProofType `json:"type"` @@ -149,6 +151,53 @@ func (p *Iden3SparseMerkleProof) GetCoreClaim() (*core.Claim, error) { return &coreClaim, err } +// Iden3SparseMerkleTreeProof JSON-LD structure +type Iden3SparseMerkleTreeProof struct { + Type ProofType `json:"type"` + + IssuerData IssuerData `json:"issuerData"` + CoreClaim string `json:"coreClaim"` + + MTP *mt.Proof `json:"mtp"` +} + +func (p *Iden3SparseMerkleTreeProof) UnmarshalJSON(in []byte) error { + var obj struct { + Type ProofType `json:"type"` + IssuerData json.RawMessage `json:"issuerData"` + CoreClaim string `json:"coreClaim"` + MTP *mt.Proof `json:"mtp"` + } + err := json.Unmarshal(in, &obj) + if err != nil { + return err + } + if obj.Type != Iden3SparseMerkleTreeProofType { + return errors.New("invalid proof type") + } + p.Type = obj.Type + err = json.Unmarshal(obj.IssuerData, &p.IssuerData) + if err != nil { + return err + } + if err := validateHexCoreClaim(obj.CoreClaim); err != nil { + return err + } + p.CoreClaim = obj.CoreClaim + p.MTP = obj.MTP + return nil +} + +func (p *Iden3SparseMerkleTreeProof) ProofType() ProofType { + return p.Type +} + +func (p *Iden3SparseMerkleTreeProof) GetCoreClaim() (*core.Claim, error) { + var coreClaim core.Claim + err := coreClaim.FromHex(p.CoreClaim) + return &coreClaim, err +} + // ProofPurpose is alias for string, represents proof purpose type ProofPurpose string @@ -235,6 +284,10 @@ func extractProof(proof any) (CredentialProof, error) { var proof Iden3SparseMerkleProof err := reUnmarshalFromObj(proofJ, &proof) return &proof, err + case Iden3SparseMerkleTreeProofType: + var proof Iden3SparseMerkleTreeProof + err := reUnmarshalFromObj(proofJ, &proof) + return &proof, err default: var proof CommonProof err := reUnmarshalFromObj(proofJ, &proof) diff --git a/verifiable/proof_test.go b/verifiable/proof_test.go index e24c06f..d4377d1 100644 --- a/verifiable/proof_test.go +++ b/verifiable/proof_test.go @@ -129,6 +129,69 @@ func TestIden3SparseMerkleProof_UnmarshalJSON(t *testing.T) { require.Equal(t, wantProof, proof) } +func TestIden3SparseMerkleTreeProof_UnmarshalJSON(t *testing.T) { + in := `{ + "type": "Iden3SparseMerkleTreeProof", + "issuerData": { + "id": "did:iden3:polygon:mumbai:wvEkzpApgwGHrSTxEFG6V6HrTCa5R2rwQ3XWAkrnG", + "state": { + "txId": "0x705881f799496f399321f7b3b0f9aab80e358e5fdacb877ef18f10afc8be156e", + "blockTimestamp": 1671180108, + "blockNumber": 29756768, + "rootOfRoots": "db07217f60526821e8c079802ebfbfb9cd07e42d4220ff72f264d9bddbe87d2f", + "claimsTreeRoot": "447b1dfd065752d099c4c8eeb181dfe1363c64491eb413f01d6e60daf6bc792e", + "revocationTreeRoot": "0000000000000000000000000000000000000000000000000000000000000000", + "value": "0bc71a0bdbf1a3e8513069b170c6b62601288fcf231f874b52e4e546dddcbb2d" + } + }, + "coreClaim": "c9b2370371b7fa8b3dab2a5ba81b68382a0000000000000000000000000000000112b4f1183b6a0708a8addd31c093004ac2e40ab1b291ad6d208244032b0c006947c37450a6a4c50a586e8a253dc8385d8d1ee77b37f464fe5052dc2f0dd8020000000000000000000000000000000000000000000000000000000000000000e29d235b00000000281cdcdf0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "mtp": { + "existence": true, + "siblings": [ + "0", + "13291429422163653257975736723599735973011351095941906941706092370486076739639", + "13426716414767621234869633661856285788095461522423569801792562280466318278688" + ] + } +}` + wantProof := Iden3SparseMerkleTreeProof{ + Type: Iden3SparseMerkleTreeProofType, + IssuerData: IssuerData{ + ID: "did:iden3:polygon:mumbai:wvEkzpApgwGHrSTxEFG6V6HrTCa5R2rwQ3XWAkrnG", + State: State{ + TxID: &[]string{"0x705881f799496f399321f7b3b0f9aab80e358e5fdacb877ef18f10afc8be156e"}[0], + BlockTimestamp: &[]int{1671180108}[0], + BlockNumber: &[]int{29756768}[0], + RootOfRoots: &[]string{"db07217f60526821e8c079802ebfbfb9cd07e42d4220ff72f264d9bddbe87d2f"}[0], + ClaimsTreeRoot: &[]string{"447b1dfd065752d099c4c8eeb181dfe1363c64491eb413f01d6e60daf6bc792e"}[0], + RevocationTreeRoot: &[]string{"0000000000000000000000000000000000000000000000000000000000000000"}[0], + Value: &[]string{"0bc71a0bdbf1a3e8513069b170c6b62601288fcf231f874b52e4e546dddcbb2d"}[0], + Status: "", + }, + AuthCoreClaim: "", + MTP: nil, + CredentialStatus: nil, + }, + CoreClaim: "c9b2370371b7fa8b3dab2a5ba81b68382a0000000000000000000000000000000112b4f1183b6a0708a8addd31c093004ac2e40ab1b291ad6d208244032b0c006947c37450a6a4c50a586e8a253dc8385d8d1ee77b37f464fe5052dc2f0dd8020000000000000000000000000000000000000000000000000000000000000000e29d235b00000000281cdcdf0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + MTP: mustProof(t, true, []*mt.Hash{ + mustHash(t, "0"), + mustHash(t, + "13291429422163653257975736723599735973011351095941906941706092370486076739639"), + mustHash(t, + "13426716414767621234869633661856285788095461522423569801792562280466318278688"), + }), + } + var proof Iden3SparseMerkleTreeProof + err := json.Unmarshal([]byte(in), &proof) + require.NoError(t, err) + require.Equal(t, wantProof, proof) + + var proof2 Iden3SparseMerkleTreeProof + err = proof2.UnmarshalJSON([]byte(in)) + require.NoError(t, err) + require.Equal(t, wantProof, proof2) +} + func TestCommonProof_UnmarshalJSON(t *testing.T) { in := `{ "type": "Ed25519Signature2020", @@ -267,3 +330,9 @@ func TestCredentialProofs_UnmarshalJSON(t *testing.T) { } require.Equal(t, want, p) } + +func TestIden3SparseMerkleTreeProofType_is_CredentialProof(t *testing.T) { + var p Iden3SparseMerkleTreeProof + var cp CredentialProof = &p + _ = cp +}