diff --git a/ct_only.go b/ct_only.go index 9fa8eb53..43a201b8 100644 --- a/ct_only.go +++ b/ct_only.go @@ -24,10 +24,10 @@ import ( // Storage described the expected functions from Tessera storage implementations. type Storage interface { - // Add should duably assign an index to the provided Entry, and return it. + // Add should duably assign an index to the provided Entry, returning a future to access that value. // // Implementations MUST call MarshalBundleData method on the entry before persisting/integrating it. - Add(context.Context, *Entry) (uint64, error) + Add(context.Context, *Entry) IndexFuture } // NewCertificateTransparencySequencedWriter returns a function which knows how to add a CT-specific entry type to the log. @@ -38,8 +38,8 @@ type Storage interface { // b) is not compatible with the https://c2sp.org/tlog-tiles API which we _very strongly_ encourage you to use instead. // // Returns the assigned index in the log, or an error. -func NewCertificateTransparencySequencedWriter(s Storage) func(context.Context, *ctonly.Entry) (uint64, error) { - return func(ctx context.Context, e *ctonly.Entry) (uint64, error) { +func NewCertificateTransparencySequencedWriter(s Storage) func(context.Context, *ctonly.Entry) IndexFuture { + return func(ctx context.Context, e *ctonly.Entry) IndexFuture { return s.Add(ctx, convertCTEntry(e)) } } diff --git a/personalities/sctfe/handlers.go b/personalities/sctfe/handlers.go index 6d1158c5..0fcd9ae3 100644 --- a/personalities/sctfe/handlers.go +++ b/personalities/sctfe/handlers.go @@ -334,7 +334,7 @@ func addChainInternal(ctx context.Context, li *logInfo, w http.ResponseWriter, r } klog.V(2).Infof("%s: %s => storage.Add", li.LogOrigin, method) - idx, err := li.storage.Add(ctx, entry) + idx, err := li.storage.Add(ctx, entry)() if err != nil { if errors.Is(err, tessera.ErrPushback) { w.Header().Add("Retry-After", "1") diff --git a/personalities/sctfe/handlers_test.go b/personalities/sctfe/handlers_test.go index cca6f1ff..fddb747d 100644 --- a/personalities/sctfe/handlers_test.go +++ b/personalities/sctfe/handlers_test.go @@ -294,7 +294,7 @@ func TestAddChainWhitespace(t *testing.T) { t.Run(test.descr, func(t *testing.T) { if test.want == http.StatusOK { info.storage.EXPECT().AddIssuerChain(deadlineMatcher(), cmpMatcher{leafChain[1:]}).Return(nil) - info.storage.EXPECT().Add(deadlineMatcher(), cmpMatcher{req}).Return(rsp, nil) + info.storage.EXPECT().Add(deadlineMatcher(), cmpMatcher{req}).Return(func() (uint64, error) { return rsp, nil }) } recorder := httptest.NewRecorder() @@ -368,7 +368,7 @@ func TestAddChain(t *testing.T) { req, leafChain := parseChain(t, false, test.chain, info.roots.RawCertificates()[0]) rsp := uint64(0) info.storage.EXPECT().AddIssuerChain(deadlineMatcher(), cmpMatcher{leafChain[1:]}).Return(nil) - info.storage.EXPECT().Add(deadlineMatcher(), cmpMatcher{req}).Return(rsp, test.err) + info.storage.EXPECT().Add(deadlineMatcher(), cmpMatcher{req}).Return(func() (uint64, error) { return rsp, test.err }) } recorder := makeAddChainRequest(t, info.li, chain) @@ -457,7 +457,7 @@ func TestAddPrechain(t *testing.T) { req, leafChain := parseChain(t, true, test.chain, info.roots.RawCertificates()[0]) rsp := uint64(0) info.storage.EXPECT().AddIssuerChain(deadlineMatcher(), cmpMatcher{leafChain[1:]}).Return(nil) - info.storage.EXPECT().Add(deadlineMatcher(), cmpMatcher{req}).Return(rsp, test.err) + info.storage.EXPECT().Add(deadlineMatcher(), cmpMatcher{req}).Return(func() (uint64, error) { return rsp, test.err }) } recorder := makeAddPrechainRequest(t, info.li, chain) diff --git a/personalities/sctfe/mockstorage/mock_ct_storage.go b/personalities/sctfe/mockstorage/mock_ct_storage.go index 373556f0..75509fd8 100644 --- a/personalities/sctfe/mockstorage/mock_ct_storage.go +++ b/personalities/sctfe/mockstorage/mock_ct_storage.go @@ -10,6 +10,7 @@ import ( gomock "github.com/golang/mock/gomock" x509 "github.com/google/certificate-transparency-go/x509" + tessera "github.com/transparency-dev/trillian-tessera" ctonly "github.com/transparency-dev/trillian-tessera/ctonly" ) @@ -37,12 +38,11 @@ func (m *MockStorage) EXPECT() *MockStorageMockRecorder { } // Add mocks base method. -func (m *MockStorage) Add(arg0 context.Context, arg1 *ctonly.Entry) (uint64, error) { +func (m *MockStorage) Add(arg0 context.Context, arg1 *ctonly.Entry) tessera.IndexFuture { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Add", arg0, arg1) - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret0, _ := ret[0].(tessera.IndexFuture) + return ret0 } // Add indicates an expected call of Add. diff --git a/personalities/sctfe/storage.go b/personalities/sctfe/storage.go index b204d68b..9bd3d75c 100644 --- a/personalities/sctfe/storage.go +++ b/personalities/sctfe/storage.go @@ -36,8 +36,8 @@ const ( // Storage provides all the storage primitives necessary to write to a ct-static-api log. type Storage interface { - // Add assigns an index to the provided Entry, stages the entry for integration, and return it the assigned index. - Add(context.Context, *ctonly.Entry) (uint64, error) + // Add assigns an index to the provided Entry, stages the entry for integration, and returns a future for the assigned index. + Add(context.Context, *ctonly.Entry) tessera.IndexFuture // AddIssuerChain stores every the chain certificate in a content-addressable store under their sha256 hash. AddIssuerChain(context.Context, []*x509.Certificate) error } @@ -54,7 +54,7 @@ type IssuerStorage interface { // CTStorage implements Storage. type CTStorage struct { - storeData func(context.Context, *ctonly.Entry) (uint64, error) + storeData func(context.Context, *ctonly.Entry) tessera.IndexFuture storeIssuers func(context.Context, []KV) error } @@ -68,7 +68,7 @@ func NewCTSTorage(logStorage tessera.Storage, issuerStorage IssuerStorage) (*CTS } // Add stores CT entries. -func (cts *CTStorage) Add(ctx context.Context, entry *ctonly.Entry) (uint64, error) { +func (cts *CTStorage) Add(ctx context.Context, entry *ctonly.Entry) tessera.IndexFuture { // TODO(phboneff): add deduplication and chain storage return cts.storeData(ctx, entry) }