diff --git a/.github/workflows/tests-c.yaml b/.github/workflows/tests-c.yaml index ea6d9cc..e21cfa0 100644 --- a/.github/workflows/tests-c.yaml +++ b/.github/workflows/tests-c.yaml @@ -14,7 +14,7 @@ jobs: strategy: matrix: containers: - - 1.21.1-bullseye + - 1.21.4-bullseye runs-on: ubuntu-22.04 container: golang:${{matrix.containers}} steps: diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 395ba6b..a9c8279 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -11,7 +11,7 @@ jobs: strategy: matrix: containers: - - 1.21.1-bullseye + - 1.21.4-bullseye runs-on: ubuntu-20.04 container: golang:${{ matrix.containers }} env: diff --git a/cmd/polygonid/polygonid.go b/cmd/polygonid/polygonid.go index 8302a77..01a55fd 100644 --- a/cmd/polygonid/polygonid.go +++ b/cmd/polygonid/polygonid.go @@ -575,13 +575,9 @@ func PLGNProfileID(jsonResponse **C.char, in *C.char, // Additional configuration may be required for Reverse Hash Service // revocation validation. In other case cfg may be nil. // -// Sample configuration: +// The configuration example may be found in the [README.md] file. // -// { -// "ethereumUrl": "http://localhost:8545", -// "stateContractAddr": "0xEA9aF2088B4a9770fC32A12fD42E61BDD317E655", -// "reverseHashServiceUrl": "http://localhost:8003" -// } +// [README.md]: https://github.com/0xPolygonID/c-polygonid/blob/main/README.md#configuration // //export PLGNAtomicQuerySigV2Inputs func PLGNAtomicQuerySigV2Inputs(jsonResponse **C.char, in *C.char, cfg *C.char, @@ -667,13 +663,9 @@ func marshalInputsResponse( // Additional configuration may be required for Reverse Hash Service // revocation validation. In other case cfg may be nil. // -// Sample configuration: +// The configuration example may be found in the [README.md] file. // -// { -// "ethereumUrl": "http://localhost:8545", -// "stateContractAddr": "0xEA9aF2088B4a9770fC32A12fD42E61BDD317E655", -// "reverseHashServiceUrl": "http://localhost:8003" -// } +// [README.md]: https://github.com/0xPolygonID/c-polygonid/blob/main/README.md#configuration // //export PLGNAtomicQueryMtpV2Inputs func PLGNAtomicQueryMtpV2Inputs(jsonResponse **C.char, in *C.char, cfg *C.char, @@ -734,13 +726,9 @@ func PLGNMtpV2Inputs(jsonResponse **C.char, in *C.char, // Additional configuration may be required for Reverse Hash Service // revocation validation. In other case cfg may be nil. // -// Sample configuration: +// The configuration example may be found in the [README.md] file. // -// { -// "ethereumUrl": "http://localhost:8545", -// "stateContractAddr": "0xEA9aF2088B4a9770fC32A12fD42E61BDD317E655", -// "reverseHashServiceUrl": "http://localhost:8003" -// } +// [README.md]: https://github.com/0xPolygonID/c-polygonid/blob/main/README.md#configuration // //export PLGNAtomicQuerySigV2OnChainInputs func PLGNAtomicQuerySigV2OnChainInputs(jsonResponse **C.char, in *C.char, @@ -759,13 +747,9 @@ func PLGNAtomicQuerySigV2OnChainInputs(jsonResponse **C.char, in *C.char, // Additional configuration may be required for Reverse Hash Service // revocation validation. In other case cfg may be nil. // -// Sample configuration: +// The configuration example may be found in the [README.md] file. // -// { -// "ethereumUrl": "http://localhost:8545", -// "stateContractAddr": "0xEA9aF2088B4a9770fC32A12fD42E61BDD317E655", -// "reverseHashServiceUrl": "http://localhost:8003" -// } +// [README.md]: https://github.com/0xPolygonID/c-polygonid/blob/main/README.md#configuration // //export PLGNAtomicQueryMtpV2OnChainInputs func PLGNAtomicQueryMtpV2OnChainInputs(jsonResponse **C.char, in *C.char, @@ -861,6 +845,70 @@ func PLGNCacheCredentials(in *C.char, cfg *C.char, status **C.PLGNStatus) bool { return true } +// PLGNW3CCredentialFromOnchainHex returns a verifiable credential from an onchain data hex string. +// +// Sample input: +// +// { +// "issuerDID": "did:polygonid:polygon:mumbai:2qCU58EJgrEMJvPfhUCnFCwuKQTkX8VmJX2sJCH6C8", +// "hexdata": "0x0...", +// "version": "0.0.1" +// } +// +// The configuration example may be found in the [README.md] file. +// +// [README.md]: https://github.com/0xPolygonID/c-polygonid/blob/main/README.md#configuration +// +//export PLGNW3CCredentialFromOnchainHex +func PLGNW3CCredentialFromOnchainHex(jsonResponse **C.char, in *C.char, + cfg *C.char, status **C.PLGNStatus) bool { + + if jsonResponse == nil { + maybeCreateStatus(status, C.PLGNSTATUSCODE_NIL_POINTER, + "jsonResponse pointer is nil") + return false + } + + if in == nil { + maybeCreateStatus(status, C.PLGNSTATUSCODE_NIL_POINTER, + "pointer to request is nil") + return false + } + + ctx, cancel := logAPITime() + defer cancel() + + ctx2, cancel2 := context.WithTimeout(ctx, defaultTimeout) + defer cancel2() + + inData := C.GoBytes(unsafe.Pointer(in), C.int(C.strlen(in))) + + envCfg, err := createEnvConfig(cfg) + if err != nil { + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + return false + } + + credential, err := c_polygonid.W3CCredentialFromOnchainHex( + ctx2, + envCfg, + inData, + ) + if err != nil { + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + return false + } + + credentialJSON, err := json.Marshal(credential) + if err != nil { + maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, err.Error()) + return false + } + + *jsonResponse = C.CString(string(credentialJSON)) + return true +} + // createEnvConfig returns empty config if input json is nil. func createEnvConfig(cfgJson *C.char) (c_polygonid.EnvConfig, error) { var cfgData []byte diff --git a/go.mod b/go.mod index 0584373..3f13029 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,15 @@ module github.com/0xPolygonID/c-polygonid -go 1.21 +go 1.21.4 require ( github.com/dgraph-io/badger/v4 v4.2.0 - github.com/ethereum/go-ethereum v1.13.11 - github.com/iden3/contracts-abi/state/go/abi v0.0.0-20230405152923-4a25f6f1f0f4 + github.com/ethereum/go-ethereum v1.13.12 github.com/iden3/go-circuits/v2 v2.0.1 - github.com/iden3/go-iden3-core/v2 v2.0.4-0.20240129182142-32180363999b + github.com/iden3/go-iden3-core/v2 v2.0.4 github.com/iden3/go-iden3-crypto v0.0.15 github.com/iden3/go-merkletree-sql/v2 v2.0.6 + github.com/iden3/go-onchain-credential-adapter v0.0.0-20240223120548-5d8d1d28c6d1 github.com/iden3/go-schema-processor/v2 v2.3.0 github.com/iden3/merkletree-proof v0.1.0 github.com/piprate/json-gold v0.5.1-0.20230111113000-6ddbe6e6f19f @@ -44,6 +44,8 @@ require ( github.com/gorilla/websocket v1.5.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect github.com/iden3/contracts-abi/onchain-credential-status-resolver/go/abi v0.0.0-20230911113809-c58b7e7a69b0 // indirect + github.com/iden3/contracts-abi/onchain-non-merklized-issuer-base/v0/go/abi v0.0.0-20240222110004-06aa097d1318 // indirect + github.com/iden3/contracts-abi/state/go/abi v0.0.0-20230405152923-4a25f6f1f0f4 // indirect github.com/klauspost/compress v1.16.5 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect diff --git a/go.sum b/go.sum index 67d2b86..ad51405 100644 --- a/go.sum +++ b/go.sum @@ -83,10 +83,10 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.13.11 h1:b51Dsm+rEg7anFRUMGB8hODXHvNfcRKzz9vcj8wSdUs= -github.com/ethereum/go-ethereum v1.13.11/go.mod h1:gFtlVORuUcT+UUIcJ/veCNjkuOSujCi338uSHJrYAew= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/ethereum/go-ethereum v1.13.12 h1:iDr9UM2JWkngBHGovRJEQn4Kor7mT4gt9rUZqB5M29Y= +github.com/ethereum/go-ethereum v1.13.12/go.mod h1:hKL2Qcj1OvStXNSEDbucexqnEt1Wh4Cz329XsjAalZY= +github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= +github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= @@ -156,16 +156,20 @@ github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/iden3/contracts-abi/onchain-credential-status-resolver/go/abi v0.0.0-20230911113809-c58b7e7a69b0 h1:Fu1/tAINi9FzZ0nKoEVOGXWzL1l15tR1loJx5sQEQ8k= github.com/iden3/contracts-abi/onchain-credential-status-resolver/go/abi v0.0.0-20230911113809-c58b7e7a69b0/go.mod h1:8fkd2xyUG/V7ovpvZRyD2LyK2zZ4ALbgf5vJGyhzKdg= +github.com/iden3/contracts-abi/onchain-non-merklized-issuer-base/v0/go/abi v0.0.0-20240222110004-06aa097d1318 h1:uCDKrWlaN4WT5Yrbjc3DxwMxQsWor26w9Q0polWU4PE= +github.com/iden3/contracts-abi/onchain-non-merklized-issuer-base/v0/go/abi v0.0.0-20240222110004-06aa097d1318/go.mod h1:vMgeBNntJeIDZrIDY0d6sZQU+JigUo4h+m95qeU03ew= github.com/iden3/contracts-abi/state/go/abi v0.0.0-20230405152923-4a25f6f1f0f4 h1:iPvYa/AhhGo3juoUFDm/fBE2CZKy4WfQu7JY90tRf9Q= github.com/iden3/contracts-abi/state/go/abi v0.0.0-20230405152923-4a25f6f1f0f4/go.mod h1:TxgIrXCvxms3sbOdsy8kTvffUCIpEEifNy0fSXdkU4w= github.com/iden3/go-circuits/v2 v2.0.1 h1:tcJtBE8aLJsf9qpBoTUKE143Mne025cunQnSExMXaKo= github.com/iden3/go-circuits/v2 v2.0.1/go.mod h1:VIFIp51+IH0hOzjnKhb84bCeyq7hq76zX/C14ua6zh4= -github.com/iden3/go-iden3-core/v2 v2.0.4-0.20240129182142-32180363999b h1:9tdFuHcaCiHy7xehrY6bIWlSPlPZH8H7jYU3pFvWIP0= -github.com/iden3/go-iden3-core/v2 v2.0.4-0.20240129182142-32180363999b/go.mod h1:L9PxhWPvoS9qTb3inEkZBm1RpjHBt+VTwvxssdzbAdw= +github.com/iden3/go-iden3-core/v2 v2.0.4 h1:ggzC2zgOWgJAAcuG9X8bQG1r4gAoHZWqY7aLV8b1qgc= +github.com/iden3/go-iden3-core/v2 v2.0.4/go.mod h1:L9PxhWPvoS9qTb3inEkZBm1RpjHBt+VTwvxssdzbAdw= github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4= github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= github.com/iden3/go-merkletree-sql/v2 v2.0.6 h1:vsVDImnvnHf7Ggr45ptFOXJyWNA/8IwVQO1jzRLUlY8= github.com/iden3/go-merkletree-sql/v2 v2.0.6/go.mod h1:kRhHKYpui5DUsry5RpveP6IC4XMe6iApdV9VChRYuEk= +github.com/iden3/go-onchain-credential-adapter v0.0.0-20240223120548-5d8d1d28c6d1 h1:xpKhrLYi0s6ocUCrFwkjG0YQjndDGMW7/cgU9KjLyig= +github.com/iden3/go-onchain-credential-adapter v0.0.0-20240223120548-5d8d1d28c6d1/go.mod h1:1RVClY0JdWmzgx3ZBvy0Z2bNyPg2iz+0R9Ryl2Z3s64= github.com/iden3/go-schema-processor/v2 v2.3.0 h1:86tnt1myHntcG+9pJ3I+0ycc6V59sITrsPSt0k7/DhU= github.com/iden3/go-schema-processor/v2 v2.3.0/go.mod h1:BcHVDZyn8q8vUlL+XpOo7hpwXmEjxzO8ao1LkvFsM+k= github.com/iden3/merkletree-proof v0.1.0 h1:AHmpkbCTLKv1MWWt6YwogB65E4y6UZthbZYPed81w4U= diff --git a/inputs_sig_test.go b/inputs_sig_test.go index f525aa5..825d080 100644 --- a/inputs_sig_test.go +++ b/inputs_sig_test.go @@ -60,6 +60,24 @@ func preserveIPFSHttpCli() func() { } } +func removeIdFromEthBody(body []byte) []byte { + var ethBody map[string]any + err := json.Unmarshal(body, ðBody) + if err != nil { + panic(err) + } + if stringFromJsonObj(ethBody, "jsonrpc") == "2.0" && + stringFromJsonObj(ethBody, "method") == "eth_call" { + + delete(ethBody, "id") + } + body, err = json.Marshal(ethBody) + if err != nil { + panic(err) + } + return body +} + func TestPrepareInputs(t *testing.T) { defer mockBadgerLog(t)() @@ -88,20 +106,6 @@ func TestPrepareInputs(t *testing.T) { } } - removeIdFromEthBody := func(body []byte) []byte { - var ethBody map[string]any - err := json.Unmarshal(body, ðBody) - require.NoError(t, err) - if stringFromJsonObj(ethBody, "jsonrpc") == "2.0" && - stringFromJsonObj(ethBody, "method") == "eth_call" { - - delete(ethBody, "id") - } - body, err = json.Marshal(ethBody) - require.NoError(t, err) - return body - } - t.Run("AtomicQueryMtpV2Onchain", func(t *testing.T) { defer httpmock.MockHTTPClient(t, map[string]string{ diff --git a/onchain_adapter.go b/onchain_adapter.go new file mode 100644 index 0000000..272cbf5 --- /dev/null +++ b/onchain_adapter.go @@ -0,0 +1,67 @@ +package c_polygonid + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/ethereum/go-ethereum/ethclient" + core "github.com/iden3/go-iden3-core/v2" + "github.com/iden3/go-iden3-core/v2/w3c" + convertor "github.com/iden3/go-onchain-credential-adapter" + "github.com/iden3/go-schema-processor/v2/merklize" + "github.com/iden3/go-schema-processor/v2/verifiable" +) + +type w3CCredentialFromOnchainHexRequest struct { + IssuerDID coreDID `json:"issuerDID"` + Hexdata string `json:"hexdata"` + Version string `json:"version"` +} + +func W3CCredentialFromOnchainHex( + ctx context.Context, + envCfg EnvConfig, + in []byte, +) (*verifiable.W3CCredential, error) { + var inParams w3CCredentialFromOnchainHexRequest + if err := json.Unmarshal(in, &inParams); err != nil { + return nil, fmt.Errorf("failed to unmarshal input params: %w", err) + } + + issuerDID := w3c.DID(inParams.IssuerDID) + + chainID, err := core.ChainIDfromDID(issuerDID) + if err != nil { + return nil, fmt.Errorf("failed to get chain id from issuer: %w", err) + } + chainConfig, ok := envCfg.ChainConfigs[chainID] + if !ok { + return nil, fmt.Errorf("chain id '%d' not found in config", chainID) + } + + ethcli, err := ethclient.DialContext(ctx, chainConfig.RPCUrl) + if err != nil { + return nil, + fmt.Errorf("failed to connect to ethereum: %w", err) + } + defer ethcli.Close() + + credential, err := convertor.W3CCredentialFromOnchainHex( + ctx, + ethcli, + &issuerDID, + inParams.Hexdata, + inParams.Version, + convertor.WithMerklizeOptions( + merklize.Options{ + DocumentLoader: envCfg.documentLoader(), + }, + ), + ) + if err != nil { + return nil, + fmt.Errorf("failed to convert onchain hex to W3C credential: %w", err) + } + return credential, nil +} diff --git a/onchain_adapter_test.go b/onchain_adapter_test.go new file mode 100644 index 0000000..e999b72 --- /dev/null +++ b/onchain_adapter_test.go @@ -0,0 +1,68 @@ +package c_polygonid + +import ( + "context" + "encoding/json" + "testing" + + httpmock "github.com/0xPolygonID/c-polygonid/testing" + core "github.com/iden3/go-iden3-core/v2" + "github.com/iden3/go-schema-processor/v2/verifiable" + "github.com/stretchr/testify/require" +) + +func TestW3CCredentialFromOnchainHex(t *testing.T) { + defer mockBadgerLog(t)() + + doTest := func(t testing.TB, inFile, wantOutFile string, cfg EnvConfig) { + ctx := context.Background() + in := readFixtureFile(inFile) + wantOut := readFixtureFile(wantOutFile) + + out, err := W3CCredentialFromOnchainHex( + ctx, + cfg, + in, + ) + require.NoError(t, err) + + var wantOutCredential *verifiable.W3CCredential + err = json.Unmarshal(wantOut, &wantOutCredential) + require.NoError(t, err) + + // since want verifiable credential was parsed from json, + // there not are types for the fields + var actualOutCredential *verifiable.W3CCredential + err = remarshalObj(&actualOutCredential, out) + require.NoError(t, err) + + require.Equal(t, wantOutCredential, actualOutCredential) + } + + t.Run("happy path", func(t *testing.T) { + defer httpmock.MockHTTPClient(t, + map[string]string{ + `http://localhost:8545%%%{"jsonrpc":"2.0","method":"eth_call","params":[{"from":"0x0000000000000000000000000000000000000000","input":"0xb37feda415bbb043d40cadbd377aeb19ef410cd8adb55a41c63707a628fefa0fac2c3ba1","to":"0xc84e8ac5385e0813f01aa9c698ed44c831961670"},"latest"]}`: "testdata/httpresp_eth_mtp_proof_onchain_issuer.json", + "https://schema.iden3.io/core/jsonld/iden3proofs.jsonld": "testdata/httpresp_iden3proofs.jsonld", + "https://gist.githubusercontent.com/ilya-korotya/660496c859f8d31a7d2a92ca5e970967/raw/6b5fc14fe630c17bfa52e05e08fdc8394c5ea0ce/non-merklized-non-zero-balance.jsonld": "testdata/httpresp_non-merklized-non-zero-balance.jsonld", + "https://schema.iden3.io/core/jsonld/displayMethod.jsonld": "testdata/httpresp_displayMethod.jsonld", + }, + httpmock.IgnoreUntouchedURLs(), + httpmock.WithPostRequestBodyProcessor(removeIdFromEthBody), + )() + cfg := EnvConfig{ + ChainConfigs: map[core.ChainID]ChainConfig{ + 80001: { + RPCUrl: "http://localhost:8545", + }, + }, + } + + doTest( + t, + "w3c_credential_from_onchain_hex_input.json", + "w3c_credential_from_onchain_hex_output.json", + cfg, + ) + }) +} diff --git a/testdata/httpresp_displayMethod.jsonld b/testdata/httpresp_displayMethod.jsonld new file mode 100644 index 0000000..7a13188 --- /dev/null +++ b/testdata/httpresp_displayMethod.jsonld @@ -0,0 +1,19 @@ +{ + "@context": { + "@version": 1.1, + "@protected": true, + "id": "@id", + "type": "@type", + "displayMethod": { + "@id": "https://schema.iden3.io/core/vocab/displayMethod.md#displayMethod", + "@type": "@id", + "@context": { + "@version": 1.1, + "@protected": true, + "id": "@id", + "type": "@type", + "Iden3BasicDisplayMethodV1": "https://schema.iden3.io/core/vocab/displayMethod.md#Iden3BasicDisplayMethodV1" + } + } + } +} \ No newline at end of file diff --git a/testdata/httpresp_eth_mtp_proof_onchain_issuer.json b/testdata/httpresp_eth_mtp_proof_onchain_issuer.json new file mode 100644 index 0000000..e135ff1 --- /dev/null +++ b/testdata/httpresp_eth_mtp_proof_onchain_issuer.json @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x00000000000000000000000000000000000000000000000000000000000000a026ab96fbcfb7a137e7acd773909a14ce77de394252318b5cca4c00131fd95d6f2ec78fb0a9f5898469243a85cc4a2fe97a0a95c00a95c4b50edad7d4ea01a73c00000000000000000000000000000000000000000000000000000000000000000ec7af27591b23ea49b849ddd31c1073bde30753b6cfbb727611a2cffe33a6192ec78fb0a9f5898469243a85cc4a2fe97a0a95c00a95c4b50edad7d4ea01a73c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010015bbb043d40cadbd377aeb19ef410cd8adb55a41c63707a628fefa0fac2c3ba126280d1f3ca6d144c0fedf0519644786c96d821dcc947576ecbbb4a175279ab700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280a6002414282733c9a4a2b7ccf5ad7cd2d9eea2c6cf0c03d7dbac53da6a60577000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} \ No newline at end of file diff --git a/testdata/httpresp_non-merklized-non-zero-balance.jsonld b/testdata/httpresp_non-merklized-non-zero-balance.jsonld new file mode 100644 index 0000000..ea6d74f --- /dev/null +++ b/testdata/httpresp_non-merklized-non-zero-balance.jsonld @@ -0,0 +1,28 @@ +{ + "@context": [ + { + "@protected": true, + "@version": 1.1, + "id": "@id", + "type": "@type", + "Balance": { + "@context": { + "@propagate": true, + "@protected": true, + "polygon-vocab": "urn:uuid:a33d80ea-88c9-4c70-a321-fc7bc9ef9cc4#", + "iden3_serialization": "iden3:v1:slotIndexA=address&slotIndexB=balance", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "address": { + "@id": "polygon-vocab:address", + "@type": "xsd:positiveInteger" + }, + "balance": { + "@id": "polygon-vocab:balance", + "@type": "xsd:positiveInteger" + } + }, + "@id": "urn:uuid:4dac09b1-2c08-47bc-abc7-c6ecef9be36b" + } + } + ] +} diff --git a/testdata/w3c_credential_from_onchain_hex_input.json b/testdata/w3c_credential_from_onchain_hex_input.json new file mode 100644 index 0000000..2a385e6 --- /dev/null +++ b/testdata/w3c_credential_from_onchain_hex_input.json @@ -0,0 +1,5 @@ +{ + "issuerDID": "did:polygonid:polygon:mumbai:2qCU58EJgrEMJvPfhUCnFCwuKQTkX8VmJX2sJCH6C8", + "hexdata": "0x00000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000a6ff88524b07a4eaab4d733c595172ff5000d60ad1dea10b097b1ab7638b962383c12d17575437e63c9786fff897f12020000000000000000000000007317d19889c6dcc9ce9b894133d33d8d51cbb60e000000000000000000000000000000000000000000000000026aa26cb85e6dd1000000000000000000000000000000000000000065feb77600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000065d72a7600000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000a368747470733a2f2f676973742e67697468756275736572636f6e74656e742e636f6d2f696c79612d6b6f726f7479612f36363034393663383539663864333161376432613932636135653937303936372f7261772f366235666331346665363330633137626661353265303565303866646338333934633565613063652f6e6f6e2d6d65726b6c697a65642d6e6f6e2d7a65726f2d62616c616e63652e6a736f6e6c640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003868747470733a2f2f736368656d612e6964656e332e696f2f636f72652f6a736f6e6c642f646973706c61794d6574686f642e6a736f6e6c640000000000000000000000000000000000000000000000000000000000000000000000000000000742616c616e6365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000a168747470733a2f2f676973742e67697468756275736572636f6e74656e742e636f6d2f696c79612d6b6f726f7479612f65313063643739613863633236616236653430343030613131383338363137652f7261772f353735656463333364343835653261346338303662616164393765323131313766336339306139662f6e6f6e2d6d65726b6c697a65642d6e6f6e2d7a65726f2d62616c616e63652e6a736f6e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4a736f6e536368656d6132303233000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d53386559385a436941415738716778335436535133484447656464774c5a736a50584e415a45785177525934000000000000000000000000000000000000000000000000000000000000000000000000000000000000194964656e334261736963446973706c61794d6574686f645631000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000026aa26cb85e6dd100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000762616c616e636500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000007317d19889c6dcc9ce9b894133d33d8d51cbb60e00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000761646472657373000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "version": "0.0.1" +} diff --git a/testdata/w3c_credential_from_onchain_hex_output.json b/testdata/w3c_credential_from_onchain_hex_output.json new file mode 100644 index 0000000..2fdb0f7 --- /dev/null +++ b/testdata/w3c_credential_from_onchain_hex_output.json @@ -0,0 +1,56 @@ +{ + "id": "urn:iden3:onchain:80001:0xc84e8ac5385E0813f01aA9C698ED44C831961670:0", + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://schema.iden3.io/core/jsonld/iden3proofs.jsonld", + "https://gist.githubusercontent.com/ilya-korotya/660496c859f8d31a7d2a92ca5e970967/raw/6b5fc14fe630c17bfa52e05e08fdc8394c5ea0ce/non-merklized-non-zero-balance.jsonld", + "https://schema.iden3.io/core/jsonld/displayMethod.jsonld" + ], + "type": [ + "VerifiableCredential", + "Balance" + ], + "expirationDate": "2024-03-23T11:05:26Z", + "issuanceDate": "2024-02-22T11:05:26Z", + "credentialSubject": { + "address": "657065114158124047812701241180089030040156354062", + "balance": "174130123440549329", + "id": "did:polygonid:polygon:mumbai:2qJFtKfABTJi2yUAcUhuvUnDojuNwUJjhuXQDhUg3e", + "type": "Balance" + }, + "credentialStatus": { + "id": "did:polygonid:polygon:mumbai:2qCU58EJgrEMJvPfhUCnFCwuKQTkX8VmJX2sJCH6C8/credentialStatus?revocationNonce=0\u0026contractAddress=80001:0xc84e8ac5385E0813f01aA9C698ED44C831961670", + "type": "Iden3OnchainSparseMerkleTreeProof2023", + "revocationNonce": 0 + }, + "issuer": "did:polygonid:polygon:mumbai:2qCU58EJgrEMJvPfhUCnFCwuKQTkX8VmJX2sJCH6C8", + "credentialSchema": { + "id": "https://gist.githubusercontent.com/ilya-korotya/e10cd79a8cc26ab6e40400a11838617e/raw/575edc33d485e2a4c806baad97e21117f3c90a9f/non-merklized-non-zero-balance.json", + "type": "JsonSchema2023" + }, + "proof": [ + { + "type": "Iden3SparseMerkleTreeProof", + "issuerData": { + "id": "did:polygonid:polygon:mumbai:2qCU58EJgrEMJvPfhUCnFCwuKQTkX8VmJX2sJCH6C8", + "state": { + "rootOfRoots": "19a633fecfa2117672bbcfb65307e3bd73101cd3dd49b849ea231b5927afc70e", + "claimsTreeRoot": "3ca701ead4d7da0eb5c4950ac0950a7ae92f4acc853a24698489f5a9b08fc72e", + "revocationTreeRoot": "0000000000000000000000000000000000000000000000000000000000000000", + "value": "6f5dd91f13004cca5c8b31524239de77ce149a9073d7ace737a1b7cffb96ab26" + } + }, + "coreClaim": "f52f1795c533d7b4aa4e7ab02485f86f0a00000000000000000000000000000002127f89ff6f78c9637e437575d1123c3862b93876abb197b010ea1dad600d000eb6cb518d3dd33341899bcec9dcc68998d11773000000000000000000000000d16d5eb86ca26a02000000000000000000000000000000000000000000000000000000000000000076b7fe650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "mtp": { + "existence": true, + "siblings": [ + "4692761366944891051814480185546124875872606319832740381039122455881379612023" + ] + } + } + ], + "displayMethod": { + "id": "ipfs://QmS8eY8ZCiAAW8qgx3T6SQ3HDGeddwLZsjPXNAZExQwRY4", + "type": "Iden3BasicDisplayMethodV1" + } +} \ No newline at end of file diff --git a/types.go b/types.go index 45b8539..f349c89 100644 --- a/types.go +++ b/types.go @@ -12,6 +12,7 @@ import ( "strings" core "github.com/iden3/go-iden3-core/v2" + "github.com/iden3/go-iden3-core/v2/w3c" "github.com/iden3/go-iden3-crypto/babyjub" "github.com/iden3/go-iden3-crypto/utils" ) @@ -169,3 +170,25 @@ func (i *JsonFieldIntStr) UnmarshalJSON(bytes []byte) error { func (i *JsonFieldIntStr) Int() *big.Int { return (*big.Int)(i) } + +type coreDID w3c.DID + +func (d *coreDID) UnmarshalJSON(bytes []byte) error { + var s *string + err := json.Unmarshal(bytes, &s) + if err != nil { + return err + } + if s == nil { + *d = coreDID(w3c.DID{}) + return nil + } + + did, err := w3c.ParseDID(*s) + if err != nil { + return err + } + + *d = coreDID(*did) + return nil +}