From dba2a03697af1fb109a21e19973865230211fd88 Mon Sep 17 00:00:00 2001 From: Mihai Chiorean Date: Fri, 22 Mar 2024 17:03:36 -0700 Subject: [PATCH 1/7] Add web5 spec resolve test vectors for did dht --- .gitmodules | 3 + dids/diddht/resolver.go | 8 +-- dids/diddht/resolver_test.go | 119 +++++++++++++++++++++++++++++++++++ web5-spec | 1 + 4 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 .gitmodules create mode 100644 dids/diddht/resolver_test.go create mode 160000 web5-spec diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a4d13ed --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "web5-spec"] + path = web5-spec + url = git@github.com:TBD54566975/web5-spec.git diff --git a/dids/diddht/resolver.go b/dids/diddht/resolver.go index a771996..8cfb3ed 100644 --- a/dids/diddht/resolver.go +++ b/dids/diddht/resolver.go @@ -48,27 +48,27 @@ func (r *Resolver) ResolveWithContext(ctx context.Context, uri string) (didcore. } if did.Method != "dht" { - return didcore.ResolutionResultWithError("invalidDid"), didcore.ResolutionError{Code: "invalidDid"} + return didcore.ResolutionResultWithError("methodNotSupported"), didcore.ResolutionError{Code: "methodNotSupported"} } // 2. ensure did ID is zbase32 identifier, err := zbase32.DecodeString(did.ID) if err != nil { // TODO log err - return didcore.ResolutionResultWithError("invalidDid"), didcore.ResolutionError{Code: "invalidDid"} + return didcore.ResolutionResultWithError("invalidPublicKey"), didcore.ResolutionError{Code: "invalidPublicKey"} } if len(identifier) == 0 { // return nil, fmt.Errorf("no bytes decoded from zbase32 identifier %s", did.ID) // TODO log err - return didcore.ResolutionResultWithError("invalidDid"), didcore.ResolutionError{Code: "invalidDid"} + return didcore.ResolutionResultWithError("invalidPublicKey"), didcore.ResolutionError{Code: "invalidPublicKey"} } // 3. fetch from the relay bep44Message, err := r.relay.FetchWithContext(ctx, did.ID) if err != nil { // TODO log err - return didcore.ResolutionResultWithError("invalidDid"), didcore.ResolutionError{Code: "invalidDid"} + return didcore.ResolutionResultWithError("notFound"), didcore.ResolutionError{Code: "notFound"} } // get the dns payload from the bep44 message diff --git a/dids/diddht/resolver_test.go b/dids/diddht/resolver_test.go new file mode 100644 index 0000000..7bd3e12 --- /dev/null +++ b/dids/diddht/resolver_test.go @@ -0,0 +1,119 @@ +package diddht + +import ( + "encoding/hex" + "encoding/json" + "net/http" + "net/http/httptest" + "os" + "testing" + + "github.com/alecthomas/assert/v2" +) + +const dhtSpecVectors string = "../../web5-spec/test-vectors/did_dht/resolve.json" + +type vector struct { + Description string `json:"description"` + Input struct { + DIDUri string `json:"didUri"` + } `json:"input"` + Output struct { + DIDResolutionMetadata struct { + Error string `json:"error"` + } `json:"didResolutionMetadata"` + } `json:"output"` + Errors bool `json:"errors"` +} + +func initVector() ([]vector, error) { + // Load test vectors from file + data, err := os.ReadFile(dhtSpecVectors) + if err != nil { + return nil, err + } + + // Unmarshal test vectors + vectorData := struct { + Vectors []vector `json:"vectors"` + }{} + if err := json.Unmarshal(data, &vectorData); err != nil { + return nil, err + } + return vectorData.Vectors, nil +} + +func Test_resolve_failures(t *testing.T) { + vectors, err := initVector() + assert.NoError(t, err) + + mocks := map[string]vector{} + for _, v := range vectors { + mocks[v.Input.DIDUri] = v + } + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) + return + })) + defer ts.Close() + + r := NewResolver(ts.URL, http.DefaultClient) + + for _, v := range vectors { + vector := v + t.Run(vector.Description, func(t *testing.T) { + res, err := r.Resolve(vector.Input.DIDUri) + if vector.Errors { + assert.True(t, err != nil) + assert.Equal(t, res.ResolutionMetadata.Error, vector.Output.DIDResolutionMetadata.Error) + } + }) + } +} + +func Test_resolve(t *testing.T) { + + // vector taken from https://github.com/TBD54566975/web5-js/blob/91d52aaa9410db5e5f7c3c31ebfe0d4956028496/packages/dids/tests/methods/did-dht.spec.ts#L725 + vectors := map[string]string{ + "did:dht:9tjoow45ef1hksoo96bmzkwwy3mhme95d7fsi3ezjyjghmp75qyo": "ea33e704f3a48a3392f54b28744cdfb4e24780699f92ba7df62fd486d2a2cda3f263e1c6bcbd" + + "75d438be7316e5d6e94b13e98151f599cfecefad0b37432bd90a0000000065b0ed1600008400" + + "0000000300000000035f6b30045f6469643439746a6f6f773435656631686b736f6f3936626d" + + "7a6b777779336d686d653935643766736933657a6a796a67686d70373571796f000010000100" + + "001c2000373669643d303b743d303b6b3d5f464d49553174425a63566145502d437536715542" + + "6c66466f5f73665332726c4630675362693239323445045f747970045f6469643439746a6f6f" + + "773435656631686b736f6f3936626d7a6b777779336d686d653935643766736933657a6a796a" + + "67686d70373571796f000010000100001c2000070669643d372c36045f6469643439746a6f6f" + + "773435656631686b736f6f3936626d7a6b777779336d686d653935643766736933657a6a796a" + + "67686d70373571796f000010000100001c20002726763d303b766d3d6b303b617574683d6b30" + + "3b61736d3d6b303b64656c3d6b303b696e763d6b30", + } + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + did := "did:dht:" + r.URL.Path[1:] + defer r.Body.Close() + buf, ok := vectors[did] + if !ok { + w.WriteHeader(http.StatusNotFound) + return + } + data, err := hex.DecodeString(buf) + assert.NoError(t, err) + _, err = w.Write(data) + assert.NoError(t, err) + + })) + defer ts.Close() + + r := NewResolver(ts.URL, http.DefaultClient) + + for k := range vectors { + did := k + t.Run(did, func(t *testing.T) { + res, err := r.Resolve(did) + assert.NoError(t, err) + assert.NotZero(t, res.Document) + assert.Equal(t, res.Document.ID, did) + }) + } +} diff --git a/web5-spec b/web5-spec new file mode 160000 index 0000000..77f2cbd --- /dev/null +++ b/web5-spec @@ -0,0 +1 @@ +Subproject commit 77f2cbd6ae302a0c58abc24515c7a2ca6e6407d6 From 3fc8a7c493e659cfcdff040eebae0a418ec6a9aa Mon Sep 17 00:00:00 2001 From: Mihai Chiorean Date: Mon, 25 Mar 2024 11:51:56 -0700 Subject: [PATCH 2/7] Update ci.yml --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fa65ba..d6b58a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,8 @@ jobs: steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup + with: + submodules: true - run: just test lint: name: Lint From 72a0bcacfe1226aeee31155366d2ab361009ea92 Mon Sep 17 00:00:00 2001 From: Mihai Chiorean Date: Mon, 25 Mar 2024 13:59:14 -0700 Subject: [PATCH 3/7] Update ci.yml --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6b58a0..2fa65ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,8 +23,6 @@ jobs: steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup - with: - submodules: true - run: just test lint: name: Lint From 1d633a5ec5404c1347969f1e76916d072f40bdcb Mon Sep 17 00:00:00 2001 From: Mihai Chiorean Date: Mon, 25 Mar 2024 14:50:20 -0700 Subject: [PATCH 4/7] Add submodule init to the test step --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fa65ba..3c950fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + # Fetches all history for all tags and branches + fetch-depth: 0 + # Initializes submodules recursively + submodules: recursive - uses: ./.github/actions/setup - run: just test lint: From 6558d6fdde91f93262b036245777f33442654763 Mon Sep 17 00:00:00 2001 From: Mihai Chiorean Date: Tue, 26 Mar 2024 10:11:17 -0700 Subject: [PATCH 5/7] Update dids/diddht/resolver_test.go Co-authored-by: Kendall Weihe --- dids/diddht/resolver_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dids/diddht/resolver_test.go b/dids/diddht/resolver_test.go index 7bd3e12..ea7bf36 100644 --- a/dids/diddht/resolver_test.go +++ b/dids/diddht/resolver_test.go @@ -43,7 +43,7 @@ func initVector() ([]vector, error) { return vectorData.Vectors, nil } -func Test_resolve_failures(t *testing.T) { +func Test_VectorsResolve(t *testing.T) { vectors, err := initVector() assert.NoError(t, err) From 747e419085ede11b97bbf3b9c939ae8679c02b92 Mon Sep 17 00:00:00 2001 From: Mihai Chiorean Date: Tue, 26 Mar 2024 10:22:46 -0700 Subject: [PATCH 6/7] add submondule init to the readme --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index e2df83e..8fd26ac 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,18 @@ JWT signing and verification using DIDs # Development ## Prerequisites +We use a submoduler for test vectors that make sure we follow the appropriate spec. Running tests will fail without it. +To set up the submodule, clone using: + +``` +git clone --recurse-submodules git@github.com:TBD54566975/web5-go.git +``` + +If you've already cloned, add submodules: + +``` +git submodule update --init +``` ### [`hermit`](https://cashapp.github.io/hermit/) This repo uses hermit to manage all environment dependencies (e.g. `just`, `go`). From 896fb5977d1a787cad4394cc5613f373480ad69e Mon Sep 17 00:00:00 2001 From: Mihai Chiorean Date: Fri, 29 Mar 2024 10:07:33 -0700 Subject: [PATCH 7/7] Update README.md Co-authored-by: Kendall Weihe --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fd26ac..7ab1c1a 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ JWT signing and verification using DIDs # Development ## Prerequisites -We use a submoduler for test vectors that make sure we follow the appropriate spec. Running tests will fail without it. +We use a submodule for test vectors that make sure we follow the appropriate spec. Running tests will fail without it. To set up the submodule, clone using: ```