diff --git a/README.md b/README.md index 2c09746556063ee768ef76879a889d7ef887d677..4c9c80617f0a6e96dcf0b334bee7888db099527d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +[](https://code.vereign.com/gaiax/tsa/signer/-/commits/main) +[](https://code.vereign.com/gaiax/tsa/signer/-/commits/main) + # signer Signer service creates and verifies digital signatures, verifiable credentials and verifiable presentations. diff --git a/internal/clients/vault/client.go b/internal/clients/vault/client.go index 0d4f65b8a7f7bfc55704d721fff02e8a2dcf7afc..c5d8b46a69e03e9396c1e87c9a51a8c090142199 100644 --- a/internal/clients/vault/client.go +++ b/internal/clients/vault/client.go @@ -88,14 +88,10 @@ func (c *Client) Sign(data []byte) ([]byte, error) { res, err := c.client.RawRequest(req) if err != nil { - return nil, err + return nil, errors.New(errors.GetKind(res.StatusCode), err) } defer res.Body.Close() - if res.StatusCode != http.StatusOK { - return nil, fmt.Errorf("sign: unexpected response from vault: %s", res.Status) - } - // expected response from the sign operation var response struct { Data struct { diff --git a/internal/clients/vault/client_test.go b/internal/clients/vault/client_test.go new file mode 100644 index 0000000000000000000000000000000000000000..a68d75407c0202f2b4b5be40188dd0e8984126b2 --- /dev/null +++ b/internal/clients/vault/client_test.go @@ -0,0 +1,167 @@ +package vault_test + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + + "code.vereign.com/gaiax/tsa/golib/errors" + "code.vereign.com/gaiax/tsa/signer/internal/clients/vault" + "code.vereign.com/gaiax/tsa/signer/internal/service/signer" +) + +func TestClient_Key(t *testing.T) { + tests := []struct { + name string + key string + handler http.HandlerFunc + + result *signer.SignKey + errkind errors.Kind + errtext string + }{ + { + name: "key not found", + handler: func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte("key is not found")) + }, + errkind: errors.NotFound, + errtext: "key is not found", + }, + { + name: "unauthorized request", + handler: func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusUnauthorized) + _, _ = w.Write([]byte("unauthorized request")) + }, + errkind: errors.Unauthorized, + errtext: "unauthorized request", + }, + { + name: "internal error", + handler: func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte("internal error")) + }, + errkind: errors.Internal, + errtext: "internal error", + }, + { + name: "key is retrieved", + handler: func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"data":{"name":"key123","type":"ed25519"}}`)) + }, + result: &signer.SignKey{ + Name: "key123", + Type: "ed25519", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + vaultsrv := httptest.NewServer(test.handler) + client, err := vault.New(vaultsrv.URL, "token", http.DefaultClient) + assert.NoError(t, err) + + res, err := client.Key(test.key) + if err != nil { + assert.Nil(t, res) + + e, ok := err.(*errors.Error) + assert.True(t, ok) + assert.Equal(t, test.errkind, e.Kind) + assert.Contains(t, e.Error(), test.errtext) + } else { + assert.Empty(t, test.errtext) + assert.Equal(t, test.result, res) + } + }) + } +} + +func TestClient_WithKey(t *testing.T) { + vaultsrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, r.URL.Path, "/v1/transit/sign/mytest-key123") + w.WriteHeader(http.StatusNotFound) + })) + + c1, err := vault.New(vaultsrv.URL, "token", http.DefaultClient) + assert.NoError(t, err) + + c2 := c1.WithKey("mytest-key123") + _, _ = c2.Sign([]byte("nop")) +} + +func TestClient_Sign(t *testing.T) { + tests := []struct { + name string + data []byte + handler http.HandlerFunc + + result []byte + errkind errors.Kind + errtext string + }{ + { + name: "key not found", + handler: func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte("key is not found")) + }, + errkind: errors.NotFound, + errtext: "key is not found", + }, + { + name: "unauthorized request", + handler: func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusUnauthorized) + _, _ = w.Write([]byte("unauthorized request")) + }, + errkind: errors.Unauthorized, + errtext: "unauthorized request", + }, + { + name: "internal error", + handler: func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte("internal error")) + }, + errkind: errors.Internal, + errtext: "internal error", + }, + { + name: "successful signing", + handler: func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"data":{"signature":"hello"}}`)) + }, + result: []byte("hello"), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + vaultsrv := httptest.NewServer(test.handler) + client, err := vault.New(vaultsrv.URL, "token", http.DefaultClient) + assert.NoError(t, err) + + res, err := client.Sign(test.data) + if err != nil { + assert.Nil(t, res) + + e, ok := err.(*errors.Error) + assert.True(t, ok) + assert.Equal(t, test.errkind, e.Kind) + assert.Contains(t, e.Error(), test.errtext) + } else { + assert.Empty(t, test.errtext) + assert.Equal(t, test.result, res) + } + }) + } +} diff --git a/internal/decoder/bytes_decoder_test.go b/internal/decoder/bytes_decoder_test.go new file mode 100644 index 0000000000000000000000000000000000000000..aec17dfc573cc96f84d155005eb2c17486c33709 --- /dev/null +++ b/internal/decoder/bytes_decoder_test.go @@ -0,0 +1,31 @@ +package decoder_test + +import ( + "bytes" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + + "code.vereign.com/gaiax/tsa/signer/internal/decoder" +) + +func TestBytesDecoder_Decode(t *testing.T) { + reqBody := []byte("hello") + req1, err := http.NewRequest("POST", "https://example.com", bytes.NewReader(reqBody)) + assert.NoError(t, err) + + var v []byte + err = decoder.RequestDecoder(req1).Decode(&v) + assert.NoError(t, err) + assert.Equal(t, reqBody, v) + + req2Body := []byte("hello 2") + req2, err := http.NewRequest("POST", "https://example.com", bytes.NewReader(req2Body)) + assert.NoError(t, err) + + var vs string + err = decoder.RequestDecoder(req2).Decode(&vs) + assert.NoError(t, err) + assert.Equal(t, string(req2Body), vs) +} diff --git a/internal/service/signer/service.go b/internal/service/signer/service.go index f16e5f12e41181f1694f7d8c441e643e30d89725..f216f1a8f39627221e3c8598ef02bfb7a9b8eb46 100644 --- a/internal/service/signer/service.go +++ b/internal/service/signer/service.go @@ -18,6 +18,8 @@ import ( "code.vereign.com/gaiax/tsa/signer/gen/signer" ) +//go:generate counterfeiter . Signer + type SignKey struct { Name string Type string @@ -112,7 +114,7 @@ func (s *Service) signatureSuite(key string, keyType string) (sigSuite ariesigne suite.WithVerifier(ecdsasecp256k1signature2019.NewPublicKeyVerifier())) default: - return nil, "", fmt.Errorf("unknown key type: %q", keyType) + return nil, "", fmt.Errorf("unsupported key type: %q", keyType) } return sigSuite, sigType, nil diff --git a/internal/service/signer/service_test.go b/internal/service/signer/service_test.go new file mode 100644 index 0000000000000000000000000000000000000000..19b47e2e3dab68ea8693c2ed45de86ae2a6972ef --- /dev/null +++ b/internal/service/signer/service_test.go @@ -0,0 +1,263 @@ +package signer_test + +import ( + "context" + "encoding/base64" + "net/http" + "testing" + + "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" + "github.com/stretchr/testify/assert" + "go.uber.org/zap" + + "code.vereign.com/gaiax/tsa/golib/errors" + "code.vereign.com/gaiax/tsa/golib/ptr" + goasigner "code.vereign.com/gaiax/tsa/signer/gen/signer" + "code.vereign.com/gaiax/tsa/signer/internal/service/signer" + "code.vereign.com/gaiax/tsa/signer/internal/service/signer/signerfakes" +) + +//nolint:gosec +var validCredential = `{ + "@context": [ + "https://www.w3.org/2018/credentials/v1" + ], + "credentialSubject": { + "hello": "world" + }, + "issuanceDate": "2022-06-02T17:24:05.032533+03:00", + "issuer": "https://example.com", + "type": "VerifiableCredential" +}` + +//nolint:gosec +var invalidCredential = `{"invalid":"credential"}` + +//nolint:gosec +var invalidCredentialContexts = `{ + "@context": ["https://www.w3.org/2018/credentials/v123"], + "credentialSubject": { + "hello": "world" + }, + "issuanceDate": "2022-06-02T17:24:05.032533+03:00", + "issuer": "https://example.com", + "type": "VerifiableCredential" +}` + +//nolint:gosec +var nonExistingCredentialContexts = `{ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://no-schema-here.com/credentials/context" + ], + "credentialSubject": { + "hello": "world" + }, + "issuanceDate": "2022-06-02T17:24:05.032533+03:00", + "issuer": "https://example.com", + "type": "VerifiableCredential" +}` + +func TestService_CredentialProof(t *testing.T) { + tests := []struct { + name string + signer *signerfakes.FakeSigner + defaultKey string + req *goasigner.CredentialProofRequest + + errkind errors.Kind + errtext string + + contexts []string + types []string + subject []verifiable.Subject + issuer verifiable.Issuer + proofPurpose string + proofValue string + proofType string + proofVerificationMethod string + }{ + { + name: "invalid credential", + defaultKey: "key1", + req: &goasigner.CredentialProofRequest{ + Credential: []byte(invalidCredential), + }, + errtext: "credential type of unknown structure", + }, + { + name: "invalid credential contexts", + defaultKey: "key1", + req: &goasigner.CredentialProofRequest{ + Credential: []byte(invalidCredentialContexts), + }, + errtext: "verifiable credential is not valid", + }, + { + name: "non-existing credential contexts", + defaultKey: "key1", + req: &goasigner.CredentialProofRequest{ + Credential: []byte(nonExistingCredentialContexts), + }, + errtext: "Dereferencing a URL did not result in a valid JSON-LD context", + }, + { + name: "valid credential but signer cannot find key", + defaultKey: "key1", + req: &goasigner.CredentialProofRequest{ + Key: ptr.String("key2"), + Credential: []byte(validCredential), + }, + signer: &signerfakes.FakeSigner{ + KeyStub: func(key string) (*signer.SignKey, error) { + return nil, errors.New(errors.NotFound) + }, + }, + errkind: errors.NotFound, + errtext: "error getting signing key", + }, + { + name: "valid credential but signer returns internal error", + defaultKey: "key1", + req: &goasigner.CredentialProofRequest{ + Key: ptr.String("key2"), + Credential: []byte(validCredential), + }, + signer: &signerfakes.FakeSigner{ + KeyStub: func(key string) (*signer.SignKey, error) { + return nil, errors.New(errors.Internal) + }, + }, + errkind: errors.Internal, + errtext: "error getting signing key", + }, + { + name: "valid credential but signer returns internal error", + defaultKey: "key1", + req: &goasigner.CredentialProofRequest{ + Key: ptr.String("key2"), + Credential: []byte(validCredential), + }, + signer: &signerfakes.FakeSigner{ + KeyStub: func(key string) (*signer.SignKey, error) { + return nil, errors.New(errors.Internal) + }, + }, + errkind: errors.Internal, + errtext: "error getting signing key", + }, + { + name: "valid credential but signer returns unsupported key type", + defaultKey: "key1", + req: &goasigner.CredentialProofRequest{ + Key: ptr.String("key2"), + Credential: []byte(validCredential), + }, + signer: &signerfakes.FakeSigner{ + KeyStub: func(key string) (*signer.SignKey, error) { + return &signer.SignKey{ + Name: "key23", + Type: "rsa4096", + }, nil + }, + }, + errkind: errors.Unknown, + errtext: "unsupported key type", + }, + { + name: "valid credential and signer key type ed25519", + defaultKey: "key1", + req: &goasigner.CredentialProofRequest{ + Key: ptr.String("key2"), + Credential: []byte(validCredential), + }, + signer: &signerfakes.FakeSigner{ + KeyStub: func(key string) (*signer.SignKey, error) { + return &signer.SignKey{ + Name: "key123", + Type: "ed25519", + }, nil + }, + WithKeyStub: func(key string) signer.Signer { + return &signerfakes.FakeSigner{ + SignStub: func(data []byte) ([]byte, error) { + return []byte("test signature"), nil + }, + } + }, + }, + + // expected attributes the VC must have + contexts: []string{"https://www.w3.org/2018/credentials/v1"}, + subject: []verifiable.Subject{{CustomFields: verifiable.CustomFields{"hello": "world"}}}, + issuer: verifiable.Issuer{ID: "https://example.com"}, + proofPurpose: "assertionMethod", + proofType: "Ed25519Signature2018", + proofValue: base64.RawURLEncoding.EncodeToString([]byte("test signature")), + proofVerificationMethod: "key123", + }, + { + name: "valid credential and signer key type ecdsa-p256", + defaultKey: "key1", + req: &goasigner.CredentialProofRequest{ + Key: ptr.String("key2"), + Credential: []byte(validCredential), + }, + signer: &signerfakes.FakeSigner{ + KeyStub: func(key string) (*signer.SignKey, error) { + return &signer.SignKey{ + Name: "key123", + Type: "ecdsa-p256", + }, nil + }, + WithKeyStub: func(key string) signer.Signer { + return &signerfakes.FakeSigner{ + SignStub: func(data []byte) ([]byte, error) { + return []byte("test signature"), nil + }, + } + }, + }, + + // expected attributes the VC must have + contexts: []string{"https://www.w3.org/2018/credentials/v1"}, + subject: []verifiable.Subject{{CustomFields: verifiable.CustomFields{"hello": "world"}}}, + issuer: verifiable.Issuer{ID: "https://example.com"}, + proofPurpose: "assertionMethod", + proofType: "EcdsaSecp256k1Signature2019", + proofValue: base64.RawURLEncoding.EncodeToString([]byte("test signature")), + proofVerificationMethod: "key123", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + svc := signer.New(test.signer, test.defaultKey, http.DefaultClient, zap.NewNop()) + res, err := svc.CredentialProof(context.Background(), test.req) + if err != nil { + assert.Nil(t, res) + assert.NotEmpty(t, test.errtext) + if e, ok := err.(*errors.Error); ok { + assert.Equal(t, test.errkind, e.Kind) + assert.Contains(t, e.Message, test.errtext) + } else { + assert.Contains(t, err.Error(), test.errtext) + } + } else { + assert.Empty(t, test.errtext) + assert.NotNil(t, res) + + vc, ok := res.(*verifiable.Credential) + assert.True(t, ok) + + assert.Equal(t, test.contexts, vc.Context) + assert.Equal(t, test.subject, vc.Subject) + assert.Equal(t, test.issuer, vc.Issuer) + assert.Equal(t, test.proofPurpose, vc.Proofs[0]["proofPurpose"]) + assert.Equal(t, test.proofType, vc.Proofs[0]["type"]) + assert.Equal(t, test.proofValue, vc.Proofs[0]["proofValue"]) + assert.Equal(t, test.proofVerificationMethod, vc.Proofs[0]["verificationMethod"]) + } + }) + } +} diff --git a/internal/service/signer/signerfakes/fake_signer.go b/internal/service/signer/signerfakes/fake_signer.go new file mode 100644 index 0000000000000000000000000000000000000000..5b2b696013317d774fe2aae6793758037054f786 --- /dev/null +++ b/internal/service/signer/signerfakes/fake_signer.go @@ -0,0 +1,274 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package signerfakes + +import ( + "sync" + + "code.vereign.com/gaiax/tsa/signer/internal/service/signer" +) + +type FakeSigner struct { + KeyStub func(string) (*signer.SignKey, error) + keyMutex sync.RWMutex + keyArgsForCall []struct { + arg1 string + } + keyReturns struct { + result1 *signer.SignKey + result2 error + } + keyReturnsOnCall map[int]struct { + result1 *signer.SignKey + result2 error + } + SignStub func([]byte) ([]byte, error) + signMutex sync.RWMutex + signArgsForCall []struct { + arg1 []byte + } + signReturns struct { + result1 []byte + result2 error + } + signReturnsOnCall map[int]struct { + result1 []byte + result2 error + } + WithKeyStub func(string) signer.Signer + withKeyMutex sync.RWMutex + withKeyArgsForCall []struct { + arg1 string + } + withKeyReturns struct { + result1 signer.Signer + } + withKeyReturnsOnCall map[int]struct { + result1 signer.Signer + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeSigner) Key(arg1 string) (*signer.SignKey, error) { + fake.keyMutex.Lock() + ret, specificReturn := fake.keyReturnsOnCall[len(fake.keyArgsForCall)] + fake.keyArgsForCall = append(fake.keyArgsForCall, struct { + arg1 string + }{arg1}) + stub := fake.KeyStub + fakeReturns := fake.keyReturns + fake.recordInvocation("Key", []interface{}{arg1}) + fake.keyMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeSigner) KeyCallCount() int { + fake.keyMutex.RLock() + defer fake.keyMutex.RUnlock() + return len(fake.keyArgsForCall) +} + +func (fake *FakeSigner) KeyCalls(stub func(string) (*signer.SignKey, error)) { + fake.keyMutex.Lock() + defer fake.keyMutex.Unlock() + fake.KeyStub = stub +} + +func (fake *FakeSigner) KeyArgsForCall(i int) string { + fake.keyMutex.RLock() + defer fake.keyMutex.RUnlock() + argsForCall := fake.keyArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *FakeSigner) KeyReturns(result1 *signer.SignKey, result2 error) { + fake.keyMutex.Lock() + defer fake.keyMutex.Unlock() + fake.KeyStub = nil + fake.keyReturns = struct { + result1 *signer.SignKey + result2 error + }{result1, result2} +} + +func (fake *FakeSigner) KeyReturnsOnCall(i int, result1 *signer.SignKey, result2 error) { + fake.keyMutex.Lock() + defer fake.keyMutex.Unlock() + fake.KeyStub = nil + if fake.keyReturnsOnCall == nil { + fake.keyReturnsOnCall = make(map[int]struct { + result1 *signer.SignKey + result2 error + }) + } + fake.keyReturnsOnCall[i] = struct { + result1 *signer.SignKey + result2 error + }{result1, result2} +} + +func (fake *FakeSigner) Sign(arg1 []byte) ([]byte, error) { + var arg1Copy []byte + if arg1 != nil { + arg1Copy = make([]byte, len(arg1)) + copy(arg1Copy, arg1) + } + fake.signMutex.Lock() + ret, specificReturn := fake.signReturnsOnCall[len(fake.signArgsForCall)] + fake.signArgsForCall = append(fake.signArgsForCall, struct { + arg1 []byte + }{arg1Copy}) + stub := fake.SignStub + fakeReturns := fake.signReturns + fake.recordInvocation("Sign", []interface{}{arg1Copy}) + fake.signMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeSigner) SignCallCount() int { + fake.signMutex.RLock() + defer fake.signMutex.RUnlock() + return len(fake.signArgsForCall) +} + +func (fake *FakeSigner) SignCalls(stub func([]byte) ([]byte, error)) { + fake.signMutex.Lock() + defer fake.signMutex.Unlock() + fake.SignStub = stub +} + +func (fake *FakeSigner) SignArgsForCall(i int) []byte { + fake.signMutex.RLock() + defer fake.signMutex.RUnlock() + argsForCall := fake.signArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *FakeSigner) SignReturns(result1 []byte, result2 error) { + fake.signMutex.Lock() + defer fake.signMutex.Unlock() + fake.SignStub = nil + fake.signReturns = struct { + result1 []byte + result2 error + }{result1, result2} +} + +func (fake *FakeSigner) SignReturnsOnCall(i int, result1 []byte, result2 error) { + fake.signMutex.Lock() + defer fake.signMutex.Unlock() + fake.SignStub = nil + if fake.signReturnsOnCall == nil { + fake.signReturnsOnCall = make(map[int]struct { + result1 []byte + result2 error + }) + } + fake.signReturnsOnCall[i] = struct { + result1 []byte + result2 error + }{result1, result2} +} + +func (fake *FakeSigner) WithKey(arg1 string) signer.Signer { + fake.withKeyMutex.Lock() + ret, specificReturn := fake.withKeyReturnsOnCall[len(fake.withKeyArgsForCall)] + fake.withKeyArgsForCall = append(fake.withKeyArgsForCall, struct { + arg1 string + }{arg1}) + stub := fake.WithKeyStub + fakeReturns := fake.withKeyReturns + fake.recordInvocation("WithKey", []interface{}{arg1}) + fake.withKeyMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeSigner) WithKeyCallCount() int { + fake.withKeyMutex.RLock() + defer fake.withKeyMutex.RUnlock() + return len(fake.withKeyArgsForCall) +} + +func (fake *FakeSigner) WithKeyCalls(stub func(string) signer.Signer) { + fake.withKeyMutex.Lock() + defer fake.withKeyMutex.Unlock() + fake.WithKeyStub = stub +} + +func (fake *FakeSigner) WithKeyArgsForCall(i int) string { + fake.withKeyMutex.RLock() + defer fake.withKeyMutex.RUnlock() + argsForCall := fake.withKeyArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *FakeSigner) WithKeyReturns(result1 signer.Signer) { + fake.withKeyMutex.Lock() + defer fake.withKeyMutex.Unlock() + fake.WithKeyStub = nil + fake.withKeyReturns = struct { + result1 signer.Signer + }{result1} +} + +func (fake *FakeSigner) WithKeyReturnsOnCall(i int, result1 signer.Signer) { + fake.withKeyMutex.Lock() + defer fake.withKeyMutex.Unlock() + fake.WithKeyStub = nil + if fake.withKeyReturnsOnCall == nil { + fake.withKeyReturnsOnCall = make(map[int]struct { + result1 signer.Signer + }) + } + fake.withKeyReturnsOnCall[i] = struct { + result1 signer.Signer + }{result1} +} + +func (fake *FakeSigner) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.keyMutex.RLock() + defer fake.keyMutex.RUnlock() + fake.signMutex.RLock() + defer fake.signMutex.RUnlock() + fake.withKeyMutex.RLock() + defer fake.withKeyMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeSigner) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ signer.Signer = new(FakeSigner) diff --git a/vendor/code.vereign.com/gaiax/tsa/golib/ptr/ptr.go b/vendor/code.vereign.com/gaiax/tsa/golib/ptr/ptr.go new file mode 100644 index 0000000000000000000000000000000000000000..fd522b7a70d7449dccc01ee3b2b3181eb9e7600e Binary files /dev/null and b/vendor/code.vereign.com/gaiax/tsa/golib/ptr/ptr.go differ diff --git a/vendor/modules.txt b/vendor/modules.txt index f58893de232b4f9954dbb6d6bbac3c405c0816d8..f2d535f0ab2c3d48dc3e1cf15f48c9750938e801 100644 Binary files a/vendor/modules.txt and b/vendor/modules.txt differ