diff --git a/auth/api/iam/generated.go b/auth/api/iam/generated.go
index 8ed32173de..04af47a13b 100644
--- a/auth/api/iam/generated.go
+++ b/auth/api/iam/generated.go
@@ -123,7 +123,6 @@ type RequestAccessTokenJSONBody struct {
Scope string `json:"scope"`
// UserID The ID of the user for which this access token is requested.
- // It's handled as opaque ID and is scoped to the requester DID.
UserID *string `json:"userID,omitempty"`
Verifier string `json:"verifier"`
}
@@ -160,7 +159,7 @@ type ServerInterface interface {
// Introspection endpoint to retrieve information from an Access Token as described by RFC7662
// (POST /internal/auth/v2/accesstoken/introspect)
IntrospectAccessToken(ctx echo.Context) error
- // Requests an access token using the vp_token-bearer grant.
+ // Start the authorization flow to get an access token from a remote authorization server.
// (POST /internal/auth/v2/{did}/request-access-token)
RequestAccessToken(ctx echo.Context, did string) error
}
@@ -686,7 +685,7 @@ type StrictServerInterface interface {
// Introspection endpoint to retrieve information from an Access Token as described by RFC7662
// (POST /internal/auth/v2/accesstoken/introspect)
IntrospectAccessToken(ctx context.Context, request IntrospectAccessTokenRequestObject) (IntrospectAccessTokenResponseObject, error)
- // Requests an access token using the vp_token-bearer grant.
+ // Start the authorization flow to get an access token from a remote authorization server.
// (POST /internal/auth/v2/{did}/request-access-token)
RequestAccessToken(ctx context.Context, request RequestAccessTokenRequestObject) (RequestAccessTokenResponseObject, error)
}
diff --git a/codegen/configs/discovery_v1.yaml b/codegen/configs/discovery_v1.yaml
index ffa5d4adbb..f0fba7b580 100644
--- a/codegen/configs/discovery_v1.yaml
+++ b/codegen/configs/discovery_v1.yaml
@@ -8,3 +8,4 @@ output-options:
skip-prune: true
exclude-schemas:
- VerifiablePresentation
+ - PresentationsResponse
diff --git a/discovery/api/v1/client/http.go b/discovery/api/v1/client/http.go
new file mode 100644
index 0000000000..357e5f04a3
--- /dev/null
+++ b/discovery/api/v1/client/http.go
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2024 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package client
+
+import (
+ "bytes"
+ "context"
+ "crypto/tls"
+ "encoding/json"
+ "fmt"
+ "github.com/nuts-foundation/go-did/vc"
+ "github.com/nuts-foundation/nuts-node/core"
+ "github.com/nuts-foundation/nuts-node/discovery/api/v1/model"
+ "io"
+ "net/http"
+ "net/url"
+ "time"
+)
+
+// New creates a new DefaultHTTPClient.
+func New(strictMode bool, timeout time.Duration, tlsConfig *tls.Config) *DefaultHTTPClient {
+ return &DefaultHTTPClient{
+ client: core.NewStrictHTTPClient(strictMode, timeout, tlsConfig),
+ }
+}
+
+var _ HTTPClient = &DefaultHTTPClient{}
+
+// DefaultHTTPClient implements HTTPClient using HTTP.
+type DefaultHTTPClient struct {
+ client core.HTTPRequestDoer
+}
+
+func (h DefaultHTTPClient) Register(ctx context.Context, serviceEndpointURL string, presentation vc.VerifiablePresentation) error {
+ requestBody, _ := json.Marshal(presentation)
+ httpRequest, err := http.NewRequestWithContext(ctx, http.MethodPost, serviceEndpointURL, bytes.NewReader(requestBody))
+ if err != nil {
+ return err
+ }
+ httpRequest.Header.Set("Content-Type", "application/json")
+ httpResponse, err := h.client.Do(httpRequest)
+ if err != nil {
+ return fmt.Errorf("failed to invoke remote Discovery Service (url=%s): %w", serviceEndpointURL, err)
+ }
+ defer httpResponse.Body.Close()
+ if err := core.TestResponseCode(201, httpResponse); err != nil {
+ return fmt.Errorf("non-OK response from remote Discovery Service (url=%s): %w", serviceEndpointURL, err)
+ }
+ return nil
+}
+
+func (h DefaultHTTPClient) Get(ctx context.Context, serviceEndpointURL string, tag *string) ([]vc.VerifiablePresentation, *string, error) {
+ httpRequest, err := http.NewRequestWithContext(ctx, http.MethodGet, serviceEndpointURL, nil)
+ if tag != nil {
+ httpRequest.URL.RawQuery = url.Values{"tag": []string{*tag}}.Encode()
+ }
+ if err != nil {
+ return nil, nil, err
+ }
+ httpResponse, err := h.client.Do(httpRequest)
+ if err != nil {
+ return nil, nil, fmt.Errorf("failed to invoke remote Discovery Service (url=%s): %w", serviceEndpointURL, err)
+ }
+ defer httpResponse.Body.Close()
+ if err := core.TestResponseCode(200, httpResponse); err != nil {
+ return nil, nil, fmt.Errorf("non-OK response from remote Discovery Service (url=%s): %w", serviceEndpointURL, err)
+ }
+ responseData, err := io.ReadAll(httpResponse.Body)
+ if err != nil {
+ return nil, nil, fmt.Errorf("failed to read response from remote Discovery Service (url=%s): %w", serviceEndpointURL, err)
+ }
+ var result model.PresentationsResponse
+ if err := json.Unmarshal(responseData, &result); err != nil {
+ return nil, nil, fmt.Errorf("failed to unmarshal response from remote Discovery Service (url=%s): %w", serviceEndpointURL, err)
+ }
+ return result.Entries, &result.Tag, nil
+}
diff --git a/discovery/api/v1/client/http_test.go b/discovery/api/v1/client/http_test.go
new file mode 100644
index 0000000000..98cee0da1d
--- /dev/null
+++ b/discovery/api/v1/client/http_test.go
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2024 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package client
+
+import (
+ "context"
+ ssi "github.com/nuts-foundation/go-did"
+ "github.com/nuts-foundation/go-did/vc"
+ testHTTP "github.com/nuts-foundation/nuts-node/test/http"
+ "github.com/stretchr/testify/assert"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+ "time"
+)
+
+func TestHTTPInvoker_Register(t *testing.T) {
+ vp := vc.VerifiablePresentation{
+ Context: []ssi.URI{ssi.MustParseURI("https://www.w3.org/2018/credentials/v1")},
+ }
+ vpData, _ := vp.MarshalJSON()
+ t.Run("ok", func(t *testing.T) {
+ handler := &testHTTP.Handler{StatusCode: http.StatusCreated}
+ server := httptest.NewServer(handler)
+ client := New(false, time.Minute, server.TLS)
+
+ err := client.Register(context.Background(), server.URL, vp)
+
+ assert.NoError(t, err)
+ assert.Equal(t, http.MethodPost, handler.Request.Method)
+ assert.Equal(t, "application/json", handler.Request.Header.Get("Content-Type"))
+ assert.Equal(t, vpData, handler.RequestData)
+ })
+ t.Run("non-ok", func(t *testing.T) {
+ server := httptest.NewServer(&testHTTP.Handler{StatusCode: http.StatusInternalServerError})
+ client := New(false, time.Minute, server.TLS)
+
+ err := client.Register(context.Background(), server.URL, vp)
+
+ assert.ErrorContains(t, err, "non-OK response from remote Discovery Service")
+ })
+}
+
+func TestHTTPInvoker_Get(t *testing.T) {
+ vp := vc.VerifiablePresentation{
+ Context: []ssi.URI{ssi.MustParseURI("https://www.w3.org/2018/credentials/v1")},
+ }
+ const clientTag = "client-tag"
+ const serverTag = "server-tag"
+ t.Run("no tag from client", func(t *testing.T) {
+ handler := &testHTTP.Handler{StatusCode: http.StatusOK}
+ handler.ResponseData = map[string]interface{}{
+ "entries": []interface{}{vp},
+ "tag": serverTag,
+ }
+ server := httptest.NewServer(handler)
+ client := New(false, time.Minute, server.TLS)
+
+ presentations, tag, err := client.Get(context.Background(), server.URL, nil)
+
+ assert.NoError(t, err)
+ assert.Len(t, presentations, 1)
+ assert.Empty(t, handler.RequestQuery.Get("tag"))
+ assert.Equal(t, serverTag, *tag)
+ })
+ t.Run("tag provided by client", func(t *testing.T) {
+ handler := &testHTTP.Handler{StatusCode: http.StatusOK}
+ handler.ResponseData = map[string]interface{}{
+ "entries": []interface{}{vp},
+ "tag": serverTag,
+ }
+ server := httptest.NewServer(handler)
+ client := New(false, time.Minute, server.TLS)
+
+ inputTag := clientTag
+ presentations, tag, err := client.Get(context.Background(), server.URL, &inputTag)
+
+ assert.NoError(t, err)
+ assert.Len(t, presentations, 1)
+ assert.Equal(t, clientTag, handler.RequestQuery.Get("tag"))
+ assert.Equal(t, serverTag, *tag)
+ })
+ t.Run("server returns invalid status code", func(t *testing.T) {
+ handler := &testHTTP.Handler{StatusCode: http.StatusInternalServerError}
+ server := httptest.NewServer(handler)
+ client := New(false, time.Minute, server.TLS)
+
+ _, _, err := client.Get(context.Background(), server.URL, nil)
+
+ assert.ErrorContains(t, err, "non-OK response from remote Discovery Service")
+ })
+ t.Run("server does not return JSON", func(t *testing.T) {
+ handler := &testHTTP.Handler{StatusCode: http.StatusOK}
+ handler.ResponseData = "not json"
+ server := httptest.NewServer(handler)
+ client := New(false, time.Minute, server.TLS)
+
+ _, _, err := client.Get(context.Background(), server.URL, nil)
+
+ assert.ErrorContains(t, err, "failed to unmarshal response from remote Discovery Service")
+ })
+}
diff --git a/discovery/api/v1/client/interface.go b/discovery/api/v1/client/interface.go
new file mode 100644
index 0000000000..1ad0842f2c
--- /dev/null
+++ b/discovery/api/v1/client/interface.go
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package client
+
+import (
+ "context"
+ "github.com/nuts-foundation/go-did/vc"
+)
+
+// HTTPClient is the interface for the client that invokes the remote Discovery Service.
+type HTTPClient interface {
+ // Register registers a Verifiable Presentation on the remote Discovery Service.
+ Register(ctx context.Context, serviceEndpointURL string, presentation vc.VerifiablePresentation) error
+
+ // Get retrieves Verifiable Presentations from the remote Discovery Service, that were added since the given tag.
+ // If the call succeeds it returns the Verifiable Presentations and the tag that was returned by the server.
+ // If tag is nil, all Verifiable Presentations are retrieved.
+ Get(ctx context.Context, serviceEndpointURL string, tag *string) ([]vc.VerifiablePresentation, *string, error)
+}
diff --git a/discovery/api/v1/client/mock.go b/discovery/api/v1/client/mock.go
new file mode 100644
index 0000000000..05119ff9bb
--- /dev/null
+++ b/discovery/api/v1/client/mock.go
@@ -0,0 +1,71 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: discovery/api/v1/client/interface.go
+//
+// Generated by this command:
+//
+// mockgen -destination=discovery/api/v1/client/mock.go -package=client -source=discovery/api/v1/client/interface.go
+//
+
+// Package client is a generated GoMock package.
+package client
+
+import (
+ context "context"
+ reflect "reflect"
+
+ vc "github.com/nuts-foundation/go-did/vc"
+ gomock "go.uber.org/mock/gomock"
+)
+
+// MockHTTPClient is a mock of HTTPClient interface.
+type MockHTTPClient struct {
+ ctrl *gomock.Controller
+ recorder *MockHTTPClientMockRecorder
+}
+
+// MockHTTPClientMockRecorder is the mock recorder for MockHTTPClient.
+type MockHTTPClientMockRecorder struct {
+ mock *MockHTTPClient
+}
+
+// NewMockHTTPClient creates a new mock instance.
+func NewMockHTTPClient(ctrl *gomock.Controller) *MockHTTPClient {
+ mock := &MockHTTPClient{ctrl: ctrl}
+ mock.recorder = &MockHTTPClientMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockHTTPClient) EXPECT() *MockHTTPClientMockRecorder {
+ return m.recorder
+}
+
+// Get mocks base method.
+func (m *MockHTTPClient) Get(ctx context.Context, serviceEndpointURL string, tag *string) ([]vc.VerifiablePresentation, *string, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Get", ctx, serviceEndpointURL, tag)
+ ret0, _ := ret[0].([]vc.VerifiablePresentation)
+ ret1, _ := ret[1].(*string)
+ ret2, _ := ret[2].(error)
+ return ret0, ret1, ret2
+}
+
+// Get indicates an expected call of Get.
+func (mr *MockHTTPClientMockRecorder) Get(ctx, serviceEndpointURL, tag any) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockHTTPClient)(nil).Get), ctx, serviceEndpointURL, tag)
+}
+
+// Register mocks base method.
+func (m *MockHTTPClient) Register(ctx context.Context, serviceEndpointURL string, presentation vc.VerifiablePresentation) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Register", ctx, serviceEndpointURL, presentation)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// Register indicates an expected call of Register.
+func (mr *MockHTTPClientMockRecorder) Register(ctx, serviceEndpointURL, presentation any) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockHTTPClient)(nil).Register), ctx, serviceEndpointURL, presentation)
+}
diff --git a/discovery/api/v1/generated.go b/discovery/api/v1/generated.go
index aac9117245..67aaee659c 100644
--- a/discovery/api/v1/generated.go
+++ b/discovery/api/v1/generated.go
@@ -304,12 +304,9 @@ type ClientWithResponsesInterface interface {
}
type GetPresentationsResponse struct {
- Body []byte
- HTTPResponse *http.Response
- JSON200 *struct {
- Entries []VerifiablePresentation `json:"entries"`
- Tag string `json:"tag"`
- }
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *PresentationsResponse
ApplicationproblemJSONDefault *struct {
// Detail A human-readable explanation specific to this occurrence of the problem.
Detail string `json:"detail"`
@@ -420,10 +417,7 @@ func ParseGetPresentationsResponse(rsp *http.Response) (*GetPresentationsRespons
switch {
case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
- var dest struct {
- Entries []VerifiablePresentation `json:"entries"`
- Tag string `json:"tag"`
- }
+ var dest PresentationsResponse
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
@@ -603,10 +597,7 @@ type GetPresentationsResponseObject interface {
VisitGetPresentationsResponse(w http.ResponseWriter) error
}
-type GetPresentations200JSONResponse struct {
- Entries []VerifiablePresentation `json:"entries"`
- Tag string `json:"tag"`
-}
+type GetPresentations200JSONResponse PresentationsResponse
func (response GetPresentations200JSONResponse) VisitGetPresentationsResponse(w http.ResponseWriter) error {
w.Header().Set("Content-Type", "application/json")
diff --git a/discovery/api/v1/model/types.go b/discovery/api/v1/model/types.go
new file mode 100644
index 0000000000..2d9a512ad0
--- /dev/null
+++ b/discovery/api/v1/model/types.go
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package model
+
+import "github.com/nuts-foundation/go-did/vc"
+
+// PresentationsResponse is the response for the GetPresentations endpoint.
+type PresentationsResponse struct {
+ Entries []vc.VerifiablePresentation `json:"entries"`
+ Tag string `json:"tag"`
+}
diff --git a/discovery/api/v1/types.go b/discovery/api/v1/types.go
index 7a9ff02004..d719c5d646 100644
--- a/discovery/api/v1/types.go
+++ b/discovery/api/v1/types.go
@@ -18,7 +18,13 @@
package v1
-import "github.com/nuts-foundation/go-did/vc"
+import (
+ "github.com/nuts-foundation/go-did/vc"
+ "github.com/nuts-foundation/nuts-node/discovery/api/v1/model"
+)
// VerifiablePresentation is a type alias for the VerifiablePresentation from the go-did library.
type VerifiablePresentation = vc.VerifiablePresentation
+
+// PresentationsResponse is a type alias
+type PresentationsResponse = model.PresentationsResponse
diff --git a/discovery/api/v1/wrapper.go b/discovery/api/v1/wrapper.go
index 375a1939e3..93f58cf394 100644
--- a/discovery/api/v1/wrapper.go
+++ b/discovery/api/v1/wrapper.go
@@ -62,6 +62,7 @@ func (w *Wrapper) Routes(router core.EchoRouter) {
func (w *Wrapper) GetPresentations(_ context.Context, request GetPresentationsRequestObject) (GetPresentationsResponseObject, error) {
var tag *discovery.Tag
if request.Params.Tag != nil {
+ // *string to *Tag
tag = new(discovery.Tag)
*tag = discovery.Tag(*request.Params.Tag)
}
diff --git a/docs/_static/discovery/v1.yaml b/docs/_static/discovery/v1.yaml
index 062502ef56..2d376315b6 100644
--- a/docs/_static/discovery/v1.yaml
+++ b/docs/_static/discovery/v1.yaml
@@ -38,17 +38,7 @@ paths:
content:
application/json:
schema:
- type: object
- required:
- - tag
- - entries
- properties:
- tag:
- type: string
- entries:
- type: array
- items:
- $ref: "#/components/schemas/VerifiablePresentation"
+ $ref: "#/components/schemas/PresentationsResponse"
default:
$ref: "../common/error_response.yaml"
post:
@@ -85,6 +75,18 @@ components:
schemas:
VerifiablePresentation:
$ref: "../common/ssi_types.yaml#/components/schemas/VerifiablePresentation"
+ PresentationsResponse:
+ type: object
+ required:
+ - tag
+ - entries
+ properties:
+ tag:
+ type: string
+ entries:
+ type: array
+ items:
+ $ref: "#/components/schemas/VerifiablePresentation"
securitySchemes:
jwtBearerAuth:
type: http
diff --git a/makefile b/makefile
index f6d6d1a711..d9b223aeb4 100644
--- a/makefile
+++ b/makefile
@@ -20,6 +20,7 @@ gen-mocks:
mockgen -destination=crypto/storage/spi/mock.go -package spi -source=crypto/storage/spi/interface.go
mockgen -destination=didman/mock.go -package=didman -source=didman/types.go
mockgen -destination=discovery/mock.go -package=discovery -source=discovery/interface.go
+ mockgen -destination=discovery/api/v1/client/mock.go -package=client -source=discovery/api/v1/client/interface.go
mockgen -destination=events/events_mock.go -package=events -source=events/interface.go Event
mockgen -destination=events/mock.go -package=events -source=events/conn.go Conn ConnectionPool
mockgen -destination=http/echo_mock.go -package=http -source=http/echo.go -imports echo=github.com/labstack/echo/v4
diff --git a/test/http/handler.go b/test/http/handler.go
index 6edd9f3b27..59814aba33 100644
--- a/test/http/handler.go
+++ b/test/http/handler.go
@@ -20,6 +20,7 @@ import (
"encoding/json"
"io"
"net/http"
+ "net/url"
)
// Handler is a custom http handler useful in testing.
@@ -31,6 +32,7 @@ import (
type Handler struct {
Request *http.Request
RequestHeaders http.Header
+ RequestQuery url.Values
StatusCode int
RequestData []byte
ResponseData interface{}
@@ -41,6 +43,7 @@ func (h *Handler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
h.Request = req
h.RequestData, _ = io.ReadAll(req.Body)
h.RequestHeaders = req.Header.Clone()
+ h.RequestQuery = req.URL.Query()
var bytes []byte
if s, ok := h.ResponseData.(string); ok {
diff --git a/vcr/verifier/signature_verifier.go b/vcr/verifier/signature_verifier.go
index 3ca21a8a2a..7822db896c 100644
--- a/vcr/verifier/signature_verifier.go
+++ b/vcr/verifier/signature_verifier.go
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) 2024 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
package verifier
import (
diff --git a/vcr/verifier/signature_verifier_test.go b/vcr/verifier/signature_verifier_test.go
index 6169923315..1307148c65 100644
--- a/vcr/verifier/signature_verifier_test.go
+++ b/vcr/verifier/signature_verifier_test.go
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) 2024 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
package verifier
import (