From 0e4fa620ce9c7435888b65a8618a165a4ae9a26b Mon Sep 17 00:00:00 2001 From: Kexort Date: Mon, 22 Apr 2024 08:18:24 +0200 Subject: [PATCH 01/19] implement grantee management --- pkg/api/api.go | 4 +- pkg/api/api_test.go | 2 +- pkg/api/dynamicaccess.go | 122 +++++++++++++++++++++ pkg/api/dynamicaccess_test.go | 75 +++++++++++++ pkg/api/router.go | 9 ++ pkg/dynamicaccess/controller.go | 158 +++++++++++++-------------- pkg/dynamicaccess/controller_test.go | 145 ++++++++++++++++++------ pkg/dynamicaccess/grantee.go | 3 +- pkg/dynamicaccess/mock/service.go | 40 ++++--- pkg/dynamicaccess/service.go | 39 ------- pkg/node/devnode.go | 6 +- pkg/node/node.go | 6 +- 12 files changed, 429 insertions(+), 180 deletions(-) delete mode 100644 pkg/dynamicaccess/service.go diff --git a/pkg/api/api.go b/pkg/api/api.go index 00373c28186..ec5f4a508ad 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -154,7 +154,7 @@ type Service struct { feedFactory feeds.Factory signer crypto.Signer post postage.Service - dac dynamicaccess.Service + dac dynamicaccess.Controller postageContract postagecontract.Interface probe *Probe metricsRegistry *prometheus.Registry @@ -253,7 +253,7 @@ type ExtraOptions struct { Pss pss.Interface FeedFactory feeds.Factory Post postage.Service - Dac dynamicaccess.Service + Dac dynamicaccess.Controller PostageContract postagecontract.Interface Staking staking.Contract Steward steward.Interface diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index 00dd73fdd01..2c93a20353b 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -104,7 +104,7 @@ type testServerOptions struct { PostageContract postagecontract.Interface StakingContract staking.Contract Post postage.Service - Dac dynamicaccess.Service + Dac dynamicaccess.Controller Steward steward.Interface WsHeaders http.Header Authenticator auth.Authenticator diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index c7c1279609e..ed68d4cbb5c 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -3,8 +3,13 @@ package api import ( "context" "crypto/ecdsa" + "encoding/hex" + "encoding/json" + "io" "net/http" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/ethersphere/bee/v2/pkg/crypto" "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/log" storer "github.com/ethersphere/bee/v2/pkg/storer" @@ -28,6 +33,16 @@ func setAddressInContext(ctx context.Context, address swarm.Address) context.Con return context.WithValue(ctx, addressKey{}, address) } +type GranteesPatchRequest struct { + Addlist []string `json:"add"` + Revokelist []string `json:"revoke"` +} + +type GranteesPatch struct { + Addlist []ecdsa.PublicKey + Revokelist []ecdsa.PublicKey +} + // actDecryptionHandler is a middleware that looks up and decrypts the given address, // if the act headers are present func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { @@ -113,3 +128,110 @@ func (s *Service) actEncryptionHandler( return encryptedReference, nil } + +func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) { + logger := s.logger.WithName("acthandler").Build() + paths := struct { + GranteesAddress swarm.Address `map:"address,resolve" validate:"required"` + }{} + if response := s.mapStructure(r.Header, &paths); response != nil { + response("invalid path params", logger, w) + return + } + grantees, err := s.dac.GetGrantees(r.Context(), paths.GranteesAddress) + if err != nil { + jsonhttp.NotFound(w, "grantee list not found") + return + } + granteeSlice := make([]string, len(grantees)) + for i, grantee := range grantees { + granteeSlice[i] = hex.EncodeToString(crypto.EncodeSecp256k1PublicKey(grantee)) + } + jsonhttp.OK(w, granteeSlice) +} + +func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) { + logger := s.logger.WithName("acthandler").Build() + + if r.Body == http.NoBody { + logger.Error(nil, "request has no body") + jsonhttp.BadRequest(w, errInvalidRequest) + return + } + + paths := struct { + GranteesAddress swarm.Address `map:"address,resolve" validate:"required"` + }{} + if response := s.mapStructure(r.Header, &paths); response != nil { + response("invalid path params", logger, w) + return + } + + headers := struct { + BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"` + Publisher *ecdsa.PublicKey `map:"Swarm-Act-Publisher" validate:"required"` + HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address"` + }{} + if response := s.mapStructure(r.Header, &headers); response != nil { + response("invalid header params", logger, w) + return + } + + body, err := io.ReadAll(r.Body) + if err != nil { + if jsonhttp.HandleBodyReadError(err, w) { + return + } + logger.Debug("read request body failed", "error", err) + logger.Error(nil, "read request body failed") + jsonhttp.InternalServerError(w, "cannot read request") + return + } + + gpr := GranteesPatchRequest{} + if len(body) > 0 { + err = json.Unmarshal(body, &gpr) + if err != nil { + logger.Debug("unmarshal body failed", "error", err) + logger.Error(nil, "unmarshal body failed") + jsonhttp.InternalServerError(w, "error unmarshaling request body") + return + } + } + + grantees := GranteesPatch{} + for _, g := range gpr.Addlist { + h, _ := hex.DecodeString(g) + k, _ := btcec.ParsePubKey(h) + grantees.Addlist = append(grantees.Addlist, *k.ToECDSA()) + } + for _, g := range gpr.Revokelist { + h, _ := hex.DecodeString(g) + k, _ := btcec.ParsePubKey(h) + grantees.Revokelist = append(grantees.Revokelist, *k.ToECDSA()) + } + + tag, _ := s.getOrCreateSessionID(0) + + ctx := r.Context() + putter, _ := s.newStamperPutter(ctx, putterOptions{ + BatchID: headers.BatchID, + TagID: tag, + Pin: false, + Deferred: true, + }) + + granteeref := paths.GranteesAddress + granteeref, historyref, _ := s.dac.HandleGrantees(ctx, granteeref, *headers.HistoryAddress, headers.Publisher, convertToPointerSlice(grantees.Addlist), convertToPointerSlice(grantees.Revokelist)) + putter.Done(granteeref) + putter.Done(historyref) + jsonhttp.OK(w, nil) +} + +func convertToPointerSlice(slice []ecdsa.PublicKey) []*ecdsa.PublicKey { + pointerSlice := make([]*ecdsa.PublicKey, len(slice)) + for i, key := range slice { + pointerSlice[i] = &key + } + return pointerSlice +} diff --git a/pkg/api/dynamicaccess_test.go b/pkg/api/dynamicaccess_test.go index 480714444e0..a9dc706c2b7 100644 --- a/pkg/api/dynamicaccess_test.go +++ b/pkg/api/dynamicaccess_test.go @@ -802,3 +802,78 @@ func TestDacPublisher(t *testing.T) { ) }) } + +func TestDacGrantees(t *testing.T) { + t.Parallel() + var ( + spk, _ = hex.DecodeString("a786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfa") + pk, _ = crypto.DecodeSecp256k1PrivateKey(spk) + publicKeyBytes = crypto.EncodeSecp256k1PublicKey(&pk.PublicKey) + publisher = hex.EncodeToString(publicKeyBytes) + storerMock = mockstorer.New() + h, fixtureHref = prepareHistoryFixture(storerMock) + logger = log.Noop + addr = swarm.RandAddress(t) + client, _, _, _ = newTestServer(t, testServerOptions{ + Storer: storerMock, + Logger: logger, + Post: mockpost.New(mockpost.WithAcceptAll()), + PublicKey: pk.PublicKey, + Dac: mockdac.New(mockdac.WithHistory(h, fixtureHref.String())), + }) + ) + t.Run("get-grantees", func(t *testing.T) { + expected := []string{ + "03d7660772cc3142f8a7a2dfac46ce34d12eac1718720cef0e3d94347902aa96a2", + "03c712a7e29bc792ac8d8ae49793d28d5bda27ed70f0d90697b2fb456c0a168bd2", + "032541acf966823bae26c2c16a7102e728ade3e2e29c11a8a17b29d8eb2bd19302", + } + jsonhttptest.Request(t, client, http.MethodGet, "/grantee/"+addr.String(), http.StatusOK, + jsonhttptest.WithExpectedJSONResponse(expected), + ) + }) + + t.Run("get-grantees-missing-address", func(t *testing.T) { + jsonhttptest.Request(t, client, http.MethodGet, "/grantee/123", http.StatusBadRequest, + jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ + Message: "Unauthorized", + Code: http.StatusBadRequest, + }), + ) + }) + t.Run("get-grantees-wrong-address", func(t *testing.T) { + }) + t.Run("add-revoke-grantees", func(t *testing.T) { + }) + t.Run("add-revoke-grantees-empty-body", func(t *testing.T) { + jsonhttptest.Request(t, client, http.MethodPatch, "/grantee/"+addr.String(), http.StatusBadRequest, + jsonhttptest.WithRequestHeader(api.SwarmPostageBatchIdHeader, batchOkStr), + jsonhttptest.WithRequestHeader(api.SwarmActPublisherHeader, publisher), + jsonhttptest.WithRequestBody(bytes.NewReader(nil)), + jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ + Message: "could not validate request", + Code: http.StatusBadRequest, + }), + ) + }) + t.Run("add-grantee-with-history", func(t *testing.T) { + }) + t.Run("add-grantee-without-history", func(t *testing.T) { + body := api.GranteesPatchRequest{ + Addlist: []string{"02ab7473879005929d10ce7d4f626412dad9fe56b0a6622038931d26bd79abf0a4"}, + } + jsonhttptest.Request(t, client, http.MethodPatch, "/grantee/"+addr.String(), http.StatusOK, + jsonhttptest.WithJSONRequestBody(body), + ) + + expected := []string{ + "03d7660772cc3142f8a7a2dfac46ce34d12eac1718720cef0e3d94347902aa96a2", + "03c712a7e29bc792ac8d8ae49793d28d5bda27ed70f0d90697b2fb456c0a168bd2", + "032541acf966823bae26c2c16a7102e728ade3e2e29c11a8a17b29d8eb2bd19302", + "02ab7473879005929d10ce7d4f626412dad9fe56b0a6622038931d26bd79abf0a4", + } + jsonhttptest.Request(t, client, http.MethodGet, "/grantee/"+addr.String(), http.StatusOK, + jsonhttptest.WithExpectedJSONResponse(expected), + ) + }) +} diff --git a/pkg/api/router.go b/pkg/api/router.go index 1b1e1c877cb..1a2040a2639 100644 --- a/pkg/api/router.go +++ b/pkg/api/router.go @@ -266,6 +266,15 @@ func (s *Service) mountAPI() { ), }) + handle("/grantee/{address}", jsonhttp.MethodHandler{ + "GET": web.ChainHandlers( + web.FinalHandlerFunc(s.actListGranteesHandler), + ), + "PATCH": web.ChainHandlers( + web.FinalHandlerFunc(s.actGrantRevokeHandler), + ), + }) + handle("/bzz/{address}", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { u := r.URL u.Path += "/" diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index fdef1c4971a..f6538af59c4 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -3,6 +3,7 @@ package dynamicaccess import ( "context" "crypto/ecdsa" + "io" "time" "github.com/ethersphere/bee/v2/pkg/file/loadsave" @@ -10,26 +11,16 @@ import ( "github.com/ethersphere/bee/v2/pkg/file/pipeline/builder" "github.com/ethersphere/bee/v2/pkg/file/redundancy" "github.com/ethersphere/bee/v2/pkg/kvs" - kvsmock "github.com/ethersphere/bee/v2/pkg/kvs/mock" "github.com/ethersphere/bee/v2/pkg/storage" "github.com/ethersphere/bee/v2/pkg/swarm" ) +const granteeListEncrypt = true + type GranteeManager interface { - //PUT /grantees/{grantee} - //body: {publisher?, grantee root hash ,grantee} - Grant(ctx context.Context, granteesAddress swarm.Address, grantee *ecdsa.PublicKey) error - //DELETE /grantees/{grantee} - //body: {publisher?, grantee root hash , grantee} - Revoke(ctx context.Context, granteesAddress swarm.Address, grantee *ecdsa.PublicKey) error - //[ ] - //POST /grantees - //body: {publisher, historyRootHash} - Commit(ctx context.Context, granteesAddress swarm.Address, actRootHash swarm.Address, publisher *ecdsa.PublicKey) (swarm.Address, swarm.Address, error) - - //Post /grantees + //PATCH /grantees //{publisher, addList, removeList} - HandleGrantees(ctx context.Context, rootHash swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) error + HandleGrantees(ctx context.Context, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, error) //GET /grantees/{history root hash} GetGrantees(ctx context.Context, rootHash swarm.Address) ([]*ecdsa.PublicKey, error) @@ -43,15 +34,13 @@ type Controller interface { // TODO: history encryption // UploadHandler encrypts the reference and stores it in the history as the latest update. UploadHandler(ctx context.Context, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) + io.Closer } type controller struct { accessLogic ActLogic - granteeList GranteeList - //[ ]: do we need to protect this with a mutex? - revokeFlag []swarm.Address - getter storage.Getter - putter storage.Putter + getter storage.Getter + putter storage.Putter } var _ Controller = (*controller)(nil) @@ -90,8 +79,8 @@ func (c *controller) UploadHandler( ls := loadsave.New(c.getter, c.putter, requestPipelineFactory(ctx, c.putter, false, redundancy.NONE)) historyRef := historyRootHash var ( - storage kvs.KeyValueStore - storageRef swarm.Address + storage kvs.KeyValueStore + actRef swarm.Address ) now := time.Now().Unix() if historyRef.IsZero() { @@ -107,12 +96,12 @@ func (c *controller) UploadHandler( if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } - storageRef, err = storage.Save(ctx) + actRef, err = storage.Save(ctx) if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } // TODO: pass granteelist ref as mtdt - err = history.Add(ctx, storageRef, &now, nil) + err = history.Add(ctx, actRef, &now, nil) if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } @@ -127,101 +116,105 @@ func (c *controller) UploadHandler( } // TODO: hanlde granteelist ref in mtdt entry, err := history.Lookup(ctx, now) - storageRef = entry.Reference() + actRef = entry.Reference() if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } - storage, err = kvs.NewReference(ls, storageRef) + storage, err = kvs.NewReference(ls, actRef) if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } encryptedRef, err := c.accessLogic.EncryptRef(ctx, storage, publisher, refrefence) - return storageRef, historyRef, encryptedRef, err + return actRef, historyRef, encryptedRef, err } func NewController(ctx context.Context, accessLogic ActLogic, getter storage.Getter, putter storage.Putter) Controller { return &controller{ - granteeList: nil, accessLogic: accessLogic, getter: getter, putter: putter, } } -func (c *controller) Grant(ctx context.Context, granteesAddress swarm.Address, grantee *ecdsa.PublicKey) error { - return c.granteeList.Add([]*ecdsa.PublicKey{grantee}) -} +func (c *controller) HandleGrantees(ctx context.Context, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, error) { + var ( + err error + h History + act kvs.KeyValueStore + ls = loadsave.New(c.getter, c.putter, requestPipelineFactory(ctx, c.putter, false, redundancy.NONE)) + gls = loadsave.New(c.getter, c.putter, requestPipelineFactory(ctx, c.putter, granteeListEncrypt, redundancy.NONE)) + ) + if !historyref.IsZero() { + h, err = NewHistoryReference(ls, historyref) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err + } + entry, err := h.Lookup(ctx, time.Now().Unix()) -func (c *controller) Revoke(ctx context.Context, granteesAddress swarm.Address, grantee *ecdsa.PublicKey) error { - if !c.isRevokeFlagged(granteesAddress) { - c.setRevokeFlag(granteesAddress, true) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err + } + actref := entry.Reference() + act, err = kvs.NewReference(ls, actref) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err + } + } else { + h, err = NewHistory(ls) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err + } + act, err = kvs.New(ls) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err + } } - return c.granteeList.Remove([]*ecdsa.PublicKey{grantee}) -} -func (c *controller) Commit(ctx context.Context, granteesAddress swarm.Address, actRootHash swarm.Address, publisher *ecdsa.PublicKey) (swarm.Address, swarm.Address, error) { - var act kvs.KeyValueStore - if c.isRevokeFlagged(granteesAddress) { - act = kvsmock.New() - c.accessLogic.AddPublisher(ctx, act, publisher) + var gl GranteeList + if granteeref.IsZero() { + gl = NewGranteeList(gls) } else { - act = kvsmock.NewReference(actRootHash) + gl = NewGranteeListReference(gls, granteeref) } + gl.Add(addList) + gl.Remove(removeList) - grantees := c.granteeList.Get() - for _, grantee := range grantees { - c.accessLogic.AddGrantee(ctx, act, publisher, grantee, nil) + granteesToAdd := addList + + // generate new access key and new act + if len(removeList) != 0 || granteeref.IsZero() { + c.accessLogic.AddPublisher(ctx, act, publisher) + granteesToAdd = gl.Get() } - granteeref, err := c.granteeList.Save(ctx) - if err != nil { - return swarm.EmptyAddress, swarm.EmptyAddress, err + for _, grantee := range granteesToAdd { + c.accessLogic.AddGrantee(ctx, act, publisher, grantee, nil) } actref, err := act.Save(ctx) if err != nil { - return swarm.EmptyAddress, swarm.EmptyAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, err } - c.setRevokeFlag(granteesAddress, false) - return granteeref, actref, err -} - -func (c *controller) HandleGrantees(ctx context.Context, granteesAddress swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) error { - act := kvsmock.New() - - c.accessLogic.AddPublisher(ctx, act, publisher) - for _, grantee := range addList { - c.accessLogic.AddGrantee(ctx, act, publisher, grantee, nil) + h.Add(ctx, actref, nil, nil) + href, err := h.Store(ctx) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err } - return nil -} -func (c *controller) GetGrantees(ctx context.Context, granteeRootHash swarm.Address) ([]*ecdsa.PublicKey, error) { - return c.granteeList.Get(), nil -} - -func (c *controller) isRevokeFlagged(granteeRootHash swarm.Address) bool { - for _, revoke := range c.revokeFlag { - if revoke.Equal(granteeRootHash) { - return true - } + glref, err := gl.Save(ctx) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err } - return false + return glref, href, nil } -func (c *controller) setRevokeFlag(granteeRootHash swarm.Address, set bool) { - if set { - c.revokeFlag = append(c.revokeFlag, granteeRootHash) - } else { - for i, revoke := range c.revokeFlag { - if revoke.Equal(granteeRootHash) { - c.revokeFlag = append(c.revokeFlag[:i], c.revokeFlag[i+1:]...) - } - } - } +func (c *controller) GetGrantees(ctx context.Context, granteeRef swarm.Address) ([]*ecdsa.PublicKey, error) { + ls := loadsave.New(c.getter, c.putter, requestPipelineFactory(ctx, c.putter, granteeListEncrypt, redundancy.NONE)) + gl := NewGranteeListReference(ls, granteeRef) + return gl.Get(), nil } func requestPipelineFactory(ctx context.Context, s storage.Putter, encrypt bool, rLevel redundancy.Level) func() pipeline.Interface { @@ -229,3 +222,8 @@ func requestPipelineFactory(ctx context.Context, s storage.Putter, encrypt bool, return builder.NewPipelineBuilder(ctx, s, encrypt, rLevel) } } + +// TODO: what to do in close ? +func (s *controller) Close() error { + return nil +} diff --git a/pkg/dynamicaccess/controller_test.go b/pkg/dynamicaccess/controller_test.go index a48d426466e..55131d3793b 100644 --- a/pkg/dynamicaccess/controller_test.go +++ b/pkg/dynamicaccess/controller_test.go @@ -3,21 +3,16 @@ package dynamicaccess_test import ( "context" "crypto/ecdsa" - "encoding/hex" "testing" "time" "github.com/ethersphere/bee/v2/pkg/dynamicaccess" - "github.com/ethersphere/bee/v2/pkg/encryption" "github.com/ethersphere/bee/v2/pkg/file" "github.com/ethersphere/bee/v2/pkg/kvs" "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/stretchr/testify/assert" - "golang.org/x/crypto/sha3" ) -var hashFunc = sha3.NewLegacyKeccak256 - func getHistoryFixture(ctx context.Context, ls file.LoadSaver, al dynamicaccess.ActLogic, publisher *ecdsa.PublicKey) (swarm.Address, error) { h, err := dynamicaccess.NewHistory(ls) if err != nil { @@ -30,12 +25,12 @@ func getHistoryFixture(ctx context.Context, ls file.LoadSaver, al dynamicaccess. al.AddPublisher(ctx, kvs0, publisher) kvs0Ref, _ := kvs0.Save(ctx) kvs1, _ := kvs.New(ls) - al.AddGrantee(ctx, kvs1, publisher, &pk1.PublicKey, nil) al.AddPublisher(ctx, kvs1, publisher) + al.AddGrantee(ctx, kvs1, publisher, &pk1.PublicKey, nil) kvs1Ref, _ := kvs1.Save(ctx) kvs2, _ := kvs.New(ls) - al.AddGrantee(ctx, kvs2, publisher, &pk2.PublicKey, nil) al.AddPublisher(ctx, kvs2, publisher) + al.AddGrantee(ctx, kvs2, publisher, &pk2.PublicKey, nil) kvs2Ref, _ := kvs2.Save(ctx) firstTime := time.Date(1994, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() secondTime := time.Date(2000, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() @@ -47,55 +42,139 @@ func getHistoryFixture(ctx context.Context, ls file.LoadSaver, al dynamicaccess. return h.Store(ctx) } -// TODO: separate up down test with fixture, now these just check if the flow works at all -func TestController_NewUploadDownload(t *testing.T) { +func TestController_NewUpload(t *testing.T) { ctx := context.Background() - publisher := getPrivKey(1) + publisher := getPrivKey(0) diffieHellman := dynamicaccess.NewDefaultSession(publisher) al := dynamicaccess.NewLogic(diffieHellman) c := dynamicaccess.NewController(ctx, al, mockStorer.ChunkStore(), mockStorer.Cache()) ref := swarm.RandAddress(t) - _, hRef, encryptedRef, err := c.UploadHandler(ctx, ref, &publisher.PublicKey, swarm.ZeroAddress) - assert.NoError(t, err) - dref, err := c.DownloadHandler(ctx, encryptedRef, &publisher.PublicKey, hRef, time.Now().Unix()) + _, hRef, encRef, err := c.UploadHandler(ctx, ref, &publisher.PublicKey, swarm.ZeroAddress) + + ls := createLs() + h, err := dynamicaccess.NewHistoryReference(ls, hRef) + entry, err := h.Lookup(ctx, time.Now().Unix()) + actRef := entry.Reference() + act, err := kvs.NewReference(ls, actRef) + expRef, err := al.EncryptRef(ctx, act, &publisher.PublicKey, ref) + assert.NoError(t, err) - assert.Equal(t, ref, dref) + assert.Equal(t, encRef, expRef) + assert.NotEqual(t, hRef, swarm.ZeroAddress) } -func TestController_ExistingUploadDownload(t *testing.T) { - ls := createLs() +func TestController_PublisherDownload(t *testing.T) { ctx := context.Background() publisher := getPrivKey(0) diffieHellman := dynamicaccess.NewDefaultSession(publisher) al := dynamicaccess.NewLogic(diffieHellman) c := dynamicaccess.NewController(ctx, al, mockStorer.ChunkStore(), mockStorer.Cache()) + ls := createLs() ref := swarm.RandAddress(t) - hRef, err := getHistoryFixture(ctx, ls, al, &publisher.PublicKey) - assert.NoError(t, err) - _, hRef, encryptedRef, err := c.UploadHandler(ctx, ref, &publisher.PublicKey, hRef) + href, err := getHistoryFixture(ctx, ls, al, &publisher.PublicKey) + h, err := dynamicaccess.NewHistoryReference(ls, href) + entry, err := h.Lookup(ctx, time.Now().Unix()) + actRef := entry.Reference() + act, err := kvs.NewReference(ls, actRef) + encRef, err := al.EncryptRef(ctx, act, &publisher.PublicKey, ref) + assert.NoError(t, err) - dref, err := c.DownloadHandler(ctx, encryptedRef, &publisher.PublicKey, hRef, time.Now().Unix()) + dref, err := c.DownloadHandler(ctx, encRef, &publisher.PublicKey, href, time.Now().Unix()) assert.NoError(t, err) assert.Equal(t, ref, dref) } -func TestControllerGrant(t *testing.T) { -} +func TestController_GranteeDownload(t *testing.T) { + ctx := context.Background() + publisher := getPrivKey(0) + grantee := getPrivKey(2) + publisherDH := dynamicaccess.NewDefaultSession(publisher) + publisherAL := dynamicaccess.NewLogic(publisherDH) -func TestControllerRevoke(t *testing.T) { + diffieHellman := dynamicaccess.NewDefaultSession(grantee) + al := dynamicaccess.NewLogic(diffieHellman) + ls := createLs() + c := dynamicaccess.NewController(ctx, al, mockStorer.ChunkStore(), mockStorer.Cache()) + ref := swarm.RandAddress(t) + href, err := getHistoryFixture(ctx, ls, publisherAL, &publisher.PublicKey) + h, err := dynamicaccess.NewHistoryReference(ls, href) + ts := time.Date(2001, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() + entry, err := h.Lookup(ctx, ts) + actRef := entry.Reference() + act, err := kvs.NewReference(ls, actRef) + encRef, err := publisherAL.EncryptRef(ctx, act, &publisher.PublicKey, ref) + assert.NoError(t, err) + dref, err := c.DownloadHandler(ctx, encRef, &publisher.PublicKey, href, ts) + assert.NoError(t, err) + assert.Equal(t, ref, dref) } -func TestControllerCommit(t *testing.T) { +func TestController_HandleGrantees(t *testing.T) { + ctx := context.Background() + publisher := getPrivKey(1) + diffieHellman := dynamicaccess.NewDefaultSession(publisher) + al := dynamicaccess.NewLogic(diffieHellman) + ls := createLs() + c := dynamicaccess.NewController(ctx, al, mockStorer.ChunkStore(), mockStorer.Cache()) + href, _ := getHistoryFixture(ctx, ls, al, &publisher.PublicKey) -} + grantee1 := getPrivKey(0) + grantee := getPrivKey(2) -func prepareEncryptedChunkReference(ak []byte) (swarm.Address, swarm.Address) { - addr, _ := hex.DecodeString("f7b1a45b70ee91d3dbfd98a2a692387f24db7279a9c96c447409e9205cf265baef29bf6aa294264762e33f6a18318562c86383dd8bfea2cec14fae08a8039bf3") - e1 := encryption.New(ak, 0, uint32(0), hashFunc) - ech, err := e1.Encrypt(addr) - if err != nil { - return swarm.EmptyAddress, swarm.EmptyAddress - } - return swarm.NewAddress(ech), swarm.NewAddress(addr) + t.Run("add to new list", func(t *testing.T) { + addList := []*ecdsa.PublicKey{&grantee.PublicKey} + granteeRef, _, err := c.HandleGrantees(ctx, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + + gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + + assert.NoError(t, err) + assert.Len(t, gl.Get(), 1) + }) + t.Run("add to existing list", func(t *testing.T) { + addList := []*ecdsa.PublicKey{&grantee.PublicKey} + granteeRef, _, err := c.HandleGrantees(ctx, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + + gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + + assert.NoError(t, err) + assert.Len(t, gl.Get(), 1) + + addList = []*ecdsa.PublicKey{&getPrivKey(0).PublicKey} + granteeRef, _, err = c.HandleGrantees(ctx, granteeRef, href, &publisher.PublicKey, addList, nil) + gl = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + assert.NoError(t, err) + assert.Len(t, gl.Get(), 2) + }) + t.Run("add and revoke", func(t *testing.T) { + addList := []*ecdsa.PublicKey{&grantee.PublicKey} + revokeList := []*ecdsa.PublicKey{&grantee1.PublicKey} + gl := dynamicaccess.NewGranteeList(createLs()) + gl.Add([]*ecdsa.PublicKey{&publisher.PublicKey, &grantee1.PublicKey}) + granteeRef, err := gl.Save(ctx) + + granteeRef, _, err = c.HandleGrantees(ctx, granteeRef, href, &publisher.PublicKey, addList, revokeList) + gl = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + + assert.NoError(t, err) + assert.Len(t, gl.Get(), 2) + }) + + t.Run("add twice", func(t *testing.T) { + addList := []*ecdsa.PublicKey{&grantee.PublicKey, &grantee.PublicKey} + granteeRef, _, err := c.HandleGrantees(ctx, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, _, err = c.HandleGrantees(ctx, granteeRef, href, &publisher.PublicKey, addList, nil) + gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + + assert.NoError(t, err) + assert.Len(t, gl.Get(), 1) + }) + t.Run("revoke non-existing", func(t *testing.T) { + addList := []*ecdsa.PublicKey{&grantee.PublicKey} + granteeRef, _, err := c.HandleGrantees(ctx, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + + assert.NoError(t, err) + assert.Len(t, gl.Get(), 1) + }) } diff --git a/pkg/dynamicaccess/grantee.go b/pkg/dynamicaccess/grantee.go index 6724b718e4f..514dd2a550e 100644 --- a/pkg/dynamicaccess/grantee.go +++ b/pkg/dynamicaccess/grantee.go @@ -6,6 +6,7 @@ import ( "crypto/elliptic" "fmt" + "github.com/btcsuite/btcd/btcec/v2" "github.com/ethersphere/bee/v2/pkg/file" "github.com/ethersphere/bee/v2/pkg/swarm" ) @@ -61,7 +62,7 @@ func (g *GranteeListStruct) deserialize(data []byte) []*ecdsa.PublicKey { } func (g *GranteeListStruct) deserializeBytes(data []byte) *ecdsa.PublicKey { - curve := elliptic.P256() + curve := btcec.S256() x, y := elliptic.Unmarshal(curve, data) return &ecdsa.PublicKey{Curve: curve, X: x, Y: y} } diff --git a/pkg/dynamicaccess/mock/service.go b/pkg/dynamicaccess/mock/service.go index 6f4d5f09e72..485de90f6a9 100644 --- a/pkg/dynamicaccess/mock/service.go +++ b/pkg/dynamicaccess/mock/service.go @@ -44,7 +44,7 @@ type Option interface { func (f optionFunc) apply(r *mockDacService) { f(r) } // New creates a new mock dynamicaccess service. -func New(o ...Option) dynamicaccess.Service { +func New(o ...Option) dynamicaccess.Controller { storer := mockstorer.New() m := &mockDacService{ historyMap: make(map[string]dynamicaccess.History), @@ -141,20 +141,32 @@ func (m *mockDacService) Close() error { return nil } -func (m *mockDacService) Grant(ctx context.Context, granteesAddress swarm.Address, grantee *ecdsa.PublicKey) error { - return nil -} -func (m *mockDacService) Revoke(ctx context.Context, granteesAddress swarm.Address, grantee *ecdsa.PublicKey) error { - return nil -} -func (m *mockDacService) Commit(ctx context.Context, granteesAddress swarm.Address, actRootHash swarm.Address, publisher *ecdsa.PublicKey) (swarm.Address, swarm.Address, error) { - return swarm.ZeroAddress, swarm.ZeroAddress, nil -} -func (m *mockDacService) HandleGrantees(ctx context.Context, rootHash swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) error { - return nil +func (m *mockDacService) HandleGrantees(ctx context.Context, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, error) { + historyRef, _ := swarm.ParseHexAddress("67bdf80a9bbea8eca9c8480e43fdceb485d2d74d5708e45144b8c4adacd13d9c") + glRef, _ := swarm.ParseHexAddress("3339613565613837623134316665343461613630396333333237656364383934") + return glRef, historyRef, nil } -func (m *mockDacService) GetGrantees(ctx context.Context, rootHash swarm.Address) ([]*ecdsa.PublicKey, error) { - return nil, nil +func (m *mockDacService) GetGrantees(ctx context.Context, granteeref swarm.Address) ([]*ecdsa.PublicKey, error) { + keys := []string{ + "a786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfa", + "b786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfb", + "c786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfc", + } + var pubkeys []*ecdsa.PublicKey + for i := range keys { + data, err := hex.DecodeString(keys[i]) + if err != nil { + panic(err) + } + + privKey, err := crypto.DecodeSecp256k1PrivateKey(data) + pubKey := privKey.PublicKey + if err != nil { + panic(err) + } + pubkeys = append(pubkeys, &pubKey) + } + return pubkeys, nil } func requestPipelineFactory(ctx context.Context, s storage.Putter, encrypt bool, rLevel redundancy.Level) func() pipeline.Interface { diff --git a/pkg/dynamicaccess/service.go b/pkg/dynamicaccess/service.go deleted file mode 100644 index b9cedbcf82b..00000000000 --- a/pkg/dynamicaccess/service.go +++ /dev/null @@ -1,39 +0,0 @@ -package dynamicaccess - -import ( - "context" - "crypto/ecdsa" - "io" - - "github.com/ethersphere/bee/v2/pkg/swarm" -) - -type Service interface { - DownloadHandler(ctx context.Context, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) - UploadHandler(ctx context.Context, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) - io.Closer -} - -// TODO: is service needed at all? -> it is just a wrapper around controller -type service struct { - controller Controller -} - -func (s *service) DownloadHandler(ctx context.Context, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) { - return s.controller.DownloadHandler(ctx, encryptedRef, publisher, historyRootHash, timestamp) -} - -func (s *service) UploadHandler(ctx context.Context, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) { - return s.controller.UploadHandler(ctx, reference, publisher, historyRootHash) -} - -// TODO: what to do in close ? -func (s *service) Close() error { - return nil -} - -func NewService(controller Controller) (Service, error) { - return &service{ - controller: controller, - }, nil -} diff --git a/pkg/node/devnode.go b/pkg/node/devnode.go index e838f93a287..4e96a301769 100644 --- a/pkg/node/devnode.go +++ b/pkg/node/devnode.go @@ -238,11 +238,7 @@ func NewDevBee(logger log.Logger, o *DevOptions) (b *DevBee, err error) { session := dynamicaccess.NewDefaultSession(mockKey) actLogic := dynamicaccess.NewLogic(session) - ctrl := dynamicaccess.NewController(context.Background(), actLogic, localStore.ChunkStore(), localStore.Cache()) - dac, err := dynamicaccess.NewService(ctrl) - if err != nil { - return nil, fmt.Errorf("dac service: %w", err) - } + dac := dynamicaccess.NewController(context.Background(), actLogic, localStore.ChunkStore(), localStore.Cache()) b.dacCloser = dac pssService := pss.New(mockKey, logger) diff --git a/pkg/node/node.go b/pkg/node/node.go index 786c9abe864..f16f2579e85 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -776,11 +776,7 @@ func NewBee( evictFn = func(id []byte) error { return localStore.EvictBatch(context.Background(), id) } actLogic := dynamicaccess.NewLogic(session) - ctrl := dynamicaccess.NewController(ctx, actLogic, localStore.ChunkStore(), localStore.Cache()) - dac, err := dynamicaccess.NewService(ctrl) - if err != nil { - return nil, fmt.Errorf("dac service: %w", err) - } + dac := dynamicaccess.NewController(ctx, actLogic, localStore.ChunkStore(), localStore.Cache()) b.dacCloser = dac var ( From 953ad35d0108dabb0f0f3fe9f2c8a88cbb8e1892 Mon Sep 17 00:00:00 2001 From: Kexort Date: Mon, 22 Apr 2024 14:12:31 +0200 Subject: [PATCH 02/19] Add POST endpoint + fixes --- pkg/api/dynamicaccess.go | 93 ++++++++++++++++++++++++++++--- pkg/api/dynamicaccess_test.go | 62 ++++++++++++++++----- pkg/api/router.go | 6 ++ pkg/dynamicaccess/controller.go | 9 +-- pkg/dynamicaccess/grantee_test.go | 20 +++++-- 5 files changed, 160 insertions(+), 30 deletions(-) diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index ed68d4cbb5c..564c8a64815 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -38,6 +38,19 @@ type GranteesPatchRequest struct { Revokelist []string `json:"revoke"` } +type GranteesPatchResponse struct { + Reference swarm.Address `json:"ref"` + HistoryReference swarm.Address `json:"historyref"` +} + +type GranteesPostRequest struct { + GranteeList []string `json:"grantees"` +} + +type GranteesPostResponse struct { + Reference swarm.Address `json:"ref"` + HistoryReference swarm.Address `json:"historyref"` +} type GranteesPatch struct { Addlist []ecdsa.PublicKey Revokelist []ecdsa.PublicKey @@ -134,7 +147,7 @@ func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) paths := struct { GranteesAddress swarm.Address `map:"address,resolve" validate:"required"` }{} - if response := s.mapStructure(r.Header, &paths); response != nil { + if response := s.mapStructure(mux.Vars(r), &paths); response != nil { response("invalid path params", logger, w) return } @@ -162,15 +175,14 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) paths := struct { GranteesAddress swarm.Address `map:"address,resolve" validate:"required"` }{} - if response := s.mapStructure(r.Header, &paths); response != nil { + if response := s.mapStructure(mux.Vars(r), &paths); response != nil { response("invalid path params", logger, w) return } headers := struct { - BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"` - Publisher *ecdsa.PublicKey `map:"Swarm-Act-Publisher" validate:"required"` - HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address"` + BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"` + HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address" validate:"required"` }{} if response := s.mapStructure(r.Header, &headers); response != nil { response("invalid header params", logger, w) @@ -222,10 +234,77 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) }) granteeref := paths.GranteesAddress - granteeref, historyref, _ := s.dac.HandleGrantees(ctx, granteeref, *headers.HistoryAddress, headers.Publisher, convertToPointerSlice(grantees.Addlist), convertToPointerSlice(grantees.Revokelist)) + granteeref, historyref, _ := s.dac.HandleGrantees(ctx, granteeref, *headers.HistoryAddress, &s.publicKey, convertToPointerSlice(grantees.Addlist), convertToPointerSlice(grantees.Revokelist)) + putter.Done(granteeref) + putter.Done(historyref) + jsonhttp.OK(w, GranteesPatchResponse{ + Reference: granteeref, + HistoryReference: historyref, + }) +} + +func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Request) { + logger := s.logger.WithName("acthandler").Build() + + if r.Body == http.NoBody { + logger.Error(nil, "request has no body") + jsonhttp.BadRequest(w, errInvalidRequest) + return + } + + headers := struct { + BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"` + }{} + if response := s.mapStructure(r.Header, &headers); response != nil { + response("invalid header params", logger, w) + return + } + + body, err := io.ReadAll(r.Body) + if err != nil { + if jsonhttp.HandleBodyReadError(err, w) { + return + } + logger.Debug("read request body failed", "error", err) + logger.Error(nil, "read request body failed") + jsonhttp.InternalServerError(w, "cannot read request") + return + } + + gpr := GranteesPostRequest{} + if len(body) > 0 { + err = json.Unmarshal(body, &gpr) + if err != nil { + logger.Debug("unmarshal body failed", "error", err) + logger.Error(nil, "unmarshal body failed") + jsonhttp.InternalServerError(w, "error unmarshaling request body") + return + } + } + + list := make([]ecdsa.PublicKey, len(gpr.GranteeList)) + for _, g := range gpr.GranteeList { + h, _ := hex.DecodeString(g) + k, _ := btcec.ParsePubKey(h) + list = append(list, *k.ToECDSA()) + } + tag, _ := s.getOrCreateSessionID(0) + + ctx := r.Context() + putter, _ := s.newStamperPutter(ctx, putterOptions{ + BatchID: headers.BatchID, + TagID: tag, + Pin: false, + Deferred: true, + }) + + granteeref, historyref, _ := s.dac.HandleGrantees(ctx, swarm.ZeroAddress, swarm.ZeroAddress, &s.publicKey, convertToPointerSlice(list), nil) putter.Done(granteeref) putter.Done(historyref) - jsonhttp.OK(w, nil) + jsonhttp.Created(w, GranteesPostResponse{ + Reference: granteeref, + HistoryReference: historyref, + }) } func convertToPointerSlice(slice []ecdsa.PublicKey) []*ecdsa.PublicKey { diff --git a/pkg/api/dynamicaccess_test.go b/pkg/api/dynamicaccess_test.go index a9dc706c2b7..4405076b4c8 100644 --- a/pkg/api/dynamicaccess_test.go +++ b/pkg/api/dynamicaccess_test.go @@ -808,8 +808,6 @@ func TestDacGrantees(t *testing.T) { var ( spk, _ = hex.DecodeString("a786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfa") pk, _ = crypto.DecodeSecp256k1PrivateKey(spk) - publicKeyBytes = crypto.EncodeSecp256k1PublicKey(&pk.PublicKey) - publisher = hex.EncodeToString(publicKeyBytes) storerMock = mockstorer.New() h, fixtureHref = prepareHistoryFixture(storerMock) logger = log.Noop @@ -841,14 +839,20 @@ func TestDacGrantees(t *testing.T) { }), ) }) - t.Run("get-grantees-wrong-address", func(t *testing.T) { - }) t.Run("add-revoke-grantees", func(t *testing.T) { + body := api.GranteesPatchRequest{ + Addlist: []string{"02ab7473879005929d10ce7d4f626412dad9fe56b0a6622038931d26bd79abf0a4"}, + Revokelist: []string{"02ab7473879005929d10ce7d4f626412dad9fe56b0a6622038931d26bd79abf0a4"}, + } + jsonhttptest.Request(t, client, http.MethodPatch, "/grantee/"+addr.String(), http.StatusOK, + jsonhttptest.WithRequestHeader(api.SwarmPostageBatchIdHeader, batchOkStr), + jsonhttptest.WithRequestHeader(api.SwarmActHistoryAddressHeader, addr.String()), + jsonhttptest.WithJSONRequestBody(body), + ) }) t.Run("add-revoke-grantees-empty-body", func(t *testing.T) { jsonhttptest.Request(t, client, http.MethodPatch, "/grantee/"+addr.String(), http.StatusBadRequest, jsonhttptest.WithRequestHeader(api.SwarmPostageBatchIdHeader, batchOkStr), - jsonhttptest.WithRequestHeader(api.SwarmActPublisherHeader, publisher), jsonhttptest.WithRequestBody(bytes.NewReader(nil)), jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ Message: "could not validate request", @@ -857,23 +861,55 @@ func TestDacGrantees(t *testing.T) { ) }) t.Run("add-grantee-with-history", func(t *testing.T) { + body := api.GranteesPatchRequest{ + Addlist: []string{"02ab7473879005929d10ce7d4f626412dad9fe56b0a6622038931d26bd79abf0a4"}, + } + jsonhttptest.Request(t, client, http.MethodPatch, "/grantee/"+addr.String(), http.StatusOK, + jsonhttptest.WithRequestHeader(api.SwarmPostageBatchIdHeader, batchOkStr), + jsonhttptest.WithRequestHeader(api.SwarmActHistoryAddressHeader, addr.String()), + jsonhttptest.WithJSONRequestBody(body), + ) }) t.Run("add-grantee-without-history", func(t *testing.T) { body := api.GranteesPatchRequest{ Addlist: []string{"02ab7473879005929d10ce7d4f626412dad9fe56b0a6622038931d26bd79abf0a4"}, } - jsonhttptest.Request(t, client, http.MethodPatch, "/grantee/"+addr.String(), http.StatusOK, + jsonhttptest.Request(t, client, http.MethodPatch, "/grantee/"+addr.String(), http.StatusBadRequest, + jsonhttptest.WithRequestHeader(api.SwarmPostageBatchIdHeader, batchOkStr), jsonhttptest.WithJSONRequestBody(body), ) - expected := []string{ - "03d7660772cc3142f8a7a2dfac46ce34d12eac1718720cef0e3d94347902aa96a2", - "03c712a7e29bc792ac8d8ae49793d28d5bda27ed70f0d90697b2fb456c0a168bd2", - "032541acf966823bae26c2c16a7102e728ade3e2e29c11a8a17b29d8eb2bd19302", - "02ab7473879005929d10ce7d4f626412dad9fe56b0a6622038931d26bd79abf0a4", + }) + t.Run("create-granteelist", func(t *testing.T) { + body := api.GranteesPostRequest{ + GranteeList: []string{ + "02ab7473879005929d10ce7d4f626412dad9fe56b0a6622038931d26bd79abf0a4", + "03d7660772cc3142f8a7a2dfac46ce34d12eac1718720cef0e3d94347902aa96a2", + }, } - jsonhttptest.Request(t, client, http.MethodGet, "/grantee/"+addr.String(), http.StatusOK, - jsonhttptest.WithExpectedJSONResponse(expected), + jsonhttptest.Request(t, client, http.MethodPost, "/grantee", http.StatusCreated, + jsonhttptest.WithRequestHeader(api.SwarmPostageBatchIdHeader, batchOkStr), + jsonhttptest.WithJSONRequestBody(body), + ) + }) + t.Run("create-granteelist-without-stamp", func(t *testing.T) { + body := api.GranteesPostRequest{ + GranteeList: []string{ + "03d7660772cc3142f8a7a2dfac46ce34d12eac1718720cef0e3d94347902aa96a2", + }, + } + jsonhttptest.Request(t, client, http.MethodPost, "/grantee", http.StatusBadRequest, + jsonhttptest.WithJSONRequestBody(body), + ) + }) + t.Run("create-granteelist-empty-body", func(t *testing.T) { + jsonhttptest.Request(t, client, http.MethodPost, "/grantee", http.StatusBadRequest, + jsonhttptest.WithRequestHeader(api.SwarmPostageBatchIdHeader, batchOkStr), + jsonhttptest.WithRequestBody(bytes.NewReader(nil)), + jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ + Message: "could not validate request", + Code: http.StatusBadRequest, + }), ) }) } diff --git a/pkg/api/router.go b/pkg/api/router.go index 1a2040a2639..8f3794b6828 100644 --- a/pkg/api/router.go +++ b/pkg/api/router.go @@ -266,6 +266,12 @@ func (s *Service) mountAPI() { ), }) + handle("/grantee", jsonhttp.MethodHandler{ + "POST": web.ChainHandlers( + web.FinalHandlerFunc(s.actCreateGranteesHandler), + ), + }) + handle("/grantee/{address}", jsonhttp.MethodHandler{ "GET": web.ChainHandlers( web.FinalHandlerFunc(s.actListGranteesHandler), diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index f6538af59c4..382b8fc463d 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -18,11 +18,7 @@ import ( const granteeListEncrypt = true type GranteeManager interface { - //PATCH /grantees - //{publisher, addList, removeList} HandleGrantees(ctx context.Context, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, error) - - //GET /grantees/{history root hash} GetGrantees(ctx context.Context, rootHash swarm.Address) ([]*ecdsa.PublicKey, error) } @@ -181,12 +177,13 @@ func (c *controller) HandleGrantees(ctx context.Context, granteeref swarm.Addres gl.Add(addList) gl.Remove(removeList) - granteesToAdd := addList - + var granteesToAdd []*ecdsa.PublicKey // generate new access key and new act if len(removeList) != 0 || granteeref.IsZero() { c.accessLogic.AddPublisher(ctx, act, publisher) granteesToAdd = gl.Get() + } else { + granteesToAdd = addList } for _, grantee := range granteesToAdd { diff --git a/pkg/dynamicaccess/grantee_test.go b/pkg/dynamicaccess/grantee_test.go index 0578be28ff4..573171ba9d9 100644 --- a/pkg/dynamicaccess/grantee_test.go +++ b/pkg/dynamicaccess/grantee_test.go @@ -3,10 +3,10 @@ package dynamicaccess_test import ( "context" "crypto/ecdsa" - "crypto/elliptic" "crypto/rand" "testing" + "github.com/btcsuite/btcd/btcec/v2" "github.com/ethersphere/bee/v2/pkg/dynamicaccess" "github.com/ethersphere/bee/v2/pkg/file" "github.com/ethersphere/bee/v2/pkg/file/loadsave" @@ -31,9 +31,9 @@ func createLs() file.LoadSaver { } func generateKeyListFixture() ([]*ecdsa.PublicKey, error) { - key1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - key2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - key3, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + key1, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) + key2, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) + key3, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { return nil, err } @@ -195,3 +195,15 @@ func TestGranteeSave(t *testing.T) { assert.Equal(t, append(keys, keys...), val) }) } + +func TestGranteeRemoveTwo(t *testing.T) { + gl := dynamicaccess.NewGranteeList(createLs()) + keys, err := generateKeyListFixture() + if err != nil { + t.Errorf("key generation error: %v", err) + } + err = gl.Add([]*ecdsa.PublicKey{keys[0]}) + err = gl.Add([]*ecdsa.PublicKey{keys[0]}) + err = gl.Remove([]*ecdsa.PublicKey{keys[0]}) + assert.NoError(t, err) +} From 4697a2e84c782339f76a2c900885f78ba8cca5e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Ujv=C3=A1ri?= Date: Mon, 22 Apr 2024 14:44:16 +0200 Subject: [PATCH 03/19] Save grantees as pubkey list and fix remove error; CHG: act-handler logger names --- pkg/api/bytes.go | 2 +- pkg/api/bzz.go | 2 +- pkg/api/chunk.go | 2 +- pkg/api/dirs.go | 2 +- pkg/api/dynamicaccess.go | 9 ++- pkg/api/feed.go | 2 +- pkg/api/soc.go | 2 +- pkg/dynamicaccess/grantee.go | 97 ++++++++++++++++--------------- pkg/dynamicaccess/grantee_test.go | 8 +-- 9 files changed, 65 insertions(+), 61 deletions(-) diff --git a/pkg/api/bytes.go b/pkg/api/bytes.go index a84ec2936de..2afb1db99c0 100644 --- a/pkg/api/bytes.go +++ b/pkg/api/bytes.go @@ -118,7 +118,7 @@ func (s *Service) bytesUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := reference if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), logger, w, putter, reference, headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, reference, headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/bzz.go b/pkg/api/bzz.go index 6319624a17d..b49bc89baea 100644 --- a/pkg/api/bzz.go +++ b/pkg/api/bzz.go @@ -266,7 +266,7 @@ func (s *Service) fileUploadHandler( encryptedReference := manifestReference if act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), logger, w, putter, manifestReference, historyAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, manifestReference, historyAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/chunk.go b/pkg/api/chunk.go index 496f7f8d306..21daa0d0f57 100644 --- a/pkg/api/chunk.go +++ b/pkg/api/chunk.go @@ -143,7 +143,7 @@ func (s *Service) chunkUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := chunk.Address() if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), logger, w, putter, chunk.Address(), headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, chunk.Address(), headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/dirs.go b/pkg/api/dirs.go index c85c68e4edb..f187fbde01e 100644 --- a/pkg/api/dirs.go +++ b/pkg/api/dirs.go @@ -102,7 +102,7 @@ func (s *Service) dirUploadHandler( encryptedReference := reference if act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), logger, w, putter, reference, historyAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, reference, historyAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index 564c8a64815..5b2b78f6888 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -11,7 +11,6 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/ethersphere/bee/v2/pkg/crypto" "github.com/ethersphere/bee/v2/pkg/jsonhttp" - "github.com/ethersphere/bee/v2/pkg/log" storer "github.com/ethersphere/bee/v2/pkg/storer" "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/gorilla/mux" @@ -61,7 +60,7 @@ type GranteesPatch struct { func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { return func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - logger := s.logger.WithName("acthandler").Build() + logger := s.logger.WithName("act_decryption_handler").Build() paths := struct { Address swarm.Address `map:"address,resolve" validate:"required"` }{} @@ -101,12 +100,12 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { // Uploads the encrypted reference, history and kvs to the store func (s *Service) actEncryptionHandler( ctx context.Context, - logger log.Logger, w http.ResponseWriter, putter storer.PutterSession, reference swarm.Address, historyRootHash swarm.Address, ) (swarm.Address, error) { + logger := s.logger.WithName("act_encryption_handler").Build() publisherPublicKey := &s.publicKey storageReference, historyReference, encryptedReference, err := s.dac.UploadHandler(ctx, reference, publisherPublicKey, historyRootHash) if err != nil { @@ -143,7 +142,7 @@ func (s *Service) actEncryptionHandler( } func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) { - logger := s.logger.WithName("acthandler").Build() + logger := s.logger.WithName("act_list_grantees_handler").Build() paths := struct { GranteesAddress swarm.Address `map:"address,resolve" validate:"required"` }{} @@ -164,7 +163,7 @@ func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) } func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) { - logger := s.logger.WithName("acthandler").Build() + logger := s.logger.WithName("act_grant_revoke_handler").Build() if r.Body == http.NoBody { logger.Error(nil, "request has no body") diff --git a/pkg/api/feed.go b/pkg/api/feed.go index a2679547478..3d43d3d148e 100644 --- a/pkg/api/feed.go +++ b/pkg/api/feed.go @@ -249,7 +249,7 @@ func (s *Service) feedPostHandler(w http.ResponseWriter, r *http.Request) { // TODO: do we want to allow feed act upload/ download? encryptedReference := ref if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), logger, w, putter, ref, headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, ref, headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/soc.go b/pkg/api/soc.go index c2f11d6e05c..29777066b10 100644 --- a/pkg/api/soc.go +++ b/pkg/api/soc.go @@ -159,7 +159,7 @@ func (s *Service) socUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := sch.Address() if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), logger, w, putter, sch.Address(), headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, sch.Address(), headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/dynamicaccess/grantee.go b/pkg/dynamicaccess/grantee.go index 514dd2a550e..b0a1a3799cd 100644 --- a/pkg/dynamicaccess/grantee.go +++ b/pkg/dynamicaccess/grantee.go @@ -23,62 +23,28 @@ type GranteeList interface { } type GranteeListStruct struct { - grantees []byte + grantees []*ecdsa.PublicKey loadSave file.LoadSaver } var _ GranteeList = (*GranteeListStruct)(nil) func (g *GranteeListStruct) Get() []*ecdsa.PublicKey { - return g.deserialize(g.grantees) -} - -func (g *GranteeListStruct) serialize(publicKeys []*ecdsa.PublicKey) []byte { - b := make([]byte, 0, len(publicKeys)*publicKeyLen) - for _, key := range publicKeys { - b = append(b, g.serializePublicKey(key)...) - } - return b -} - -func (g *GranteeListStruct) serializePublicKey(pub *ecdsa.PublicKey) []byte { - return elliptic.Marshal(pub.Curve, pub.X, pub.Y) -} - -func (g *GranteeListStruct) deserialize(data []byte) []*ecdsa.PublicKey { - if len(data) == 0 { - return nil - } - - p := make([]*ecdsa.PublicKey, 0, len(data)/publicKeyLen) - for i := 0; i < len(data); i += publicKeyLen { - pubKey := g.deserializeBytes(data[i : i+publicKeyLen]) - if pubKey == nil { - return nil - } - p = append(p, pubKey) - } - return p -} - -func (g *GranteeListStruct) deserializeBytes(data []byte) *ecdsa.PublicKey { - curve := btcec.S256() - x, y := elliptic.Unmarshal(curve, data) - return &ecdsa.PublicKey{Curve: curve, X: x, Y: y} + return g.grantees } func (g *GranteeListStruct) Add(addList []*ecdsa.PublicKey) error { if len(addList) == 0 { return fmt.Errorf("no public key provided") } + g.grantees = append(g.grantees, addList...) - data := g.serialize(addList) - g.grantees = append(g.grantees, data...) return nil } func (g *GranteeListStruct) Save(ctx context.Context) (swarm.Address, error) { - refBytes, err := g.loadSave.Save(ctx, g.grantees) + data := serialize(g.grantees) + refBytes, err := g.loadSave.Save(ctx, data) if err != nil { return swarm.ZeroAddress, fmt.Errorf("grantee save error: %w", err) } @@ -90,26 +56,28 @@ func (g *GranteeListStruct) Remove(keysToRemove []*ecdsa.PublicKey) error { if len(keysToRemove) == 0 { return fmt.Errorf("nothing to remove") } - grantees := g.deserialize(g.grantees) - if grantees == nil { + + if len(g.grantees) == 0 { return fmt.Errorf("no grantee found") } + grantees := g.grantees for _, remove := range keysToRemove { - for i, grantee := range grantees { - if grantee.Equal(remove) { + for i := 0; i < len(grantees); i++ { + if grantees[i].Equal(remove) { grantees[i] = grantees[len(grantees)-1] grantees = grantees[:len(grantees)-1] } } } - g.grantees = g.serialize(grantees) + g.grantees = grantees + return nil } func NewGranteeList(ls file.LoadSaver) GranteeList { return &GranteeListStruct{ - grantees: []byte{}, + grantees: []*ecdsa.PublicKey{}, loadSave: ls, } } @@ -119,9 +87,46 @@ func NewGranteeListReference(ls file.LoadSaver, reference swarm.Address) Grantee if err != nil { return nil } + grantees := deserialize(data) return &GranteeListStruct{ - grantees: data, + grantees: grantees, loadSave: ls, } } + +func serialize(publicKeys []*ecdsa.PublicKey) []byte { + b := make([]byte, 0, len(publicKeys)*publicKeyLen) + for _, key := range publicKeys { + b = append(b, serializePublicKey(key)...) + } + return b +} + +func serializePublicKey(pub *ecdsa.PublicKey) []byte { + return elliptic.Marshal(pub.Curve, pub.X, pub.Y) +} + +func deserialize(data []byte) []*ecdsa.PublicKey { + if len(data) == 0 { + return []*ecdsa.PublicKey{} + } + + p := make([]*ecdsa.PublicKey, 0, len(data)/publicKeyLen) + for i := 0; i < len(data); i += publicKeyLen { + pubKey := deserializeBytes(data[i : i+publicKeyLen]) + if pubKey == nil { + return []*ecdsa.PublicKey{} + } + p = append(p, pubKey) + } + return p +} + +func deserializeBytes(data []byte) *ecdsa.PublicKey { + key, err := btcec.ParsePubKey(data) + if err != nil { + return nil + } + return key.ToECDSA() +} diff --git a/pkg/dynamicaccess/grantee_test.go b/pkg/dynamicaccess/grantee_test.go index 573171ba9d9..8782a96bc45 100644 --- a/pkg/dynamicaccess/grantee_test.go +++ b/pkg/dynamicaccess/grantee_test.go @@ -49,7 +49,7 @@ func TestGranteeAddGet(t *testing.T) { t.Run("Get empty grantee list should return error", func(t *testing.T) { val := gl.Get() - assert.Nil(t, val) + assert.Empty(t, val) }) t.Run("Get should return value equal to put value", func(t *testing.T) { @@ -128,19 +128,19 @@ func TestGranteeRemove(t *testing.T) { err := gl.Remove(removeList2) assert.NoError(t, err) retVal := gl.Get() - assert.Nil(t, retVal) + assert.Empty(t, retVal) }) t.Run("Remove from empty grantee list should return error", func(t *testing.T) { err := gl.Remove(removeList1) assert.Error(t, err) retVal := gl.Get() - assert.Nil(t, retVal) + assert.Empty(t, retVal) }) t.Run("Remove empty remove list should return error", func(t *testing.T) { err := gl.Remove(nil) assert.Error(t, err) retVal := gl.Get() - assert.Nil(t, retVal) + assert.Empty(t, retVal) }) } From 8df33ecf32cb27609e8cfdaa6dfcc480aa813be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Ujv=C3=A1ri?= Date: Tue, 23 Apr 2024 17:56:24 +0200 Subject: [PATCH 04/19] Refactor: pass getter, putter to controller functions --- pkg/api/bytes.go | 2 +- pkg/api/bzz.go | 2 +- pkg/api/chunk.go | 2 +- pkg/api/dirs.go | 2 +- pkg/api/dynamicaccess.go | 86 +++++++++++++++++++++++----- pkg/api/feed.go | 2 +- pkg/api/soc.go | 2 +- pkg/dynamicaccess/controller.go | 67 +++++++++++++++------- pkg/dynamicaccess/controller_test.go | 30 +++++----- pkg/dynamicaccess/mock/service.go | 8 +-- pkg/node/devnode.go | 2 +- pkg/node/node.go | 2 +- 12 files changed, 147 insertions(+), 60 deletions(-) diff --git a/pkg/api/bytes.go b/pkg/api/bytes.go index 2afb1db99c0..449eabac0e1 100644 --- a/pkg/api/bytes.go +++ b/pkg/api/bytes.go @@ -118,7 +118,7 @@ func (s *Service) bytesUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := reference if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, reference, headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, reference, headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/bzz.go b/pkg/api/bzz.go index b49bc89baea..75a56be94a3 100644 --- a/pkg/api/bzz.go +++ b/pkg/api/bzz.go @@ -266,7 +266,7 @@ func (s *Service) fileUploadHandler( encryptedReference := manifestReference if act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, manifestReference, historyAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, manifestReference, historyAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/chunk.go b/pkg/api/chunk.go index 21daa0d0f57..7d98efcb30a 100644 --- a/pkg/api/chunk.go +++ b/pkg/api/chunk.go @@ -143,7 +143,7 @@ func (s *Service) chunkUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := chunk.Address() if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, chunk.Address(), headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, chunk.Address(), headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/dirs.go b/pkg/api/dirs.go index f187fbde01e..66f20f1a137 100644 --- a/pkg/api/dirs.go +++ b/pkg/api/dirs.go @@ -102,7 +102,7 @@ func (s *Service) dirUploadHandler( encryptedReference := reference if act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, reference, historyAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, reference, historyAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index 5b2b78f6888..2e7c28e7b03 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -5,12 +5,15 @@ import ( "crypto/ecdsa" "encoding/hex" "encoding/json" + "errors" "io" "net/http" "github.com/btcsuite/btcd/btcec/v2" "github.com/ethersphere/bee/v2/pkg/crypto" "github.com/ethersphere/bee/v2/pkg/jsonhttp" + "github.com/ethersphere/bee/v2/pkg/postage" + storage "github.com/ethersphere/bee/v2/pkg/storage" storer "github.com/ethersphere/bee/v2/pkg/storer" "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/gorilla/mux" @@ -85,7 +88,7 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { return } ctx := r.Context() - reference, err := s.dac.DownloadHandler(ctx, paths.Address, headers.Publisher, *headers.HistoryAddress, *headers.Timestamp) + reference, err := s.dac.DownloadHandler(ctx, s.storer.Download(true), paths.Address, headers.Publisher, *headers.HistoryAddress, *headers.Timestamp) if err != nil { jsonhttp.InternalServerError(w, errActDownload) return @@ -101,13 +104,14 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { func (s *Service) actEncryptionHandler( ctx context.Context, w http.ResponseWriter, + getter storage.Getter, putter storer.PutterSession, reference swarm.Address, historyRootHash swarm.Address, ) (swarm.Address, error) { logger := s.logger.WithName("act_encryption_handler").Build() publisherPublicKey := &s.publicKey - storageReference, historyReference, encryptedReference, err := s.dac.UploadHandler(ctx, reference, publisherPublicKey, historyRootHash) + storageReference, historyReference, encryptedReference, err := s.dac.UploadHandler(ctx, getter, putter, reference, publisherPublicKey, historyRootHash) if err != nil { logger.Debug("act failed to encrypt reference", "error", err) logger.Error(nil, "act failed to encrypt reference") @@ -137,7 +141,6 @@ func (s *Service) actEncryptionHandler( } w.Header().Set(SwarmActHistoryAddressHeader, historyReference.String()) - return encryptedReference, nil } @@ -150,7 +153,7 @@ func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) response("invalid path params", logger, w) return } - grantees, err := s.dac.GetGrantees(r.Context(), paths.GranteesAddress) + grantees, err := s.dac.GetGrantees(r.Context(), s.storer.Download(true), paths.GranteesAddress) if err != nil { jsonhttp.NotFound(w, "grantee list not found") return @@ -225,15 +228,32 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) tag, _ := s.getOrCreateSessionID(0) ctx := r.Context() - putter, _ := s.newStamperPutter(ctx, putterOptions{ + putter, err := s.newStamperPutter(ctx, putterOptions{ BatchID: headers.BatchID, TagID: tag, Pin: false, - Deferred: true, + Deferred: false, }) + if err != nil { + logger.Debug("putter failed", "error", err) + logger.Error(nil, "putter failed") + switch { + case errors.Is(err, errBatchUnusable) || errors.Is(err, postage.ErrNotUsable): + jsonhttp.UnprocessableEntity(w, "batch not usable yet or does not exist") + case errors.Is(err, postage.ErrNotFound): + jsonhttp.NotFound(w, "batch with id not found") + case errors.Is(err, errInvalidPostageBatch): + jsonhttp.BadRequest(w, "invalid batch id") + case errors.Is(err, errUnsupportedDevNodeOperation): + jsonhttp.BadRequest(w, errUnsupportedDevNodeOperation) + default: + jsonhttp.BadRequest(w, nil) + } + return + } granteeref := paths.GranteesAddress - granteeref, historyref, _ := s.dac.HandleGrantees(ctx, granteeref, *headers.HistoryAddress, &s.publicKey, convertToPointerSlice(grantees.Addlist), convertToPointerSlice(grantees.Revokelist)) + granteeref, historyref, _ := s.dac.HandleGrantees(ctx, s.storer.Download(true), putter, granteeref, *headers.HistoryAddress, &s.publicKey, convertToPointerSlice(grantees.Addlist), convertToPointerSlice(grantees.Revokelist)) putter.Done(granteeref) putter.Done(historyref) jsonhttp.OK(w, GranteesPatchResponse{ @@ -290,16 +310,55 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques tag, _ := s.getOrCreateSessionID(0) ctx := r.Context() - putter, _ := s.newStamperPutter(ctx, putterOptions{ + // TODO: pin and deferred headers + putter, err := s.newStamperPutter(ctx, putterOptions{ BatchID: headers.BatchID, TagID: tag, Pin: false, - Deferred: true, + Deferred: false, }) + if err != nil { + logger.Debug("putter failed", "error", err) + logger.Error(nil, "putter failed") + switch { + case errors.Is(err, errBatchUnusable) || errors.Is(err, postage.ErrNotUsable): + jsonhttp.UnprocessableEntity(w, "batch not usable yet or does not exist") + case errors.Is(err, postage.ErrNotFound): + jsonhttp.NotFound(w, "batch with id not found") + case errors.Is(err, errInvalidPostageBatch): + jsonhttp.BadRequest(w, "invalid batch id") + case errors.Is(err, errUnsupportedDevNodeOperation): + jsonhttp.BadRequest(w, errUnsupportedDevNodeOperation) + default: + jsonhttp.BadRequest(w, nil) + } + return + } + + granteeref, historyref, err := s.dac.HandleGrantees(ctx, s.storer.Download(true), putter, swarm.ZeroAddress, swarm.ZeroAddress, &s.publicKey, convertToPointerSlice(list), nil) + if err != nil { + logger.Info("HandleGrantees error", "error", err) + logger.Error(nil, "HandleGrantees error") + jsonhttp.InternalServerError(w, "HandleGrantees error") + return + } + + err = putter.Done(granteeref) + if err != nil { + logger.Info("putter granteeref error", "error", err) + logger.Error(nil, "putter granteeref error") + jsonhttp.InternalServerError(w, "putter granteeref error") + return + } + + err = putter.Done(historyref) + if err != nil { + logger.Info("putter historyref error", "error", err) + logger.Error(nil, "putter historyref error") + jsonhttp.InternalServerError(w, "putter historyref error") + return + } - granteeref, historyref, _ := s.dac.HandleGrantees(ctx, swarm.ZeroAddress, swarm.ZeroAddress, &s.publicKey, convertToPointerSlice(list), nil) - putter.Done(granteeref) - putter.Done(historyref) jsonhttp.Created(w, GranteesPostResponse{ Reference: granteeref, HistoryReference: historyref, @@ -309,7 +368,8 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques func convertToPointerSlice(slice []ecdsa.PublicKey) []*ecdsa.PublicKey { pointerSlice := make([]*ecdsa.PublicKey, len(slice)) for i, key := range slice { - pointerSlice[i] = &key + tempKey := key + pointerSlice[i] = &tempKey } return pointerSlice } diff --git a/pkg/api/feed.go b/pkg/api/feed.go index 3d43d3d148e..6f6b0a5c955 100644 --- a/pkg/api/feed.go +++ b/pkg/api/feed.go @@ -249,7 +249,7 @@ func (s *Service) feedPostHandler(w http.ResponseWriter, r *http.Request) { // TODO: do we want to allow feed act upload/ download? encryptedReference := ref if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, ref, headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, ref, headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/soc.go b/pkg/api/soc.go index 29777066b10..f61463584ac 100644 --- a/pkg/api/soc.go +++ b/pkg/api/soc.go @@ -159,7 +159,7 @@ func (s *Service) socUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := sch.Address() if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, sch.Address(), headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, sch.Address(), headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index 382b8fc463d..003d897a4ca 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -18,37 +18,36 @@ import ( const granteeListEncrypt = true type GranteeManager interface { - HandleGrantees(ctx context.Context, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, error) - GetGrantees(ctx context.Context, rootHash swarm.Address) ([]*ecdsa.PublicKey, error) + HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, error) + GetGrantees(ctx context.Context, getter storage.Getter, rootHash swarm.Address) ([]*ecdsa.PublicKey, error) } // TODO: add granteeList ref to history metadata to solve inconsistency type Controller interface { GranteeManager // DownloadHandler decrypts the encryptedRef using the lookupkey based on the history and timestamp. - DownloadHandler(ctx context.Context, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) + DownloadHandler(ctx context.Context, getter storage.Getter, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) // TODO: history encryption // UploadHandler encrypts the reference and stores it in the history as the latest update. - UploadHandler(ctx context.Context, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) + UploadHandler(ctx context.Context, getter storage.Getter, putter storage.Putter, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) io.Closer } type controller struct { accessLogic ActLogic - getter storage.Getter - putter storage.Putter } var _ Controller = (*controller)(nil) func (c *controller) DownloadHandler( ctx context.Context, + getter storage.Getter, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64, ) (swarm.Address, error) { - ls := loadsave.New(c.getter, c.putter, requestPipelineFactory(ctx, c.putter, false, redundancy.NONE)) + ls := loadsave.NewReadonly(getter) history, err := NewHistoryReference(ls, historyRootHash) if err != nil { return swarm.ZeroAddress, err @@ -68,11 +67,13 @@ func (c *controller) DownloadHandler( func (c *controller) UploadHandler( ctx context.Context, + getter storage.Getter, + putter storage.Putter, refrefence swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, ) (swarm.Address, swarm.Address, swarm.Address, error) { - ls := loadsave.New(c.getter, c.putter, requestPipelineFactory(ctx, c.putter, false, redundancy.NONE)) + ls := loadsave.New(getter, putter, requestPipelineFactory(ctx, putter, false, redundancy.NONE)) historyRef := historyRootHash var ( storage kvs.KeyValueStore @@ -126,21 +127,28 @@ func (c *controller) UploadHandler( return actRef, historyRef, encryptedRef, err } -func NewController(ctx context.Context, accessLogic ActLogic, getter storage.Getter, putter storage.Putter) Controller { +func NewController(ctx context.Context, accessLogic ActLogic) Controller { return &controller{ accessLogic: accessLogic, - getter: getter, - putter: putter, } } -func (c *controller) HandleGrantees(ctx context.Context, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, error) { +func (c *controller) HandleGrantees( + ctx context.Context, + getter storage.Getter, + putter storage.Putter, + granteeref swarm.Address, + historyref swarm.Address, + publisher *ecdsa.PublicKey, + addList []*ecdsa.PublicKey, + removeList []*ecdsa.PublicKey, +) (swarm.Address, swarm.Address, error) { var ( err error h History act kvs.KeyValueStore - ls = loadsave.New(c.getter, c.putter, requestPipelineFactory(ctx, c.putter, false, redundancy.NONE)) - gls = loadsave.New(c.getter, c.putter, requestPipelineFactory(ctx, c.putter, granteeListEncrypt, redundancy.NONE)) + ls = loadsave.New(getter, putter, requestPipelineFactory(ctx, putter, false, redundancy.NONE)) + gls = loadsave.New(getter, putter, requestPipelineFactory(ctx, putter, granteeListEncrypt, redundancy.NONE)) ) if !historyref.IsZero() { h, err = NewHistoryReference(ls, historyref) @@ -174,20 +182,34 @@ func (c *controller) HandleGrantees(ctx context.Context, granteeref swarm.Addres } else { gl = NewGranteeListReference(gls, granteeref) } - gl.Add(addList) - gl.Remove(removeList) + err = gl.Add(addList) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err + } + if len(removeList) != 0 { + err = gl.Remove(removeList) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err + } + } var granteesToAdd []*ecdsa.PublicKey // generate new access key and new act if len(removeList) != 0 || granteeref.IsZero() { - c.accessLogic.AddPublisher(ctx, act, publisher) + err = c.accessLogic.AddPublisher(ctx, act, publisher) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err + } granteesToAdd = gl.Get() } else { granteesToAdd = addList } for _, grantee := range granteesToAdd { - c.accessLogic.AddGrantee(ctx, act, publisher, grantee, nil) + err := c.accessLogic.AddGrantee(ctx, act, publisher, grantee, nil) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err + } } actref, err := act.Save(ctx) @@ -195,7 +217,10 @@ func (c *controller) HandleGrantees(ctx context.Context, granteeref swarm.Addres return swarm.ZeroAddress, swarm.ZeroAddress, err } - h.Add(ctx, actref, nil, nil) + err = h.Add(ctx, actref, nil, nil) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, err + } href, err := h.Store(ctx) if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, err @@ -208,8 +233,8 @@ func (c *controller) HandleGrantees(ctx context.Context, granteeref swarm.Addres return glref, href, nil } -func (c *controller) GetGrantees(ctx context.Context, granteeRef swarm.Address) ([]*ecdsa.PublicKey, error) { - ls := loadsave.New(c.getter, c.putter, requestPipelineFactory(ctx, c.putter, granteeListEncrypt, redundancy.NONE)) +func (c *controller) GetGrantees(ctx context.Context, getter storage.Getter, granteeRef swarm.Address) ([]*ecdsa.PublicKey, error) { + ls := loadsave.NewReadonly(getter) gl := NewGranteeListReference(ls, granteeRef) return gl.Get(), nil } diff --git a/pkg/dynamicaccess/controller_test.go b/pkg/dynamicaccess/controller_test.go index 55131d3793b..3d5b4a5b850 100644 --- a/pkg/dynamicaccess/controller_test.go +++ b/pkg/dynamicaccess/controller_test.go @@ -47,9 +47,9 @@ func TestController_NewUpload(t *testing.T) { publisher := getPrivKey(0) diffieHellman := dynamicaccess.NewDefaultSession(publisher) al := dynamicaccess.NewLogic(diffieHellman) - c := dynamicaccess.NewController(ctx, al, mockStorer.ChunkStore(), mockStorer.Cache()) + c := dynamicaccess.NewController(ctx, al) ref := swarm.RandAddress(t) - _, hRef, encRef, err := c.UploadHandler(ctx, ref, &publisher.PublicKey, swarm.ZeroAddress) + _, hRef, encRef, err := c.UploadHandler(ctx, mockStorer.ChunkStore(), mockStorer.Cache(), ref, &publisher.PublicKey, swarm.ZeroAddress) ls := createLs() h, err := dynamicaccess.NewHistoryReference(ls, hRef) @@ -68,7 +68,7 @@ func TestController_PublisherDownload(t *testing.T) { publisher := getPrivKey(0) diffieHellman := dynamicaccess.NewDefaultSession(publisher) al := dynamicaccess.NewLogic(diffieHellman) - c := dynamicaccess.NewController(ctx, al, mockStorer.ChunkStore(), mockStorer.Cache()) + c := dynamicaccess.NewController(ctx, al) ls := createLs() ref := swarm.RandAddress(t) href, err := getHistoryFixture(ctx, ls, al, &publisher.PublicKey) @@ -79,7 +79,7 @@ func TestController_PublisherDownload(t *testing.T) { encRef, err := al.EncryptRef(ctx, act, &publisher.PublicKey, ref) assert.NoError(t, err) - dref, err := c.DownloadHandler(ctx, encRef, &publisher.PublicKey, href, time.Now().Unix()) + dref, err := c.DownloadHandler(ctx, mockStorer.ChunkStore(), encRef, &publisher.PublicKey, href, time.Now().Unix()) assert.NoError(t, err) assert.Equal(t, ref, dref) } @@ -94,7 +94,7 @@ func TestController_GranteeDownload(t *testing.T) { diffieHellman := dynamicaccess.NewDefaultSession(grantee) al := dynamicaccess.NewLogic(diffieHellman) ls := createLs() - c := dynamicaccess.NewController(ctx, al, mockStorer.ChunkStore(), mockStorer.Cache()) + c := dynamicaccess.NewController(ctx, al) ref := swarm.RandAddress(t) href, err := getHistoryFixture(ctx, ls, publisherAL, &publisher.PublicKey) h, err := dynamicaccess.NewHistoryReference(ls, href) @@ -105,7 +105,7 @@ func TestController_GranteeDownload(t *testing.T) { encRef, err := publisherAL.EncryptRef(ctx, act, &publisher.PublicKey, ref) assert.NoError(t, err) - dref, err := c.DownloadHandler(ctx, encRef, &publisher.PublicKey, href, ts) + dref, err := c.DownloadHandler(ctx, mockStorer.ChunkStore(), encRef, &publisher.PublicKey, href, ts) assert.NoError(t, err) assert.Equal(t, ref, dref) } @@ -116,7 +116,9 @@ func TestController_HandleGrantees(t *testing.T) { diffieHellman := dynamicaccess.NewDefaultSession(publisher) al := dynamicaccess.NewLogic(diffieHellman) ls := createLs() - c := dynamicaccess.NewController(ctx, al, mockStorer.ChunkStore(), mockStorer.Cache()) + getter := mockStorer.ChunkStore() + putter := mockStorer.Cache() + c := dynamicaccess.NewController(ctx, al) href, _ := getHistoryFixture(ctx, ls, al, &publisher.PublicKey) grantee1 := getPrivKey(0) @@ -124,7 +126,7 @@ func TestController_HandleGrantees(t *testing.T) { t.Run("add to new list", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, _, err := c.HandleGrantees(ctx, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + granteeRef, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) @@ -133,7 +135,7 @@ func TestController_HandleGrantees(t *testing.T) { }) t.Run("add to existing list", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, _, err := c.HandleGrantees(ctx, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) @@ -141,7 +143,7 @@ func TestController_HandleGrantees(t *testing.T) { assert.Len(t, gl.Get(), 1) addList = []*ecdsa.PublicKey{&getPrivKey(0).PublicKey} - granteeRef, _, err = c.HandleGrantees(ctx, granteeRef, href, &publisher.PublicKey, addList, nil) + granteeRef, _, err = c.HandleGrantees(ctx, getter, putter, granteeRef, href, &publisher.PublicKey, addList, nil) gl = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 2) @@ -153,7 +155,7 @@ func TestController_HandleGrantees(t *testing.T) { gl.Add([]*ecdsa.PublicKey{&publisher.PublicKey, &grantee1.PublicKey}) granteeRef, err := gl.Save(ctx) - granteeRef, _, err = c.HandleGrantees(ctx, granteeRef, href, &publisher.PublicKey, addList, revokeList) + granteeRef, _, err = c.HandleGrantees(ctx, getter, putter, granteeRef, href, &publisher.PublicKey, addList, revokeList) gl = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) @@ -162,8 +164,8 @@ func TestController_HandleGrantees(t *testing.T) { t.Run("add twice", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey, &grantee.PublicKey} - granteeRef, _, err := c.HandleGrantees(ctx, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) - granteeRef, _, err = c.HandleGrantees(ctx, granteeRef, href, &publisher.PublicKey, addList, nil) + granteeRef, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, _, err = c.HandleGrantees(ctx, getter, putter, granteeRef, href, &publisher.PublicKey, addList, nil) gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) @@ -171,7 +173,7 @@ func TestController_HandleGrantees(t *testing.T) { }) t.Run("revoke non-existing", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, _, err := c.HandleGrantees(ctx, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) diff --git a/pkg/dynamicaccess/mock/service.go b/pkg/dynamicaccess/mock/service.go index 485de90f6a9..15f26ac6f00 100644 --- a/pkg/dynamicaccess/mock/service.go +++ b/pkg/dynamicaccess/mock/service.go @@ -78,7 +78,7 @@ func WithPublisher(ref string) Option { }) } -func (m *mockDacService) DownloadHandler(ctx context.Context, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) { +func (m *mockDacService) DownloadHandler(ctx context.Context, getter storage.Getter, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) { if m.acceptAll { return swarm.ParseHexAddress("36e6c1bbdfee6ac21485d5f970479fd1df458d36df9ef4e8179708ed46da557f") } @@ -101,7 +101,7 @@ func (m *mockDacService) DownloadHandler(ctx context.Context, encryptedRef swarm return m.refMap[encryptedRef.String()], nil } -func (m *mockDacService) UploadHandler(ctx context.Context, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) { +func (m *mockDacService) UploadHandler(ctx context.Context, getter storage.Getter, putter storage.Putter, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) { historyRef, _ := swarm.ParseHexAddress("67bdf80a9bbea8eca9c8480e43fdceb485d2d74d5708e45144b8c4adacd13d9c") kvsRef, _ := swarm.ParseHexAddress("3339613565613837623134316665343461613630396333333237656364383934") if m.acceptAll { @@ -141,12 +141,12 @@ func (m *mockDacService) Close() error { return nil } -func (m *mockDacService) HandleGrantees(ctx context.Context, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, error) { +func (m *mockDacService) HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, error) { historyRef, _ := swarm.ParseHexAddress("67bdf80a9bbea8eca9c8480e43fdceb485d2d74d5708e45144b8c4adacd13d9c") glRef, _ := swarm.ParseHexAddress("3339613565613837623134316665343461613630396333333237656364383934") return glRef, historyRef, nil } -func (m *mockDacService) GetGrantees(ctx context.Context, granteeref swarm.Address) ([]*ecdsa.PublicKey, error) { +func (m *mockDacService) GetGrantees(ctx context.Context, getter storage.Getter, granteeref swarm.Address) ([]*ecdsa.PublicKey, error) { keys := []string{ "a786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfa", "b786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfb", diff --git a/pkg/node/devnode.go b/pkg/node/devnode.go index 4e96a301769..b7ac3dfee56 100644 --- a/pkg/node/devnode.go +++ b/pkg/node/devnode.go @@ -238,7 +238,7 @@ func NewDevBee(logger log.Logger, o *DevOptions) (b *DevBee, err error) { session := dynamicaccess.NewDefaultSession(mockKey) actLogic := dynamicaccess.NewLogic(session) - dac := dynamicaccess.NewController(context.Background(), actLogic, localStore.ChunkStore(), localStore.Cache()) + dac := dynamicaccess.NewController(context.Background(), actLogic) b.dacCloser = dac pssService := pss.New(mockKey, logger) diff --git a/pkg/node/node.go b/pkg/node/node.go index f16f2579e85..b48e97ddafc 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -776,7 +776,7 @@ func NewBee( evictFn = func(id []byte) error { return localStore.EvictBatch(context.Background(), id) } actLogic := dynamicaccess.NewLogic(session) - dac := dynamicaccess.NewController(ctx, actLogic, localStore.ChunkStore(), localStore.Cache()) + dac := dynamicaccess.NewController(ctx, actLogic) b.dacCloser = dac var ( From 5f219fe49452984cd621cedc63c1c9864e1d00db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Ujv=C3=A1ri?= Date: Tue, 23 Apr 2024 18:29:03 +0200 Subject: [PATCH 05/19] Refactor: error handling in dynamicaccess; Read cache header only for download handlers --- pkg/api/bytes.go | 2 +- pkg/api/bzz.go | 2 +- pkg/api/chunk.go | 2 +- pkg/api/dirs.go | 2 +- pkg/api/dynamicaccess.go | 134 +++++++++++++++++++++++++++++++-------- pkg/api/feed.go | 2 +- pkg/api/soc.go | 2 +- 7 files changed, 115 insertions(+), 31 deletions(-) diff --git a/pkg/api/bytes.go b/pkg/api/bytes.go index 449eabac0e1..a2d65cae1ba 100644 --- a/pkg/api/bytes.go +++ b/pkg/api/bytes.go @@ -118,7 +118,7 @@ func (s *Service) bytesUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := reference if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, reference, headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, reference, headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/bzz.go b/pkg/api/bzz.go index 75a56be94a3..7f322be0720 100644 --- a/pkg/api/bzz.go +++ b/pkg/api/bzz.go @@ -266,7 +266,7 @@ func (s *Service) fileUploadHandler( encryptedReference := manifestReference if act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, manifestReference, historyAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, manifestReference, historyAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/chunk.go b/pkg/api/chunk.go index 7d98efcb30a..9c462b1a558 100644 --- a/pkg/api/chunk.go +++ b/pkg/api/chunk.go @@ -143,7 +143,7 @@ func (s *Service) chunkUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := chunk.Address() if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, chunk.Address(), headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, chunk.Address(), headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/dirs.go b/pkg/api/dirs.go index 66f20f1a137..e871eee2e8b 100644 --- a/pkg/api/dirs.go +++ b/pkg/api/dirs.go @@ -102,7 +102,7 @@ func (s *Service) dirUploadHandler( encryptedReference := reference if act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, reference, historyAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, reference, historyAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index 2e7c28e7b03..60d3a1c5fab 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -76,6 +76,7 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { Timestamp *int64 `map:"Swarm-Act-Timestamp"` Publisher *ecdsa.PublicKey `map:"Swarm-Act-Publisher"` HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address"` + Cache *bool `map:"Swarm-Cache"` }{} if response := s.mapStructure(r.Header, &headers); response != nil { response("invalid header params", logger, w) @@ -87,8 +88,13 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { h.ServeHTTP(w, r) return } + + cache := true + if headers.Cache != nil { + cache = *headers.Cache + } ctx := r.Context() - reference, err := s.dac.DownloadHandler(ctx, s.storer.Download(true), paths.Address, headers.Publisher, *headers.HistoryAddress, *headers.Timestamp) + reference, err := s.dac.DownloadHandler(ctx, s.storer.Download(cache), paths.Address, headers.Publisher, *headers.HistoryAddress, *headers.Timestamp) if err != nil { jsonhttp.InternalServerError(w, errActDownload) return @@ -153,7 +159,19 @@ func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) response("invalid path params", logger, w) return } - grantees, err := s.dac.GetGrantees(r.Context(), s.storer.Download(true), paths.GranteesAddress) + + headers := struct { + Cache *bool `map:"Swarm-Cache"` + }{} + if response := s.mapStructure(r.Header, &headers); response != nil { + response("invalid header params", logger, w) + return + } + cache := true + if headers.Cache != nil { + cache = *headers.Cache + } + grantees, err := s.dac.GetGrantees(r.Context(), s.storer.Download(cache), paths.GranteesAddress) if err != nil { jsonhttp.NotFound(w, "grantee list not found") return @@ -214,18 +232,36 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) } grantees := GranteesPatch{} - for _, g := range gpr.Addlist { - h, _ := hex.DecodeString(g) - k, _ := btcec.ParsePubKey(h) - grantees.Addlist = append(grantees.Addlist, *k.ToECDSA()) + paresAddlist, err := parseKeys(gpr.Addlist) + if err != nil { + logger.Debug("add list key parse failed", "error", err) + logger.Error(nil, "add list key parse failed") + jsonhttp.InternalServerError(w, "error add list key parsing") + return } - for _, g := range gpr.Revokelist { - h, _ := hex.DecodeString(g) - k, _ := btcec.ParsePubKey(h) - grantees.Revokelist = append(grantees.Revokelist, *k.ToECDSA()) + grantees.Addlist = append(grantees.Addlist, paresAddlist...) + + paresRevokelist, err := parseKeys(gpr.Revokelist) + if err != nil { + logger.Debug("revoke list key parse failed", "error", err) + logger.Error(nil, "revoke list key parse failed") + jsonhttp.InternalServerError(w, "error revoke list key parsing") + return } + grantees.Revokelist = append(grantees.Revokelist, paresRevokelist...) - tag, _ := s.getOrCreateSessionID(0) + tag, err := s.getOrCreateSessionID(0) + if err != nil { + logger.Debug("get or create tag failed", "error", err) + logger.Error(nil, "get or create tag failed") + switch { + case errors.Is(err, storage.ErrNotFound): + jsonhttp.NotFound(w, "tag not found") + default: + jsonhttp.InternalServerError(w, "cannot get or create tag") + } + return + } ctx := r.Context() putter, err := s.newStamperPutter(ctx, putterOptions{ @@ -253,9 +289,29 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) } granteeref := paths.GranteesAddress - granteeref, historyref, _ := s.dac.HandleGrantees(ctx, s.storer.Download(true), putter, granteeref, *headers.HistoryAddress, &s.publicKey, convertToPointerSlice(grantees.Addlist), convertToPointerSlice(grantees.Revokelist)) - putter.Done(granteeref) - putter.Done(historyref) + granteeref, historyref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, granteeref, *headers.HistoryAddress, &s.publicKey, convertToPointerSlice(grantees.Addlist), convertToPointerSlice(grantees.Revokelist)) + if err != nil { + logger.Debug("failed to update grantee list", "error", err) + logger.Error(nil, "failed to update grantee list") + jsonhttp.InternalServerError(w, "failed to update grantee list") + return + } + + err = putter.Done(granteeref) + if err != nil { + logger.Debug("done split grantees failed", "error", err) + logger.Error(nil, "done split grantees failed") + jsonhttp.InternalServerError(w, "done split grantees failed") + return + } + + err = putter.Done(historyref) + if err != nil { + logger.Debug("done split history failed", "error", err) + logger.Error(nil, "done split history failed") + jsonhttp.InternalServerError(w, "done split history failed") + return + } jsonhttp.OK(w, GranteesPatchResponse{ Reference: granteeref, HistoryReference: historyref, @@ -307,7 +363,18 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques k, _ := btcec.ParsePubKey(h) list = append(list, *k.ToECDSA()) } - tag, _ := s.getOrCreateSessionID(0) + tag, err := s.getOrCreateSessionID(0) + if err != nil { + logger.Debug("get or create tag failed", "error", err) + logger.Error(nil, "get or create tag failed") + switch { + case errors.Is(err, storage.ErrNotFound): + jsonhttp.NotFound(w, "tag not found") + default: + jsonhttp.InternalServerError(w, "cannot get or create tag") + } + return + } ctx := r.Context() // TODO: pin and deferred headers @@ -335,27 +402,27 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques return } - granteeref, historyref, err := s.dac.HandleGrantees(ctx, s.storer.Download(true), putter, swarm.ZeroAddress, swarm.ZeroAddress, &s.publicKey, convertToPointerSlice(list), nil) + granteeref, historyref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, swarm.ZeroAddress, swarm.ZeroAddress, &s.publicKey, convertToPointerSlice(list), nil) if err != nil { - logger.Info("HandleGrantees error", "error", err) - logger.Error(nil, "HandleGrantees error") - jsonhttp.InternalServerError(w, "HandleGrantees error") + logger.Debug("failed to update grantee list", "error", err) + logger.Error(nil, "failed to update grantee list") + jsonhttp.InternalServerError(w, "failed to update grantee list") return } err = putter.Done(granteeref) if err != nil { - logger.Info("putter granteeref error", "error", err) - logger.Error(nil, "putter granteeref error") - jsonhttp.InternalServerError(w, "putter granteeref error") + logger.Debug("done split grantees failed", "error", err) + logger.Error(nil, "done split grantees failed") + jsonhttp.InternalServerError(w, "done split grantees failed") return } err = putter.Done(historyref) if err != nil { - logger.Info("putter historyref error", "error", err) - logger.Error(nil, "putter historyref error") - jsonhttp.InternalServerError(w, "putter historyref error") + logger.Debug("done split history failed", "error", err) + logger.Error(nil, "done split history failed") + jsonhttp.InternalServerError(w, "done split history failed") return } @@ -373,3 +440,20 @@ func convertToPointerSlice(slice []ecdsa.PublicKey) []*ecdsa.PublicKey { } return pointerSlice } + +func parseKeys(list []string) ([]ecdsa.PublicKey, error) { + parsedList := make([]ecdsa.PublicKey, len(list)) + for _, g := range list { + h, err := hex.DecodeString(g) + if err != nil { + return []ecdsa.PublicKey{}, err + } + k, err := btcec.ParsePubKey(h) + if err != nil { + return []ecdsa.PublicKey{}, err + } + parsedList = append(parsedList, *k.ToECDSA()) + } + + return parsedList, nil +} diff --git a/pkg/api/feed.go b/pkg/api/feed.go index 6f6b0a5c955..3e4b8d5c10e 100644 --- a/pkg/api/feed.go +++ b/pkg/api/feed.go @@ -249,7 +249,7 @@ func (s *Service) feedPostHandler(w http.ResponseWriter, r *http.Request) { // TODO: do we want to allow feed act upload/ download? encryptedReference := ref if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, ref, headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, ref, headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/soc.go b/pkg/api/soc.go index f61463584ac..cf37432ed1f 100644 --- a/pkg/api/soc.go +++ b/pkg/api/soc.go @@ -159,7 +159,7 @@ func (s *Service) socUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := sch.Address() if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.Download(true), putter, sch.Address(), headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, sch.Address(), headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return From 17b09e4b67245158b5f8996e59be4a1853c51350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Ujv=C3=A1ri?= Date: Fri, 26 Apr 2024 13:28:31 +0200 Subject: [PATCH 06/19] CHG: grantees ref is encrypted and added to history ref + tests --- pkg/api/dynamicaccess.go | 51 ++++--- pkg/api/dynamicaccess_test.go | 34 ++++- pkg/dynamicaccess/accesslogic.go | 16 ++- pkg/dynamicaccess/controller.go | 130 ++++++++++++------ pkg/dynamicaccess/controller_test.go | 79 ++++++++--- pkg/dynamicaccess/grantee.go | 36 ++++- pkg/dynamicaccess/grantee_test.go | 42 ++++-- .../mock/{service.go => controller.go} | 14 +- pkg/node/devnode.go | 2 +- pkg/node/node.go | 2 +- 10 files changed, 289 insertions(+), 117 deletions(-) rename pkg/dynamicaccess/mock/{service.go => controller.go} (93%) diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index 60d3a1c5fab..505e33ee950 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -139,6 +139,7 @@ func (s *Service) actEncryptionHandler( return swarm.ZeroAddress, err } } + // TODO: probably does not need to store the eref, just return it err = putter.Done(encryptedReference) if err != nil { logger.Debug("done split encrypted reference failed", "error", err) @@ -150,6 +151,8 @@ func (s *Service) actEncryptionHandler( return encryptedReference, nil } +// actListGranteesHandler is a middleware that decrypts the given address and returns the list of grantees, +// only the publisher is authorized to access the list func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) { logger := s.logger.WithName("act_list_grantees_handler").Build() paths := struct { @@ -171,9 +174,12 @@ func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) if headers.Cache != nil { cache = *headers.Cache } - grantees, err := s.dac.GetGrantees(r.Context(), s.storer.Download(cache), paths.GranteesAddress) + publisher := &s.publicKey + grantees, err := s.dac.GetGrantees(r.Context(), s.storer.Download(cache), publisher, paths.GranteesAddress) if err != nil { - jsonhttp.NotFound(w, "grantee list not found") + logger.Debug("could not get grantees", "error", err) + logger.Error(nil, "could not get grantees") + jsonhttp.Unauthorized(w, "granteelist not found") return } granteeSlice := make([]string, len(grantees)) @@ -183,6 +189,7 @@ func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) jsonhttp.OK(w, granteeSlice) } +// TODO: actGrantRevokeHandler doc. func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) { logger := s.logger.WithName("act_grant_revoke_handler").Build() @@ -289,7 +296,7 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) } granteeref := paths.GranteesAddress - granteeref, historyref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, granteeref, *headers.HistoryAddress, &s.publicKey, convertToPointerSlice(grantees.Addlist), convertToPointerSlice(grantees.Revokelist)) + granteeref, encryptedglref, historyref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, granteeref, *headers.HistoryAddress, &s.publicKey, convertToPointerSlice(grantees.Addlist), convertToPointerSlice(grantees.Revokelist)) if err != nil { logger.Debug("failed to update grantee list", "error", err) logger.Error(nil, "failed to update grantee list") @@ -297,6 +304,14 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) return } + err = putter.Done(historyref) + if err != nil { + logger.Debug("done split history failed", "error", err) + logger.Error(nil, "done split history failed") + jsonhttp.InternalServerError(w, "done split history failed") + return + } + err = putter.Done(granteeref) if err != nil { logger.Debug("done split grantees failed", "error", err) @@ -305,19 +320,13 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) return } - err = putter.Done(historyref) - if err != nil { - logger.Debug("done split history failed", "error", err) - logger.Error(nil, "done split history failed") - jsonhttp.InternalServerError(w, "done split history failed") - return - } jsonhttp.OK(w, GranteesPatchResponse{ - Reference: granteeref, + Reference: encryptedglref, HistoryReference: historyref, }) } +// TODO: actCreateGranteesHandler doc. func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Request) { logger := s.logger.WithName("acthandler").Build() @@ -402,7 +411,7 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques return } - granteeref, historyref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, swarm.ZeroAddress, swarm.ZeroAddress, &s.publicKey, convertToPointerSlice(list), nil) + granteeref, encryptedglref, historyref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, swarm.ZeroAddress, swarm.ZeroAddress, &s.publicKey, convertToPointerSlice(list), nil) if err != nil { logger.Debug("failed to update grantee list", "error", err) logger.Error(nil, "failed to update grantee list") @@ -410,14 +419,6 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques return } - err = putter.Done(granteeref) - if err != nil { - logger.Debug("done split grantees failed", "error", err) - logger.Error(nil, "done split grantees failed") - jsonhttp.InternalServerError(w, "done split grantees failed") - return - } - err = putter.Done(historyref) if err != nil { logger.Debug("done split history failed", "error", err) @@ -426,8 +427,16 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques return } + err = putter.Done(granteeref) + if err != nil { + logger.Debug("done split grantees failed", "error", err) + logger.Error(nil, "done split grantees failed") + jsonhttp.InternalServerError(w, "done split grantees failed") + return + } + jsonhttp.Created(w, GranteesPostResponse{ - Reference: granteeref, + Reference: encryptedglref, HistoryReference: historyref, }) } diff --git a/pkg/api/dynamicaccess_test.go b/pkg/api/dynamicaccess_test.go index 4405076b4c8..dd50f0cf749 100644 --- a/pkg/api/dynamicaccess_test.go +++ b/pkg/api/dynamicaccess_test.go @@ -821,24 +821,48 @@ func TestDacGrantees(t *testing.T) { }) ) t.Run("get-grantees", func(t *testing.T) { + var ( + publicKeyBytes = crypto.EncodeSecp256k1PublicKey(&pk.PublicKey) + publisher = hex.EncodeToString(publicKeyBytes) + ) + clientwihtpublisher, _, _, _ := newTestServer(t, testServerOptions{ + Storer: storerMock, + Logger: logger, + Post: mockpost.New(mockpost.WithAcceptAll()), + PublicKey: pk.PublicKey, + Dac: mockdac.New(mockdac.WithHistory(h, fixtureHref.String()), mockdac.WithPublisher(publisher)), + }) expected := []string{ "03d7660772cc3142f8a7a2dfac46ce34d12eac1718720cef0e3d94347902aa96a2", "03c712a7e29bc792ac8d8ae49793d28d5bda27ed70f0d90697b2fb456c0a168bd2", "032541acf966823bae26c2c16a7102e728ade3e2e29c11a8a17b29d8eb2bd19302", } - jsonhttptest.Request(t, client, http.MethodGet, "/grantee/"+addr.String(), http.StatusOK, + jsonhttptest.Request(t, clientwihtpublisher, http.MethodGet, "/grantee/"+addr.String(), http.StatusOK, jsonhttptest.WithExpectedJSONResponse(expected), ) }) - t.Run("get-grantees-missing-address", func(t *testing.T) { - jsonhttptest.Request(t, client, http.MethodGet, "/grantee/123", http.StatusBadRequest, + t.Run("get-grantees-unauthorized", func(t *testing.T) { + jsonhttptest.Request(t, client, http.MethodGet, "/grantee/fc4e9fe978991257b897d987bc4ff13058b66ef45a53189a0b4fe84bb3346396", http.StatusUnauthorized, jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ - Message: "Unauthorized", - Code: http.StatusBadRequest, + Message: "granteelist not found", + Code: http.StatusUnauthorized, }), ) }) + t.Run("get-grantees-invalid-address", func(t *testing.T) { + jsonhttptest.Request(t, client, http.MethodGet, "/grantee/asd", http.StatusBadRequest, + jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ + Code: http.StatusBadRequest, + Message: "invalid path params", + Reasons: []jsonhttp.Reason{ + { + Field: "address", + Error: api.HexInvalidByteError('s').Error(), + }, + }}), + ) + }) t.Run("add-revoke-grantees", func(t *testing.T) { body := api.GranteesPatchRequest{ Addlist: []string{"02ab7473879005929d10ce7d4f626412dad9fe56b0a6622038931d26bd79abf0a4"}, diff --git a/pkg/dynamicaccess/accesslogic.go b/pkg/dynamicaccess/accesslogic.go index b3b808e2b74..33b8ba819ba 100644 --- a/pkg/dynamicaccess/accesslogic.go +++ b/pkg/dynamicaccess/accesslogic.go @@ -11,6 +11,8 @@ import ( ) var hashFunc = sha3.NewLegacyKeccak256 +var oneByteArray = []byte{1} +var zeroByteArray = []byte{0} // Read-only interface for the ACT type Decryptor interface { @@ -50,15 +52,20 @@ func (al ActLogic) EncryptRef(ctx context.Context, storage kvs.KeyValueStore, pu return swarm.ZeroAddress, err } refCipher := encryption.New(accessKey, 0, uint32(0), hashFunc) - encryptedRef, _ := refCipher.Encrypt(ref.Bytes()) + encryptedRef, err := refCipher.Encrypt(ref.Bytes()) + if err != nil { + return swarm.ZeroAddress, err + } return swarm.NewAddress(encryptedRef), nil } // Adds a new grantee to the ACT func (al ActLogic) AddGrantee(ctx context.Context, storage kvs.KeyValueStore, publisherPubKey, granteePubKey *ecdsa.PublicKey, accessKeyPointer *encryption.Key) error { - var accessKey encryption.Key - var err error // Declare the "err" variable + var ( + accessKey encryption.Key + err error + ) if accessKeyPointer == nil { // Get previously generated access key @@ -109,9 +116,6 @@ func (al *ActLogic) getAccessKey(ctx context.Context, storage kvs.KeyValueStore, return accessKeyDecryptionCipher.Decrypt(encryptedAK) } -var oneByteArray = []byte{1} -var zeroByteArray = []byte{0} - // Generate lookup key and access key decryption key for a given public key func (al *ActLogic) getKeys(publicKey *ecdsa.PublicKey) ([][]byte, error) { return al.Session.Key(publicKey, [][]byte{zeroByteArray, oneByteArray}) diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index 003d897a4ca..c8f5851d5d0 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -6,6 +6,7 @@ import ( "io" "time" + encryption "github.com/ethersphere/bee/v2/pkg/encryption" "github.com/ethersphere/bee/v2/pkg/file/loadsave" "github.com/ethersphere/bee/v2/pkg/file/pipeline" "github.com/ethersphere/bee/v2/pkg/file/pipeline/builder" @@ -18,16 +19,17 @@ import ( const granteeListEncrypt = true type GranteeManager interface { - HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, error) - GetGrantees(ctx context.Context, getter storage.Getter, rootHash swarm.Address) ([]*ecdsa.PublicKey, error) + // TODO: doc + HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, error) + // GetGrantees returns the list of grantees for the given publisher. + // The list is accessible only by the publisher. + GetGrantees(ctx context.Context, getter storage.Getter, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) } -// TODO: add granteeList ref to history metadata to solve inconsistency type Controller interface { GranteeManager // DownloadHandler decrypts the encryptedRef using the lookupkey based on the history and timestamp. DownloadHandler(ctx context.Context, getter storage.Getter, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) - // TODO: history encryption // UploadHandler encrypts the reference and stores it in the history as the latest update. UploadHandler(ctx context.Context, getter storage.Getter, putter storage.Putter, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) io.Closer @@ -56,13 +58,12 @@ func (c *controller) DownloadHandler( if err != nil { return swarm.ZeroAddress, err } - // TODO: hanlde granteelist ref in mtdt - kvs, err := kvs.NewReference(ls, entry.Reference()) + act, err := kvs.NewReference(ls, entry.Reference()) if err != nil { return swarm.ZeroAddress, err } - return c.accessLogic.DecryptRef(ctx, kvs, encryptedRef, publisher) + return c.accessLogic.DecryptRef(ctx, act, encryptedRef, publisher) } func (c *controller) UploadHandler( @@ -97,7 +98,6 @@ func (c *controller) UploadHandler( if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } - // TODO: pass granteelist ref as mtdt err = history.Add(ctx, actRef, &now, nil) if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err @@ -111,7 +111,6 @@ func (c *controller) UploadHandler( if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } - // TODO: hanlde granteelist ref in mtdt entry, err := history.Lookup(ctx, now) actRef = entry.Reference() if err != nil { @@ -127,69 +126,81 @@ func (c *controller) UploadHandler( return actRef, historyRef, encryptedRef, err } -func NewController(ctx context.Context, accessLogic ActLogic) Controller { +func NewController(accessLogic ActLogic) Controller { return &controller{ accessLogic: accessLogic, } } +// TODO: is an empty addlist && removelist check necessary ? func (c *controller) HandleGrantees( ctx context.Context, getter storage.Getter, putter storage.Putter, - granteeref swarm.Address, + encryptedglref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList []*ecdsa.PublicKey, removeList []*ecdsa.PublicKey, -) (swarm.Address, swarm.Address, error) { +) (swarm.Address, swarm.Address, swarm.Address, error) { var ( - err error - h History - act kvs.KeyValueStore - ls = loadsave.New(getter, putter, requestPipelineFactory(ctx, putter, false, redundancy.NONE)) - gls = loadsave.New(getter, putter, requestPipelineFactory(ctx, putter, granteeListEncrypt, redundancy.NONE)) + err error + h History + act kvs.KeyValueStore + granteeref swarm.Address + ls = loadsave.New(getter, putter, requestPipelineFactory(ctx, putter, false, redundancy.NONE)) + gls = loadsave.New(getter, putter, requestPipelineFactory(ctx, putter, granteeListEncrypt, redundancy.NONE)) ) if !historyref.IsZero() { h, err = NewHistoryReference(ls, historyref) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } entry, err := h.Lookup(ctx, time.Now().Unix()) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } actref := entry.Reference() act, err = kvs.NewReference(ls, actref) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } else { h, err = NewHistory(ls) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } act, err = kvs.New(ls) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } var gl GranteeList - if granteeref.IsZero() { - gl = NewGranteeList(gls) + if encryptedglref.IsZero() { + gl, err = NewGranteeList(gls) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + } } else { - gl = NewGranteeListReference(gls, granteeref) + granteeref, err = c.decryptRefForPublisher(publisher, encryptedglref) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + } + gl, err = NewGranteeListReference(gls, granteeref) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + } } err = gl.Add(addList) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } if len(removeList) != 0 { err = gl.Remove(removeList) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } @@ -198,7 +209,7 @@ func (c *controller) HandleGrantees( if len(removeList) != 0 || granteeref.IsZero() { err = c.accessLogic.AddPublisher(ctx, act, publisher) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } granteesToAdd = gl.Get() } else { @@ -208,37 +219,78 @@ func (c *controller) HandleGrantees( for _, grantee := range granteesToAdd { err := c.accessLogic.AddGrantee(ctx, act, publisher, grantee, nil) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } actref, err := act.Save(ctx) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } - err = h.Add(ctx, actref, nil, nil) + glref, err := gl.Save(ctx) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } - href, err := h.Store(ctx) + eglref, err := c.encryptRefForPublisher(publisher, glref) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } - glref, err := gl.Save(ctx) + mtdt := map[string]string{"encryptedglref": eglref.String()} + err = h.Add(ctx, actref, nil, &mtdt) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + } + href, err := h.Store(ctx) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } - return glref, href, nil + + return glref, eglref, href, nil } -func (c *controller) GetGrantees(ctx context.Context, getter storage.Getter, granteeRef swarm.Address) ([]*ecdsa.PublicKey, error) { +func (c *controller) GetGrantees(ctx context.Context, getter storage.Getter, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) { ls := loadsave.NewReadonly(getter) - gl := NewGranteeListReference(ls, granteeRef) + granteeRef, err := c.decryptRefForPublisher(publisher, encryptedglref) + if err != nil { + return nil, err + } + gl, err := NewGranteeListReference(ls, granteeRef) + if err != nil { + return nil, err + } return gl.Get(), nil } +func (c *controller) encryptRefForPublisher(publisherPubKey *ecdsa.PublicKey, ref swarm.Address) (swarm.Address, error) { + keys, err := c.accessLogic.Session.Key(publisherPubKey, [][]byte{oneByteArray}) + if err != nil { + return swarm.ZeroAddress, err + } + refCipher := encryption.New(keys[0], 0, uint32(0), hashFunc) + encryptedRef, err := refCipher.Encrypt(ref.Bytes()) + if err != nil { + return swarm.ZeroAddress, err + } + + return swarm.NewAddress(encryptedRef), nil +} + +func (c *controller) decryptRefForPublisher(publisherPubKey *ecdsa.PublicKey, encryptedRef swarm.Address) (swarm.Address, error) { + keys, err := c.accessLogic.Session.Key(publisherPubKey, [][]byte{oneByteArray}) + if err != nil { + return swarm.ZeroAddress, err + } + refCipher := encryption.New(keys[0], 0, uint32(0), hashFunc) + ref, err := refCipher.Decrypt(encryptedRef.Bytes()) + if err != nil { + return swarm.ZeroAddress, err + } + + return swarm.NewAddress(ref), nil +} + func requestPipelineFactory(ctx context.Context, s storage.Putter, encrypt bool, rLevel redundancy.Level) func() pipeline.Interface { return func() pipeline.Interface { return builder.NewPipelineBuilder(ctx, s, encrypt, rLevel) diff --git a/pkg/dynamicaccess/controller_test.go b/pkg/dynamicaccess/controller_test.go index 3d5b4a5b850..e12a6acc624 100644 --- a/pkg/dynamicaccess/controller_test.go +++ b/pkg/dynamicaccess/controller_test.go @@ -3,20 +3,23 @@ package dynamicaccess_test import ( "context" "crypto/ecdsa" + "reflect" "testing" "time" "github.com/ethersphere/bee/v2/pkg/dynamicaccess" + encryption "github.com/ethersphere/bee/v2/pkg/encryption" "github.com/ethersphere/bee/v2/pkg/file" "github.com/ethersphere/bee/v2/pkg/kvs" "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/stretchr/testify/assert" + "golang.org/x/crypto/sha3" ) func getHistoryFixture(ctx context.Context, ls file.LoadSaver, al dynamicaccess.ActLogic, publisher *ecdsa.PublicKey) (swarm.Address, error) { h, err := dynamicaccess.NewHistory(ls) if err != nil { - return swarm.ZeroAddress, nil + return swarm.ZeroAddress, err } pk1 := getPrivKey(1) pk2 := getPrivKey(2) @@ -47,7 +50,7 @@ func TestController_NewUpload(t *testing.T) { publisher := getPrivKey(0) diffieHellman := dynamicaccess.NewDefaultSession(publisher) al := dynamicaccess.NewLogic(diffieHellman) - c := dynamicaccess.NewController(ctx, al) + c := dynamicaccess.NewController(al) ref := swarm.RandAddress(t) _, hRef, encRef, err := c.UploadHandler(ctx, mockStorer.ChunkStore(), mockStorer.Cache(), ref, &publisher.PublicKey, swarm.ZeroAddress) @@ -68,7 +71,7 @@ func TestController_PublisherDownload(t *testing.T) { publisher := getPrivKey(0) diffieHellman := dynamicaccess.NewDefaultSession(publisher) al := dynamicaccess.NewLogic(diffieHellman) - c := dynamicaccess.NewController(ctx, al) + c := dynamicaccess.NewController(al) ls := createLs() ref := swarm.RandAddress(t) href, err := getHistoryFixture(ctx, ls, al, &publisher.PublicKey) @@ -94,7 +97,7 @@ func TestController_GranteeDownload(t *testing.T) { diffieHellman := dynamicaccess.NewDefaultSession(grantee) al := dynamicaccess.NewLogic(diffieHellman) ls := createLs() - c := dynamicaccess.NewController(ctx, al) + c := dynamicaccess.NewController(al) ref := swarm.RandAddress(t) href, err := getHistoryFixture(ctx, ls, publisherAL, &publisher.PublicKey) h, err := dynamicaccess.NewHistoryReference(ls, href) @@ -115,10 +118,12 @@ func TestController_HandleGrantees(t *testing.T) { publisher := getPrivKey(1) diffieHellman := dynamicaccess.NewDefaultSession(publisher) al := dynamicaccess.NewLogic(diffieHellman) + keys, _ := al.Session.Key(&publisher.PublicKey, [][]byte{{1}}) + refCipher := encryption.New(keys[0], 0, uint32(0), sha3.NewLegacyKeccak256) ls := createLs() getter := mockStorer.ChunkStore() putter := mockStorer.Cache() - c := dynamicaccess.NewController(ctx, al) + c := dynamicaccess.NewController(al) href, _ := getHistoryFixture(ctx, ls, al, &publisher.PublicKey) grantee1 := getPrivKey(0) @@ -126,37 +131,38 @@ func TestController_HandleGrantees(t *testing.T) { t.Run("add to new list", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + granteeRef, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) - gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 1) }) t.Run("add to existing list", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, eglref, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) - gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 1) addList = []*ecdsa.PublicKey{&getPrivKey(0).PublicKey} - granteeRef, _, err = c.HandleGrantees(ctx, getter, putter, granteeRef, href, &publisher.PublicKey, addList, nil) - gl = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + granteeRef, _, _, err = c.HandleGrantees(ctx, getter, putter, eglref, href, &publisher.PublicKey, addList, nil) + gl, err = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 2) }) t.Run("add and revoke", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} revokeList := []*ecdsa.PublicKey{&grantee1.PublicKey} - gl := dynamicaccess.NewGranteeList(createLs()) + gl, _ := dynamicaccess.NewGranteeList(createLs()) gl.Add([]*ecdsa.PublicKey{&publisher.PublicKey, &grantee1.PublicKey}) granteeRef, err := gl.Save(ctx) + eglref, _ := refCipher.Encrypt(granteeRef.Bytes()) - granteeRef, _, err = c.HandleGrantees(ctx, getter, putter, granteeRef, href, &publisher.PublicKey, addList, revokeList) - gl = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + granteeRef, _, _, err = c.HandleGrantees(ctx, getter, putter, swarm.NewAddress(eglref), href, &publisher.PublicKey, addList, revokeList) + gl, err = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 2) @@ -164,19 +170,54 @@ func TestController_HandleGrantees(t *testing.T) { t.Run("add twice", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey, &grantee.PublicKey} - granteeRef, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) - granteeRef, _, err = c.HandleGrantees(ctx, getter, putter, granteeRef, href, &publisher.PublicKey, addList, nil) - gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + granteeRef, eglref, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, _, _, err = c.HandleGrantees(ctx, getter, putter, eglref, href, &publisher.PublicKey, addList, nil) + gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 1) }) t.Run("revoke non-existing", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) - gl := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + granteeRef, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 1) }) } + +func TestController_GetGrantees(t *testing.T) { + ctx := context.Background() + publisher := getPrivKey(1) + caller := getPrivKey(0) + grantee := getPrivKey(2) + diffieHellman1 := dynamicaccess.NewDefaultSession(publisher) + diffieHellman2 := dynamicaccess.NewDefaultSession(caller) + al1 := dynamicaccess.NewLogic(diffieHellman1) + al2 := dynamicaccess.NewLogic(diffieHellman2) + ls := createLs() + getter := mockStorer.ChunkStore() + putter := mockStorer.Cache() + c1 := dynamicaccess.NewController(al1) + c2 := dynamicaccess.NewController(al2) + + t.Run("get by publisher", func(t *testing.T) { + addList := []*ecdsa.PublicKey{&grantee.PublicKey} + granteeRef, eglRef, _, err := c1.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + + grantees, err := c1.GetGrantees(ctx, getter, &publisher.PublicKey, eglRef) + assert.NoError(t, err) + assert.True(t, reflect.DeepEqual(grantees, addList)) + + gl, _ := dynamicaccess.NewGranteeListReference(ls, granteeRef) + assert.True(t, reflect.DeepEqual(gl.Get(), addList)) + }) + t.Run("get by non-publisher", func(t *testing.T) { + addList := []*ecdsa.PublicKey{&grantee.PublicKey} + _, eglRef, _, err := c1.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + grantees, err := c2.GetGrantees(ctx, getter, &publisher.PublicKey, eglRef) + assert.Error(t, err) + assert.Nil(t, grantees) + }) +} diff --git a/pkg/dynamicaccess/grantee.go b/pkg/dynamicaccess/grantee.go index b0a1a3799cd..02cd8099021 100644 --- a/pkg/dynamicaccess/grantee.go +++ b/pkg/dynamicaccess/grantee.go @@ -15,10 +15,15 @@ const ( publicKeyLen = 65 ) +// GranteeList manages a list of public keys. type GranteeList interface { + // Add adds a list of public keys to the grantee list. It filters out duplicates. Add(addList []*ecdsa.PublicKey) error + // Remove removes a list of public keys from the grantee list, if there is any. Remove(removeList []*ecdsa.PublicKey) error + // Get simply returns the list of public keys. Get() []*ecdsa.PublicKey + // Save saves the grantee list to the underlying storage and returns the reference. Save(ctx context.Context) (swarm.Address, error) } @@ -37,7 +42,26 @@ func (g *GranteeListStruct) Add(addList []*ecdsa.PublicKey) error { if len(addList) == 0 { return fmt.Errorf("no public key provided") } - g.grantees = append(g.grantees, addList...) + filteredList := make([]*ecdsa.PublicKey, 0, len(addList)) + for _, addkey := range addList { + add := true + for _, granteekey := range g.grantees { + if granteekey.Equal(addkey) { + add = false + break + } + } + for _, filteredkey := range filteredList { + if filteredkey.Equal(addkey) { + add = false + break + } + } + if add { + filteredList = append(filteredList, addkey) + } + } + g.grantees = append(g.grantees, filteredList...) return nil } @@ -75,24 +99,24 @@ func (g *GranteeListStruct) Remove(keysToRemove []*ecdsa.PublicKey) error { return nil } -func NewGranteeList(ls file.LoadSaver) GranteeList { +func NewGranteeList(ls file.LoadSaver) (GranteeList, error) { return &GranteeListStruct{ grantees: []*ecdsa.PublicKey{}, loadSave: ls, - } + }, nil } -func NewGranteeListReference(ls file.LoadSaver, reference swarm.Address) GranteeList { +func NewGranteeListReference(ls file.LoadSaver, reference swarm.Address) (GranteeList, error) { data, err := ls.Load(context.Background(), reference.Bytes()) if err != nil { - return nil + return nil, err } grantees := deserialize(data) return &GranteeListStruct{ grantees: grantees, loadSave: ls, - } + }, nil } func serialize(publicKeys []*ecdsa.PublicKey) []byte { diff --git a/pkg/dynamicaccess/grantee_test.go b/pkg/dynamicaccess/grantee_test.go index 8782a96bc45..c4ce58ac8aa 100644 --- a/pkg/dynamicaccess/grantee_test.go +++ b/pkg/dynamicaccess/grantee_test.go @@ -15,6 +15,7 @@ import ( "github.com/ethersphere/bee/v2/pkg/file/redundancy" "github.com/ethersphere/bee/v2/pkg/storage" mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" + "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/stretchr/testify/assert" ) @@ -41,7 +42,7 @@ func generateKeyListFixture() ([]*ecdsa.PublicKey, error) { } func TestGranteeAddGet(t *testing.T) { - gl := dynamicaccess.NewGranteeList(createLs()) + gl, _ := dynamicaccess.NewGranteeList(createLs()) keys, err := generateKeyListFixture() if err != nil { t.Errorf("key generation error: %v", err) @@ -54,9 +55,10 @@ func TestGranteeAddGet(t *testing.T) { t.Run("Get should return value equal to put value", func(t *testing.T) { var ( + keys2, _ = generateKeyListFixture() addList1 []*ecdsa.PublicKey = []*ecdsa.PublicKey{keys[0]} - addList2 []*ecdsa.PublicKey = []*ecdsa.PublicKey{keys[1], keys[0]} - addList3 []*ecdsa.PublicKey = keys + addList2 []*ecdsa.PublicKey = []*ecdsa.PublicKey{keys[1], keys[2]} + addList3 []*ecdsa.PublicKey = keys2 ) testCases := []struct { name string @@ -66,6 +68,10 @@ func TestGranteeAddGet(t *testing.T) { name: "Test list = 1", list: addList1, }, + { + name: "Test list = duplicate1", + list: addList1, + }, { name: "Test list = 2", list: addList2, @@ -88,7 +94,9 @@ func TestGranteeAddGet(t *testing.T) { assert.Error(t, err) } else { assert.NoError(t, err) - expList = append(expList, tc.list...) + if tc.name != "Test list = duplicate1" { + expList = append(expList, tc.list...) + } retVal := gl.Get() assert.Equal(t, expList, retVal) } @@ -98,7 +106,7 @@ func TestGranteeAddGet(t *testing.T) { } func TestGranteeRemove(t *testing.T) { - gl := dynamicaccess.NewGranteeList(createLs()) + gl, _ := dynamicaccess.NewGranteeList(createLs()) keys, err := generateKeyListFixture() if err != nil { t.Errorf("key generation error: %v", err) @@ -150,13 +158,18 @@ func TestGranteeSave(t *testing.T) { if err != nil { t.Errorf("key generation error: %v", err) } + t.Run("Create grantee list with invalid reference, expect error", func(t *testing.T) { + gl, err := dynamicaccess.NewGranteeListReference(createLs(), swarm.RandAddress(t)) + assert.Error(t, err) + assert.Nil(t, gl) + }) t.Run("Save empty grantee list return NO error", func(t *testing.T) { - gl := dynamicaccess.NewGranteeList(createLs()) + gl, _ := dynamicaccess.NewGranteeList(createLs()) _, err := gl.Save(ctx) assert.NoError(t, err) }) t.Run("Save not empty grantee list return valid swarm address", func(t *testing.T) { - gl := dynamicaccess.NewGranteeList(createLs()) + gl, _ := dynamicaccess.NewGranteeList(createLs()) err = gl.Add(keys) ref, err := gl.Save(ctx) assert.NoError(t, err) @@ -164,7 +177,7 @@ func TestGranteeSave(t *testing.T) { }) t.Run("Save grantee list with one item, no error, pre-save value exist", func(t *testing.T) { ls := createLs() - gl1 := dynamicaccess.NewGranteeList(ls) + gl1, _ := dynamicaccess.NewGranteeList(ls) err := gl1.Add(keys) assert.NoError(t, err) @@ -172,32 +185,33 @@ func TestGranteeSave(t *testing.T) { ref, err := gl1.Save(ctx) assert.NoError(t, err) - gl2 := dynamicaccess.NewGranteeListReference(ls, ref) + gl2, _ := dynamicaccess.NewGranteeListReference(ls, ref) val := gl2.Get() assert.NoError(t, err) assert.Equal(t, keys, val) }) t.Run("Save grantee list and add one item, no error, after-save value exist", func(t *testing.T) { ls := createLs() + keys2, _ := generateKeyListFixture() - gl1 := dynamicaccess.NewGranteeList(ls) + gl1, _ := dynamicaccess.NewGranteeList(ls) err := gl1.Add(keys) assert.NoError(t, err) ref, err := gl1.Save(ctx) assert.NoError(t, err) - gl2 := dynamicaccess.NewGranteeListReference(ls, ref) - err = gl2.Add(keys) + gl2, _ := dynamicaccess.NewGranteeListReference(ls, ref) + err = gl2.Add(keys2) assert.NoError(t, err) val := gl2.Get() - assert.Equal(t, append(keys, keys...), val) + assert.Equal(t, append(keys, keys2...), val) }) } func TestGranteeRemoveTwo(t *testing.T) { - gl := dynamicaccess.NewGranteeList(createLs()) + gl, _ := dynamicaccess.NewGranteeList(createLs()) keys, err := generateKeyListFixture() if err != nil { t.Errorf("key generation error: %v", err) diff --git a/pkg/dynamicaccess/mock/service.go b/pkg/dynamicaccess/mock/controller.go similarity index 93% rename from pkg/dynamicaccess/mock/service.go rename to pkg/dynamicaccess/mock/controller.go index 15f26ac6f00..241e22fa931 100644 --- a/pkg/dynamicaccess/mock/service.go +++ b/pkg/dynamicaccess/mock/controller.go @@ -126,7 +126,6 @@ func (m *mockDacService) UploadHandler(ctx context.Context, getter storage.Gette } } else { h, _ = dynamicaccess.NewHistory(m.ls) - // TODO: pass granteelist ref as mtdt h.Add(ctx, kvsRef, &now, nil) historyRef, _ = h.Store(ctx) m.historyMap[historyRef.String()] = h @@ -141,18 +140,23 @@ func (m *mockDacService) Close() error { return nil } -func (m *mockDacService) HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, error) { +func (m *mockDacService) HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, error) { historyRef, _ := swarm.ParseHexAddress("67bdf80a9bbea8eca9c8480e43fdceb485d2d74d5708e45144b8c4adacd13d9c") glRef, _ := swarm.ParseHexAddress("3339613565613837623134316665343461613630396333333237656364383934") - return glRef, historyRef, nil + eglRef, _ := swarm.ParseHexAddress("fc4e9fe978991257b897d987bc4ff13058b66ef45a53189a0b4fe84bb3346396") + return glRef, eglRef, historyRef, nil } -func (m *mockDacService) GetGrantees(ctx context.Context, getter storage.Getter, granteeref swarm.Address) ([]*ecdsa.PublicKey, error) { + +func (m *mockDacService) GetGrantees(ctx context.Context, getter storage.Getter, publisher *ecdsa.PublicKey, granteeref swarm.Address) ([]*ecdsa.PublicKey, error) { + if m.publisher == "" { + return nil, fmt.Errorf("granteelist not found") + } keys := []string{ "a786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfa", "b786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfb", "c786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfc", } - var pubkeys []*ecdsa.PublicKey + pubkeys := make([]*ecdsa.PublicKey, 0, len(keys)) for i := range keys { data, err := hex.DecodeString(keys[i]) if err != nil { diff --git a/pkg/node/devnode.go b/pkg/node/devnode.go index b7ac3dfee56..275140e10a5 100644 --- a/pkg/node/devnode.go +++ b/pkg/node/devnode.go @@ -238,7 +238,7 @@ func NewDevBee(logger log.Logger, o *DevOptions) (b *DevBee, err error) { session := dynamicaccess.NewDefaultSession(mockKey) actLogic := dynamicaccess.NewLogic(session) - dac := dynamicaccess.NewController(context.Background(), actLogic) + dac := dynamicaccess.NewController(actLogic) b.dacCloser = dac pssService := pss.New(mockKey, logger) diff --git a/pkg/node/node.go b/pkg/node/node.go index b48e97ddafc..4002693ff2e 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -776,7 +776,7 @@ func NewBee( evictFn = func(id []byte) error { return localStore.EvictBatch(context.Background(), id) } actLogic := dynamicaccess.NewLogic(session) - dac := dynamicaccess.NewController(ctx, actLogic) + dac := dynamicaccess.NewController(actLogic) b.dacCloser = dac var ( From e49e4a2531388962db8641826c50efd2959c2288 Mon Sep 17 00:00:00 2001 From: Kexort Date: Mon, 29 Apr 2024 08:34:29 +0200 Subject: [PATCH 07/19] Fix nil pointer dereference panic --- pkg/api/dynamicaccess.go | 6 +++--- pkg/api/dynamicaccess_test.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index 505e33ee950..96c1f542bbf 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -179,7 +179,7 @@ func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) if err != nil { logger.Debug("could not get grantees", "error", err) logger.Error(nil, "could not get grantees") - jsonhttp.Unauthorized(w, "granteelist not found") + jsonhttp.NotFound(w, "granteelist not found") return } granteeSlice := make([]string, len(grantees)) @@ -366,7 +366,7 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques } } - list := make([]ecdsa.PublicKey, len(gpr.GranteeList)) + list := make([]ecdsa.PublicKey, 0, len(gpr.GranteeList)) for _, g := range gpr.GranteeList { h, _ := hex.DecodeString(g) k, _ := btcec.ParsePubKey(h) @@ -451,7 +451,7 @@ func convertToPointerSlice(slice []ecdsa.PublicKey) []*ecdsa.PublicKey { } func parseKeys(list []string) ([]ecdsa.PublicKey, error) { - parsedList := make([]ecdsa.PublicKey, len(list)) + parsedList := make([]ecdsa.PublicKey, 0, len(list)) for _, g := range list { h, err := hex.DecodeString(g) if err != nil { diff --git a/pkg/api/dynamicaccess_test.go b/pkg/api/dynamicaccess_test.go index dd50f0cf749..3e316b6bf64 100644 --- a/pkg/api/dynamicaccess_test.go +++ b/pkg/api/dynamicaccess_test.go @@ -846,7 +846,7 @@ func TestDacGrantees(t *testing.T) { jsonhttptest.Request(t, client, http.MethodGet, "/grantee/fc4e9fe978991257b897d987bc4ff13058b66ef45a53189a0b4fe84bb3346396", http.StatusUnauthorized, jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ Message: "granteelist not found", - Code: http.StatusUnauthorized, + Code: http.StatusNotFound, }), ) }) From d0f9dddcf4e8ee949bcc5e0b66fe90abb5dacf07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Ujv=C3=A1ri?= Date: Mon, 29 Apr 2024 13:10:15 +0200 Subject: [PATCH 08/19] CHG: put actref in handlegrantees; Add: pin, tag,deferred headers --- pkg/api/dynamicaccess.go | 135 ++++++++++++++++----------- pkg/api/dynamicaccess_test.go | 2 + pkg/dynamicaccess/controller.go | 46 ++++----- pkg/dynamicaccess/controller_test.go | 18 ++-- pkg/dynamicaccess/mock/controller.go | 5 +- 5 files changed, 116 insertions(+), 90 deletions(-) diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index 96c1f542bbf..a8ca979cbc8 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -54,8 +54,8 @@ type GranteesPostResponse struct { HistoryReference swarm.Address `json:"historyref"` } type GranteesPatch struct { - Addlist []ecdsa.PublicKey - Revokelist []ecdsa.PublicKey + Addlist []*ecdsa.PublicKey + Revokelist []*ecdsa.PublicKey } // actDecryptionHandler is a middleware that looks up and decrypts the given address, @@ -139,13 +139,6 @@ func (s *Service) actEncryptionHandler( return swarm.ZeroAddress, err } } - // TODO: probably does not need to store the eref, just return it - err = putter.Done(encryptedReference) - if err != nil { - logger.Debug("done split encrypted reference failed", "error", err) - logger.Error(nil, "done split encrypted reference failed") - return swarm.ZeroAddress, err - } w.Header().Set(SwarmActHistoryAddressHeader, historyReference.String()) return encryptedReference, nil @@ -182,7 +175,7 @@ func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) jsonhttp.NotFound(w, "granteelist not found") return } - granteeSlice := make([]string, len(grantees)) + granteeSlice := make([]string, 0, len(grantees)) for i, grantee := range grantees { granteeSlice[i] = hex.EncodeToString(crypto.EncodeSecp256k1PublicKey(grantee)) } @@ -209,6 +202,9 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) headers := struct { BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"` + SwarmTag uint64 `map:"Swarm-Tag"` + Pin bool `map:"Swarm-Pin"` + Deferred *bool `map:"Swarm-Deferred-Upload"` HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address" validate:"required"` }{} if response := s.mapStructure(r.Header, &headers); response != nil { @@ -216,6 +212,27 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) return } + var ( + tag uint64 + err error + deferred = defaultUploadMethod(headers.Deferred) + ) + + if deferred || headers.Pin { + tag, err = s.getOrCreateSessionID(headers.SwarmTag) + if err != nil { + logger.Debug("get or create tag failed", "error", err) + logger.Error(nil, "get or create tag failed") + switch { + case errors.Is(err, storage.ErrNotFound): + jsonhttp.NotFound(w, "tag not found") + default: + jsonhttp.InternalServerError(w, "cannot get or create tag") + } + return + } + } + body, err := io.ReadAll(r.Body) if err != nil { if jsonhttp.HandleBodyReadError(err, w) { @@ -257,19 +274,6 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) } grantees.Revokelist = append(grantees.Revokelist, paresRevokelist...) - tag, err := s.getOrCreateSessionID(0) - if err != nil { - logger.Debug("get or create tag failed", "error", err) - logger.Error(nil, "get or create tag failed") - switch { - case errors.Is(err, storage.ErrNotFound): - jsonhttp.NotFound(w, "tag not found") - default: - jsonhttp.InternalServerError(w, "cannot get or create tag") - } - return - } - ctx := r.Context() putter, err := s.newStamperPutter(ctx, putterOptions{ BatchID: headers.BatchID, @@ -296,7 +300,7 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) } granteeref := paths.GranteesAddress - granteeref, encryptedglref, historyref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, granteeref, *headers.HistoryAddress, &s.publicKey, convertToPointerSlice(grantees.Addlist), convertToPointerSlice(grantees.Revokelist)) + granteeref, encryptedglref, historyref, actref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, granteeref, *headers.HistoryAddress, &s.publicKey, grantees.Addlist, grantees.Revokelist) if err != nil { logger.Debug("failed to update grantee list", "error", err) logger.Error(nil, "failed to update grantee list") @@ -304,6 +308,14 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) return } + err = putter.Done(actref) + if err != nil { + logger.Debug("done split act failed", "error", err) + logger.Error(nil, "done split act failed") + jsonhttp.InternalServerError(w, "done split act failed") + return + } + err = putter.Done(historyref) if err != nil { logger.Debug("done split history failed", "error", err) @@ -337,13 +349,37 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques } headers := struct { - BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"` + BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"` + SwarmTag uint64 `map:"Swarm-Tag"` + Pin bool `map:"Swarm-Pin"` + Deferred *bool `map:"Swarm-Deferred-Upload"` }{} if response := s.mapStructure(r.Header, &headers); response != nil { response("invalid header params", logger, w) return } + var ( + tag uint64 + err error + deferred = defaultUploadMethod(headers.Deferred) + ) + + if deferred || headers.Pin { + tag, err = s.getOrCreateSessionID(headers.SwarmTag) + if err != nil { + logger.Debug("get or create tag failed", "error", err) + logger.Error(nil, "get or create tag failed") + switch { + case errors.Is(err, storage.ErrNotFound): + jsonhttp.NotFound(w, "tag not found") + default: + jsonhttp.InternalServerError(w, "cannot get or create tag") + } + return + } + } + body, err := io.ReadAll(r.Body) if err != nil { if jsonhttp.HandleBodyReadError(err, w) { @@ -366,27 +402,15 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques } } - list := make([]ecdsa.PublicKey, 0, len(gpr.GranteeList)) - for _, g := range gpr.GranteeList { - h, _ := hex.DecodeString(g) - k, _ := btcec.ParsePubKey(h) - list = append(list, *k.ToECDSA()) - } - tag, err := s.getOrCreateSessionID(0) + list, err := parseKeys(gpr.GranteeList) if err != nil { - logger.Debug("get or create tag failed", "error", err) - logger.Error(nil, "get or create tag failed") - switch { - case errors.Is(err, storage.ErrNotFound): - jsonhttp.NotFound(w, "tag not found") - default: - jsonhttp.InternalServerError(w, "cannot get or create tag") - } + logger.Debug("create list key parse failed", "error", err) + logger.Error(nil, "create list key parse failed") + jsonhttp.InternalServerError(w, "error create list key parsing") return } ctx := r.Context() - // TODO: pin and deferred headers putter, err := s.newStamperPutter(ctx, putterOptions{ BatchID: headers.BatchID, TagID: tag, @@ -411,7 +435,7 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques return } - granteeref, encryptedglref, historyref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, swarm.ZeroAddress, swarm.ZeroAddress, &s.publicKey, convertToPointerSlice(list), nil) + granteeref, encryptedglref, historyref, actref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, swarm.ZeroAddress, swarm.ZeroAddress, &s.publicKey, list, nil) if err != nil { logger.Debug("failed to update grantee list", "error", err) logger.Error(nil, "failed to update grantee list") @@ -419,6 +443,14 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques return } + err = putter.Done(actref) + if err != nil { + logger.Debug("done split act failed", "error", err) + logger.Error(nil, "done split act failed") + jsonhttp.InternalServerError(w, "done split act failed") + return + } + err = putter.Done(historyref) if err != nil { logger.Debug("done split history failed", "error", err) @@ -441,27 +473,18 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques }) } -func convertToPointerSlice(slice []ecdsa.PublicKey) []*ecdsa.PublicKey { - pointerSlice := make([]*ecdsa.PublicKey, len(slice)) - for i, key := range slice { - tempKey := key - pointerSlice[i] = &tempKey - } - return pointerSlice -} - -func parseKeys(list []string) ([]ecdsa.PublicKey, error) { - parsedList := make([]ecdsa.PublicKey, 0, len(list)) +func parseKeys(list []string) ([]*ecdsa.PublicKey, error) { + parsedList := make([]*ecdsa.PublicKey, 0, len(list)) for _, g := range list { h, err := hex.DecodeString(g) if err != nil { - return []ecdsa.PublicKey{}, err + return []*ecdsa.PublicKey{}, err } k, err := btcec.ParsePubKey(h) if err != nil { - return []ecdsa.PublicKey{}, err + return []*ecdsa.PublicKey{}, err } - parsedList = append(parsedList, *k.ToECDSA()) + parsedList = append(parsedList, k.ToECDSA()) } return parsedList, nil diff --git a/pkg/api/dynamicaccess_test.go b/pkg/api/dynamicaccess_test.go index 3e316b6bf64..4b503f9ffcb 100644 --- a/pkg/api/dynamicaccess_test.go +++ b/pkg/api/dynamicaccess_test.go @@ -62,6 +62,7 @@ func prepareHistoryFixture(storer api.Storer) (dynamicaccess.History, swarm.Addr return h, ref } +// TODO: test tag, pin, deferred, stamp // TODO: feed test // nolint:paralleltest,tparallel // TestDacWithoutActHeader [positive tests]: @@ -387,6 +388,7 @@ func TestDacHistory(t *testing.T) { fileName = "sample.html" now = time.Now().Unix() ) + fmt.Printf("bagoy now: %d\n", now) t.Run("empty-history-upload-then-download-and-check-data", func(t *testing.T) { client, _, _, _ := newTestServer(t, testServerOptions{ diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index c8f5851d5d0..c47f78d8ef1 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -20,7 +20,7 @@ const granteeListEncrypt = true type GranteeManager interface { // TODO: doc - HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, error) + HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, swarm.Address, error) // GetGrantees returns the list of grantees for the given publisher. // The list is accessible only by the publisher. GetGrantees(ctx context.Context, getter storage.Getter, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) @@ -132,7 +132,6 @@ func NewController(accessLogic ActLogic) Controller { } } -// TODO: is an empty addlist && removelist check necessary ? func (c *controller) HandleGrantees( ctx context.Context, getter storage.Getter, @@ -142,7 +141,7 @@ func (c *controller) HandleGrantees( publisher *ecdsa.PublicKey, addList []*ecdsa.PublicKey, removeList []*ecdsa.PublicKey, -) (swarm.Address, swarm.Address, swarm.Address, error) { +) (swarm.Address, swarm.Address, swarm.Address, swarm.Address, error) { var ( err error h History @@ -154,26 +153,25 @@ func (c *controller) HandleGrantees( if !historyref.IsZero() { h, err = NewHistoryReference(ls, historyref) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } entry, err := h.Lookup(ctx, time.Now().Unix()) - if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } actref := entry.Reference() act, err = kvs.NewReference(ls, actref) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } else { h, err = NewHistory(ls) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } act, err = kvs.New(ls) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } @@ -181,35 +179,36 @@ func (c *controller) HandleGrantees( if encryptedglref.IsZero() { gl, err = NewGranteeList(gls) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } else { granteeref, err = c.decryptRefForPublisher(publisher, encryptedglref) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } + gl, err = NewGranteeListReference(gls, granteeref) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } err = gl.Add(addList) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } if len(removeList) != 0 { err = gl.Remove(removeList) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } var granteesToAdd []*ecdsa.PublicKey // generate new access key and new act - if len(removeList) != 0 || granteeref.IsZero() { + if len(removeList) != 0 || encryptedglref.IsZero() { err = c.accessLogic.AddPublisher(ctx, act, publisher) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } granteesToAdd = gl.Get() } else { @@ -219,35 +218,36 @@ func (c *controller) HandleGrantees( for _, grantee := range granteesToAdd { err := c.accessLogic.AddGrantee(ctx, act, publisher, grantee, nil) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } actref, err := act.Save(ctx) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } glref, err := gl.Save(ctx) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } + eglref, err := c.encryptRefForPublisher(publisher, glref) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } mtdt := map[string]string{"encryptedglref": eglref.String()} err = h.Add(ctx, actref, nil, &mtdt) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } href, err := h.Store(ctx) if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } - return glref, eglref, href, nil + return glref, eglref, href, actref, nil } func (c *controller) GetGrantees(ctx context.Context, getter storage.Getter, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) { diff --git a/pkg/dynamicaccess/controller_test.go b/pkg/dynamicaccess/controller_test.go index e12a6acc624..5298ac8e7e7 100644 --- a/pkg/dynamicaccess/controller_test.go +++ b/pkg/dynamicaccess/controller_test.go @@ -131,7 +131,7 @@ func TestController_HandleGrantees(t *testing.T) { t.Run("add to new list", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + granteeRef, _, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) @@ -140,7 +140,7 @@ func TestController_HandleGrantees(t *testing.T) { }) t.Run("add to existing list", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, eglref, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, eglref, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) @@ -148,7 +148,7 @@ func TestController_HandleGrantees(t *testing.T) { assert.Len(t, gl.Get(), 1) addList = []*ecdsa.PublicKey{&getPrivKey(0).PublicKey} - granteeRef, _, _, err = c.HandleGrantees(ctx, getter, putter, eglref, href, &publisher.PublicKey, addList, nil) + granteeRef, _, _, _, err = c.HandleGrantees(ctx, getter, putter, eglref, href, &publisher.PublicKey, addList, nil) gl, err = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 2) @@ -161,7 +161,7 @@ func TestController_HandleGrantees(t *testing.T) { granteeRef, err := gl.Save(ctx) eglref, _ := refCipher.Encrypt(granteeRef.Bytes()) - granteeRef, _, _, err = c.HandleGrantees(ctx, getter, putter, swarm.NewAddress(eglref), href, &publisher.PublicKey, addList, revokeList) + granteeRef, _, _, _, err = c.HandleGrantees(ctx, getter, putter, swarm.NewAddress(eglref), href, &publisher.PublicKey, addList, revokeList) gl, err = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) @@ -170,8 +170,8 @@ func TestController_HandleGrantees(t *testing.T) { t.Run("add twice", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey, &grantee.PublicKey} - granteeRef, eglref, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) - granteeRef, _, _, err = c.HandleGrantees(ctx, getter, putter, eglref, href, &publisher.PublicKey, addList, nil) + granteeRef, eglref, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, _, _, _, err = c.HandleGrantees(ctx, getter, putter, eglref, href, &publisher.PublicKey, addList, nil) gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) @@ -179,7 +179,7 @@ func TestController_HandleGrantees(t *testing.T) { }) t.Run("revoke non-existing", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, _, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) @@ -204,7 +204,7 @@ func TestController_GetGrantees(t *testing.T) { t.Run("get by publisher", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, eglRef, _, err := c1.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + granteeRef, eglRef, _, _, err := c1.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) grantees, err := c1.GetGrantees(ctx, getter, &publisher.PublicKey, eglRef) assert.NoError(t, err) @@ -215,7 +215,7 @@ func TestController_GetGrantees(t *testing.T) { }) t.Run("get by non-publisher", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - _, eglRef, _, err := c1.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + _, eglRef, _, _, err := c1.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) grantees, err := c2.GetGrantees(ctx, getter, &publisher.PublicKey, eglRef) assert.Error(t, err) assert.Nil(t, grantees) diff --git a/pkg/dynamicaccess/mock/controller.go b/pkg/dynamicaccess/mock/controller.go index 241e22fa931..10f4c2823a1 100644 --- a/pkg/dynamicaccess/mock/controller.go +++ b/pkg/dynamicaccess/mock/controller.go @@ -140,11 +140,12 @@ func (m *mockDacService) Close() error { return nil } -func (m *mockDacService) HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, error) { +func (m *mockDacService) HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, swarm.Address, error) { historyRef, _ := swarm.ParseHexAddress("67bdf80a9bbea8eca9c8480e43fdceb485d2d74d5708e45144b8c4adacd13d9c") glRef, _ := swarm.ParseHexAddress("3339613565613837623134316665343461613630396333333237656364383934") eglRef, _ := swarm.ParseHexAddress("fc4e9fe978991257b897d987bc4ff13058b66ef45a53189a0b4fe84bb3346396") - return glRef, eglRef, historyRef, nil + actref, _ := swarm.ParseHexAddress("39a5ea87b141fe44aa609c3327ecd896c0e2122897f5f4bbacf74db1033c5559") + return glRef, eglRef, historyRef, actref, nil } func (m *mockDacService) GetGrantees(ctx context.Context, getter storage.Getter, publisher *ecdsa.PublicKey, granteeref swarm.Address) ([]*ecdsa.PublicKey, error) { From 5ae2d9df23f293feef7955ac208c062c3da7a6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Ujv=C3=A1ri?= Date: Mon, 6 May 2024 12:59:10 +0200 Subject: [PATCH 09/19] CHG: pass loadsave to handlers; check if history address is nil --- pkg/api/bytes.go | 2 +- pkg/api/bzz.go | 2 +- pkg/api/chunk.go | 2 +- pkg/api/dirs.go | 2 +- pkg/api/dynamicaccess.go | 54 ++++++++++++++++++++-------- pkg/api/feed.go | 2 +- pkg/api/soc.go | 2 +- pkg/dynamicaccess/controller.go | 28 ++++++--------- pkg/dynamicaccess/controller_test.go | 48 ++++++++++++------------- pkg/dynamicaccess/mock/controller.go | 8 ++--- 10 files changed, 83 insertions(+), 67 deletions(-) diff --git a/pkg/api/bytes.go b/pkg/api/bytes.go index a2d65cae1ba..2afb1db99c0 100644 --- a/pkg/api/bytes.go +++ b/pkg/api/bytes.go @@ -118,7 +118,7 @@ func (s *Service) bytesUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := reference if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, reference, headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, reference, headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/bzz.go b/pkg/api/bzz.go index 7f322be0720..b49bc89baea 100644 --- a/pkg/api/bzz.go +++ b/pkg/api/bzz.go @@ -266,7 +266,7 @@ func (s *Service) fileUploadHandler( encryptedReference := manifestReference if act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, manifestReference, historyAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, manifestReference, historyAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/chunk.go b/pkg/api/chunk.go index 9c462b1a558..21daa0d0f57 100644 --- a/pkg/api/chunk.go +++ b/pkg/api/chunk.go @@ -143,7 +143,7 @@ func (s *Service) chunkUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := chunk.Address() if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, chunk.Address(), headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, chunk.Address(), headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/dirs.go b/pkg/api/dirs.go index e871eee2e8b..f187fbde01e 100644 --- a/pkg/api/dirs.go +++ b/pkg/api/dirs.go @@ -102,7 +102,7 @@ func (s *Service) dirUploadHandler( encryptedReference := reference if act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, reference, historyAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, reference, historyAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index a8ca979cbc8..2ba951c5d67 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -11,6 +11,8 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/ethersphere/bee/v2/pkg/crypto" + "github.com/ethersphere/bee/v2/pkg/file/loadsave" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/postage" storage "github.com/ethersphere/bee/v2/pkg/storage" @@ -21,6 +23,8 @@ import ( type addressKey struct{} +const granteeListEncrypt = true + // getAddressFromContext is a helper function to extract the address from the context func getAddressFromContext(ctx context.Context) swarm.Address { v, ok := ctx.Value(addressKey{}).(swarm.Address) @@ -53,6 +57,7 @@ type GranteesPostResponse struct { Reference swarm.Address `json:"ref"` HistoryReference swarm.Address `json:"historyref"` } + type GranteesPatch struct { Addlist []*ecdsa.PublicKey Revokelist []*ecdsa.PublicKey @@ -94,7 +99,8 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { cache = *headers.Cache } ctx := r.Context() - reference, err := s.dac.DownloadHandler(ctx, s.storer.Download(cache), paths.Address, headers.Publisher, *headers.HistoryAddress, *headers.Timestamp) + ls := loadsave.NewReadonly(s.storer.Download(cache)) + reference, err := s.dac.DownloadHandler(ctx, ls, paths.Address, headers.Publisher, *headers.HistoryAddress, *headers.Timestamp) if err != nil { jsonhttp.InternalServerError(w, errActDownload) return @@ -110,14 +116,14 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { func (s *Service) actEncryptionHandler( ctx context.Context, w http.ResponseWriter, - getter storage.Getter, putter storer.PutterSession, reference swarm.Address, historyRootHash swarm.Address, ) (swarm.Address, error) { logger := s.logger.WithName("act_encryption_handler").Build() publisherPublicKey := &s.publicKey - storageReference, historyReference, encryptedReference, err := s.dac.UploadHandler(ctx, getter, putter, reference, publisherPublicKey, historyRootHash) + ls := loadsave.New(s.storer.ChunkStore(), s.storer.Cache(), requestPipelineFactory(ctx, putter, false, redundancy.NONE)) + storageReference, historyReference, encryptedReference, err := s.dac.UploadHandler(ctx, ls, reference, publisherPublicKey, historyRootHash) if err != nil { logger.Debug("act failed to encrypt reference", "error", err) logger.Error(nil, "act failed to encrypt reference") @@ -168,14 +174,15 @@ func (s *Service) actListGranteesHandler(w http.ResponseWriter, r *http.Request) cache = *headers.Cache } publisher := &s.publicKey - grantees, err := s.dac.GetGrantees(r.Context(), s.storer.Download(cache), publisher, paths.GranteesAddress) + ls := loadsave.NewReadonly(s.storer.Download(cache)) + grantees, err := s.dac.GetGrantees(r.Context(), ls, publisher, paths.GranteesAddress) if err != nil { logger.Debug("could not get grantees", "error", err) logger.Error(nil, "could not get grantees") jsonhttp.NotFound(w, "granteelist not found") return } - granteeSlice := make([]string, 0, len(grantees)) + granteeSlice := make([]string, len(grantees)) for i, grantee := range grantees { granteeSlice[i] = hex.EncodeToString(crypto.EncodeSecp256k1PublicKey(grantee)) } @@ -212,6 +219,11 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) return } + historyAddress := swarm.ZeroAddress + if headers.HistoryAddress != nil { + historyAddress = *headers.HistoryAddress + } + var ( tag uint64 err error @@ -278,8 +290,8 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) putter, err := s.newStamperPutter(ctx, putterOptions{ BatchID: headers.BatchID, TagID: tag, - Pin: false, - Deferred: false, + Pin: headers.Pin, + Deferred: deferred, }) if err != nil { logger.Debug("putter failed", "error", err) @@ -300,7 +312,10 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) } granteeref := paths.GranteesAddress - granteeref, encryptedglref, historyref, actref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, granteeref, *headers.HistoryAddress, &s.publicKey, grantees.Addlist, grantees.Revokelist) + publisher := &s.publicKey + ls := loadsave.New(s.storer.ChunkStore(), s.storer.Cache(), requestPipelineFactory(ctx, putter, false, redundancy.NONE)) + gls := loadsave.New(s.storer.ChunkStore(), s.storer.Cache(), requestPipelineFactory(ctx, putter, granteeListEncrypt, redundancy.NONE)) + granteeref, encryptedglref, historyref, actref, err := s.dac.HandleGrantees(ctx, ls, gls, granteeref, historyAddress, publisher, grantees.Addlist, grantees.Revokelist) if err != nil { logger.Debug("failed to update grantee list", "error", err) logger.Error(nil, "failed to update grantee list") @@ -349,16 +364,22 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques } headers := struct { - BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"` - SwarmTag uint64 `map:"Swarm-Tag"` - Pin bool `map:"Swarm-Pin"` - Deferred *bool `map:"Swarm-Deferred-Upload"` + BatchID []byte `map:"Swarm-Postage-Batch-Id" validate:"required"` + SwarmTag uint64 `map:"Swarm-Tag"` + Pin bool `map:"Swarm-Pin"` + Deferred *bool `map:"Swarm-Deferred-Upload"` + HistoryAddress *swarm.Address `map:"Swarm-Act-History-Address"` }{} if response := s.mapStructure(r.Header, &headers); response != nil { response("invalid header params", logger, w) return } + historyAddress := swarm.ZeroAddress + if headers.HistoryAddress != nil { + historyAddress = *headers.HistoryAddress + } + var ( tag uint64 err error @@ -414,8 +435,8 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques putter, err := s.newStamperPutter(ctx, putterOptions{ BatchID: headers.BatchID, TagID: tag, - Pin: false, - Deferred: false, + Pin: headers.Pin, + Deferred: deferred, }) if err != nil { logger.Debug("putter failed", "error", err) @@ -435,7 +456,10 @@ func (s *Service) actCreateGranteesHandler(w http.ResponseWriter, r *http.Reques return } - granteeref, encryptedglref, historyref, actref, err := s.dac.HandleGrantees(ctx, s.storer.ChunkStore(), putter, swarm.ZeroAddress, swarm.ZeroAddress, &s.publicKey, list, nil) + publisher := &s.publicKey + ls := loadsave.New(s.storer.ChunkStore(), s.storer.Cache(), requestPipelineFactory(ctx, putter, false, redundancy.NONE)) + gls := loadsave.New(s.storer.ChunkStore(), s.storer.Cache(), requestPipelineFactory(ctx, putter, granteeListEncrypt, redundancy.NONE)) + granteeref, encryptedglref, historyref, actref, err := s.dac.HandleGrantees(ctx, ls, gls, swarm.ZeroAddress, historyAddress, publisher, list, nil) if err != nil { logger.Debug("failed to update grantee list", "error", err) logger.Error(nil, "failed to update grantee list") diff --git a/pkg/api/feed.go b/pkg/api/feed.go index 3e4b8d5c10e..3d43d3d148e 100644 --- a/pkg/api/feed.go +++ b/pkg/api/feed.go @@ -249,7 +249,7 @@ func (s *Service) feedPostHandler(w http.ResponseWriter, r *http.Request) { // TODO: do we want to allow feed act upload/ download? encryptedReference := ref if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, ref, headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, ref, headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/api/soc.go b/pkg/api/soc.go index cf37432ed1f..29777066b10 100644 --- a/pkg/api/soc.go +++ b/pkg/api/soc.go @@ -159,7 +159,7 @@ func (s *Service) socUploadHandler(w http.ResponseWriter, r *http.Request) { encryptedReference := sch.Address() if headers.Act { - encryptedReference, err = s.actEncryptionHandler(r.Context(), w, s.storer.ChunkStore(), putter, sch.Address(), headers.HistoryAddress) + encryptedReference, err = s.actEncryptionHandler(r.Context(), w, putter, sch.Address(), headers.HistoryAddress) if err != nil { jsonhttp.InternalServerError(w, errActUpload) return diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index c47f78d8ef1..3764ea2d31f 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -7,7 +7,7 @@ import ( "time" encryption "github.com/ethersphere/bee/v2/pkg/encryption" - "github.com/ethersphere/bee/v2/pkg/file/loadsave" + "github.com/ethersphere/bee/v2/pkg/file" "github.com/ethersphere/bee/v2/pkg/file/pipeline" "github.com/ethersphere/bee/v2/pkg/file/pipeline/builder" "github.com/ethersphere/bee/v2/pkg/file/redundancy" @@ -16,22 +16,20 @@ import ( "github.com/ethersphere/bee/v2/pkg/swarm" ) -const granteeListEncrypt = true - type GranteeManager interface { // TODO: doc - HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, swarm.Address, error) + HandleGrantees(ctx context.Context, ls file.LoadSaver, gls file.LoadSaver, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, swarm.Address, error) // GetGrantees returns the list of grantees for the given publisher. // The list is accessible only by the publisher. - GetGrantees(ctx context.Context, getter storage.Getter, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) + GetGrantees(ctx context.Context, ls file.LoadSaver, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) } type Controller interface { GranteeManager // DownloadHandler decrypts the encryptedRef using the lookupkey based on the history and timestamp. - DownloadHandler(ctx context.Context, getter storage.Getter, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) + DownloadHandler(ctx context.Context, ls file.LoadSaver, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) // UploadHandler encrypts the reference and stores it in the history as the latest update. - UploadHandler(ctx context.Context, getter storage.Getter, putter storage.Putter, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) + UploadHandler(ctx context.Context, ls file.LoadSaver, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) io.Closer } @@ -43,13 +41,12 @@ var _ Controller = (*controller)(nil) func (c *controller) DownloadHandler( ctx context.Context, - getter storage.Getter, + ls file.LoadSaver, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64, ) (swarm.Address, error) { - ls := loadsave.NewReadonly(getter) history, err := NewHistoryReference(ls, historyRootHash) if err != nil { return swarm.ZeroAddress, err @@ -68,13 +65,11 @@ func (c *controller) DownloadHandler( func (c *controller) UploadHandler( ctx context.Context, - getter storage.Getter, - putter storage.Putter, + ls file.LoadSaver, refrefence swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, ) (swarm.Address, swarm.Address, swarm.Address, error) { - ls := loadsave.New(getter, putter, requestPipelineFactory(ctx, putter, false, redundancy.NONE)) historyRef := historyRootHash var ( storage kvs.KeyValueStore @@ -134,8 +129,8 @@ func NewController(accessLogic ActLogic) Controller { func (c *controller) HandleGrantees( ctx context.Context, - getter storage.Getter, - putter storage.Putter, + ls file.LoadSaver, + gls file.LoadSaver, encryptedglref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, @@ -147,8 +142,6 @@ func (c *controller) HandleGrantees( h History act kvs.KeyValueStore granteeref swarm.Address - ls = loadsave.New(getter, putter, requestPipelineFactory(ctx, putter, false, redundancy.NONE)) - gls = loadsave.New(getter, putter, requestPipelineFactory(ctx, putter, granteeListEncrypt, redundancy.NONE)) ) if !historyref.IsZero() { h, err = NewHistoryReference(ls, historyref) @@ -250,8 +243,7 @@ func (c *controller) HandleGrantees( return glref, eglref, href, actref, nil } -func (c *controller) GetGrantees(ctx context.Context, getter storage.Getter, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) { - ls := loadsave.NewReadonly(getter) +func (c *controller) GetGrantees(ctx context.Context, ls file.LoadSaver, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) { granteeRef, err := c.decryptRefForPublisher(publisher, encryptedglref) if err != nil { return nil, err diff --git a/pkg/dynamicaccess/controller_test.go b/pkg/dynamicaccess/controller_test.go index 5298ac8e7e7..0f6950dcf20 100644 --- a/pkg/dynamicaccess/controller_test.go +++ b/pkg/dynamicaccess/controller_test.go @@ -10,6 +10,8 @@ import ( "github.com/ethersphere/bee/v2/pkg/dynamicaccess" encryption "github.com/ethersphere/bee/v2/pkg/encryption" "github.com/ethersphere/bee/v2/pkg/file" + "github.com/ethersphere/bee/v2/pkg/file/loadsave" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" "github.com/ethersphere/bee/v2/pkg/kvs" "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/stretchr/testify/assert" @@ -52,9 +54,9 @@ func TestController_NewUpload(t *testing.T) { al := dynamicaccess.NewLogic(diffieHellman) c := dynamicaccess.NewController(al) ref := swarm.RandAddress(t) - _, hRef, encRef, err := c.UploadHandler(ctx, mockStorer.ChunkStore(), mockStorer.Cache(), ref, &publisher.PublicKey, swarm.ZeroAddress) - ls := createLs() + _, hRef, encRef, err := c.UploadHandler(ctx, ls, ref, &publisher.PublicKey, swarm.ZeroAddress) + h, err := dynamicaccess.NewHistoryReference(ls, hRef) entry, err := h.Lookup(ctx, time.Now().Unix()) actRef := entry.Reference() @@ -82,7 +84,7 @@ func TestController_PublisherDownload(t *testing.T) { encRef, err := al.EncryptRef(ctx, act, &publisher.PublicKey, ref) assert.NoError(t, err) - dref, err := c.DownloadHandler(ctx, mockStorer.ChunkStore(), encRef, &publisher.PublicKey, href, time.Now().Unix()) + dref, err := c.DownloadHandler(ctx, ls, encRef, &publisher.PublicKey, href, time.Now().Unix()) assert.NoError(t, err) assert.Equal(t, ref, dref) } @@ -108,7 +110,7 @@ func TestController_GranteeDownload(t *testing.T) { encRef, err := publisherAL.EncryptRef(ctx, act, &publisher.PublicKey, ref) assert.NoError(t, err) - dref, err := c.DownloadHandler(ctx, mockStorer.ChunkStore(), encRef, &publisher.PublicKey, href, ts) + dref, err := c.DownloadHandler(ctx, ls, encRef, &publisher.PublicKey, href, ts) assert.NoError(t, err) assert.Equal(t, ref, dref) } @@ -121,8 +123,7 @@ func TestController_HandleGrantees(t *testing.T) { keys, _ := al.Session.Key(&publisher.PublicKey, [][]byte{{1}}) refCipher := encryption.New(keys[0], 0, uint32(0), sha3.NewLegacyKeccak256) ls := createLs() - getter := mockStorer.ChunkStore() - putter := mockStorer.Cache() + gls := loadsave.New(mockStorer.ChunkStore(), mockStorer.Cache(), requestPipelineFactory(context.Background(), mockStorer.Cache(), true, redundancy.NONE)) c := dynamicaccess.NewController(al) href, _ := getHistoryFixture(ctx, ls, al, &publisher.PublicKey) @@ -131,38 +132,38 @@ func TestController_HandleGrantees(t *testing.T) { t.Run("add to new list", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, _, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + granteeRef, _, _, _, err := c.HandleGrantees(ctx, ls, ls, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) - gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + gl, err := dynamicaccess.NewGranteeListReference(ls, granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 1) }) t.Run("add to existing list", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, eglref, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, eglref, _, _, err := c.HandleGrantees(ctx, ls, gls, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) - gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + gl, err := dynamicaccess.NewGranteeListReference(ls, granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 1) addList = []*ecdsa.PublicKey{&getPrivKey(0).PublicKey} - granteeRef, _, _, _, err = c.HandleGrantees(ctx, getter, putter, eglref, href, &publisher.PublicKey, addList, nil) - gl, err = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + granteeRef, _, _, _, err = c.HandleGrantees(ctx, ls, ls, eglref, href, &publisher.PublicKey, addList, nil) + gl, err = dynamicaccess.NewGranteeListReference(ls, granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 2) }) t.Run("add and revoke", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} revokeList := []*ecdsa.PublicKey{&grantee1.PublicKey} - gl, _ := dynamicaccess.NewGranteeList(createLs()) + gl, _ := dynamicaccess.NewGranteeList(ls) gl.Add([]*ecdsa.PublicKey{&publisher.PublicKey, &grantee1.PublicKey}) granteeRef, err := gl.Save(ctx) eglref, _ := refCipher.Encrypt(granteeRef.Bytes()) - granteeRef, _, _, _, err = c.HandleGrantees(ctx, getter, putter, swarm.NewAddress(eglref), href, &publisher.PublicKey, addList, revokeList) - gl, err = dynamicaccess.NewGranteeListReference(createLs(), granteeRef) + granteeRef, _, _, _, err = c.HandleGrantees(ctx, ls, gls, swarm.NewAddress(eglref), href, &publisher.PublicKey, addList, revokeList) + gl, err = dynamicaccess.NewGranteeListReference(ls, granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 2) @@ -170,8 +171,8 @@ func TestController_HandleGrantees(t *testing.T) { t.Run("add twice", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey, &grantee.PublicKey} - granteeRef, eglref, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) - granteeRef, _, _, _, err = c.HandleGrantees(ctx, getter, putter, eglref, href, &publisher.PublicKey, addList, nil) + granteeRef, eglref, _, _, err := c.HandleGrantees(ctx, ls, gls, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, _, _, _, err = c.HandleGrantees(ctx, ls, ls, eglref, href, &publisher.PublicKey, addList, nil) gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) @@ -179,7 +180,7 @@ func TestController_HandleGrantees(t *testing.T) { }) t.Run("revoke non-existing", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, _, _, _, err := c.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, _, _, _, err := c.HandleGrantees(ctx, ls, ls, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) @@ -197,16 +198,15 @@ func TestController_GetGrantees(t *testing.T) { al1 := dynamicaccess.NewLogic(diffieHellman1) al2 := dynamicaccess.NewLogic(diffieHellman2) ls := createLs() - getter := mockStorer.ChunkStore() - putter := mockStorer.Cache() + gls := loadsave.New(mockStorer.ChunkStore(), mockStorer.Cache(), requestPipelineFactory(context.Background(), mockStorer.Cache(), true, redundancy.NONE)) c1 := dynamicaccess.NewController(al1) c2 := dynamicaccess.NewController(al2) t.Run("get by publisher", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, eglRef, _, _, err := c1.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + granteeRef, eglRef, _, _, err := c1.HandleGrantees(ctx, ls, gls, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) - grantees, err := c1.GetGrantees(ctx, getter, &publisher.PublicKey, eglRef) + grantees, err := c1.GetGrantees(ctx, ls, &publisher.PublicKey, eglRef) assert.NoError(t, err) assert.True(t, reflect.DeepEqual(grantees, addList)) @@ -215,8 +215,8 @@ func TestController_GetGrantees(t *testing.T) { }) t.Run("get by non-publisher", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - _, eglRef, _, _, err := c1.HandleGrantees(ctx, getter, putter, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) - grantees, err := c2.GetGrantees(ctx, getter, &publisher.PublicKey, eglRef) + _, eglRef, _, _, err := c1.HandleGrantees(ctx, ls, gls, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + grantees, err := c2.GetGrantees(ctx, ls, &publisher.PublicKey, eglRef) assert.Error(t, err) assert.Nil(t, grantees) }) diff --git a/pkg/dynamicaccess/mock/controller.go b/pkg/dynamicaccess/mock/controller.go index 10f4c2823a1..09cacb65145 100644 --- a/pkg/dynamicaccess/mock/controller.go +++ b/pkg/dynamicaccess/mock/controller.go @@ -78,7 +78,7 @@ func WithPublisher(ref string) Option { }) } -func (m *mockDacService) DownloadHandler(ctx context.Context, getter storage.Getter, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) { +func (m *mockDacService) DownloadHandler(ctx context.Context, ls file.LoadSaver, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) { if m.acceptAll { return swarm.ParseHexAddress("36e6c1bbdfee6ac21485d5f970479fd1df458d36df9ef4e8179708ed46da557f") } @@ -101,7 +101,7 @@ func (m *mockDacService) DownloadHandler(ctx context.Context, getter storage.Get return m.refMap[encryptedRef.String()], nil } -func (m *mockDacService) UploadHandler(ctx context.Context, getter storage.Getter, putter storage.Putter, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) { +func (m *mockDacService) UploadHandler(ctx context.Context, ls file.LoadSaver, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) { historyRef, _ := swarm.ParseHexAddress("67bdf80a9bbea8eca9c8480e43fdceb485d2d74d5708e45144b8c4adacd13d9c") kvsRef, _ := swarm.ParseHexAddress("3339613565613837623134316665343461613630396333333237656364383934") if m.acceptAll { @@ -140,7 +140,7 @@ func (m *mockDacService) Close() error { return nil } -func (m *mockDacService) HandleGrantees(ctx context.Context, getter storage.Getter, putter storage.Putter, granteeref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, swarm.Address, error) { +func (m *mockDacService) HandleGrantees(ctx context.Context, ls file.LoadSaver, gls file.LoadSaver, encryptedglref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList []*ecdsa.PublicKey, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, swarm.Address, error) { historyRef, _ := swarm.ParseHexAddress("67bdf80a9bbea8eca9c8480e43fdceb485d2d74d5708e45144b8c4adacd13d9c") glRef, _ := swarm.ParseHexAddress("3339613565613837623134316665343461613630396333333237656364383934") eglRef, _ := swarm.ParseHexAddress("fc4e9fe978991257b897d987bc4ff13058b66ef45a53189a0b4fe84bb3346396") @@ -148,7 +148,7 @@ func (m *mockDacService) HandleGrantees(ctx context.Context, getter storage.Gett return glRef, eglRef, historyRef, actref, nil } -func (m *mockDacService) GetGrantees(ctx context.Context, getter storage.Getter, publisher *ecdsa.PublicKey, granteeref swarm.Address) ([]*ecdsa.PublicKey, error) { +func (m *mockDacService) GetGrantees(ctx context.Context, ls file.LoadSaver, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) { if m.publisher == "" { return nil, fmt.Errorf("granteelist not found") } From f7b7560fe469e20edfe9e9889275d7c1c7f9f021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Ujv=C3=A1ri?= Date: Tue, 7 May 2024 12:44:57 +0200 Subject: [PATCH 10/19] FIX: re-init history so that it can be saved; only add publisher if histroy is zero --- pkg/api/dynamicaccess_test.go | 2 +- pkg/dynamicaccess/controller.go | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pkg/api/dynamicaccess_test.go b/pkg/api/dynamicaccess_test.go index 4b503f9ffcb..a2d0cd6e4b2 100644 --- a/pkg/api/dynamicaccess_test.go +++ b/pkg/api/dynamicaccess_test.go @@ -845,7 +845,7 @@ func TestDacGrantees(t *testing.T) { }) t.Run("get-grantees-unauthorized", func(t *testing.T) { - jsonhttptest.Request(t, client, http.MethodGet, "/grantee/fc4e9fe978991257b897d987bc4ff13058b66ef45a53189a0b4fe84bb3346396", http.StatusUnauthorized, + jsonhttptest.Request(t, client, http.MethodGet, "/grantee/fc4e9fe978991257b897d987bc4ff13058b66ef45a53189a0b4fe84bb3346396", http.StatusNotFound, jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ Message: "granteelist not found", Code: http.StatusNotFound, diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index 3764ea2d31f..da725511169 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -199,9 +199,11 @@ func (c *controller) HandleGrantees( var granteesToAdd []*ecdsa.PublicKey // generate new access key and new act if len(removeList) != 0 || encryptedglref.IsZero() { - err = c.accessLogic.AddPublisher(ctx, act, publisher) - if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + if historyref.IsZero() { + err = c.accessLogic.AddPublisher(ctx, act, publisher) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + } } granteesToAdd = gl.Get() } else { @@ -229,6 +231,13 @@ func (c *controller) HandleGrantees( if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } + // need to re-initialize history, because Lookup loads the forks causing the manifest save to skip the root node + if !historyref.IsZero() { + h, err = NewHistoryReference(ls, historyref) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + } + } mtdt := map[string]string{"encryptedglref": eglref.String()} err = h.Add(ctx, actref, nil, &mtdt) From 6fa9c4e31064f3f85f88f0edab2edba6ef9afb22 Mon Sep 17 00:00:00 2001 From: Kexort Date: Tue, 7 May 2024 14:08:22 +0200 Subject: [PATCH 11/19] make act timestamp optional --- pkg/api/dynamicaccess.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index 2ba951c5d67..b69a984fa92 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -8,6 +8,7 @@ import ( "errors" "io" "net/http" + "time" "github.com/btcsuite/btcd/btcec/v2" "github.com/ethersphere/bee/v2/pkg/crypto" @@ -89,18 +90,23 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { } // Try to download the file wihtout decryption, if the act headers are not present - if headers.Publisher == nil || headers.Timestamp == nil || headers.HistoryAddress == nil { + if headers.Publisher == nil || headers.HistoryAddress == nil { h.ServeHTTP(w, r) return } + timestamp := time.Now().Unix() + if headers.Timestamp == nil { + timestamp = *headers.Timestamp + } + cache := true if headers.Cache != nil { cache = *headers.Cache } ctx := r.Context() ls := loadsave.NewReadonly(s.storer.Download(cache)) - reference, err := s.dac.DownloadHandler(ctx, ls, paths.Address, headers.Publisher, *headers.HistoryAddress, *headers.Timestamp) + reference, err := s.dac.DownloadHandler(ctx, ls, paths.Address, headers.Publisher, *headers.HistoryAddress, timestamp) if err != nil { jsonhttp.InternalServerError(w, errActDownload) return From 933c5f855b626a51d9a3fa0976de990ff962c86b Mon Sep 17 00:00:00 2001 From: Kexort Date: Tue, 7 May 2024 14:08:45 +0200 Subject: [PATCH 12/19] fix revoke grantees --- pkg/dynamicaccess/controller.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index da725511169..ad5ab1f1c8f 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -162,10 +162,6 @@ func (c *controller) HandleGrantees( if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } - act, err = kvs.New(ls) - if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err - } } var gl GranteeList @@ -185,9 +181,11 @@ func (c *controller) HandleGrantees( return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } } - err = gl.Add(addList) - if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + if len(addList) != 0 { + err = gl.Add(addList) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + } } if len(removeList) != 0 { err = gl.Remove(removeList) @@ -199,11 +197,13 @@ func (c *controller) HandleGrantees( var granteesToAdd []*ecdsa.PublicKey // generate new access key and new act if len(removeList) != 0 || encryptedglref.IsZero() { - if historyref.IsZero() { - err = c.accessLogic.AddPublisher(ctx, act, publisher) - if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err - } + act, err = kvs.New(ls) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + } + err = c.accessLogic.AddPublisher(ctx, act, publisher) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } granteesToAdd = gl.Get() } else { From 7960a49e4d7e95fcf33443ac1d6fba5699a8fc77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Ujv=C3=A1ri?= Date: Tue, 7 May 2024 16:43:50 +0200 Subject: [PATCH 13/19] Fix: Act timestamp header nil check; Uploadhandler UT --- pkg/api/dynamicaccess.go | 2 +- pkg/dynamicaccess/controller.go | 8 +++-- pkg/dynamicaccess/controller_test.go | 51 ++++++++++++++++++++++------ 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index b69a984fa92..bbf3abbc69e 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -96,7 +96,7 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { } timestamp := time.Now().Unix() - if headers.Timestamp == nil { + if headers.Timestamp != nil { timestamp = *headers.Timestamp } diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index ad5ab1f1c8f..5deb69c9ffe 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -201,9 +201,11 @@ func (c *controller) HandleGrantees( if err != nil { return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err } - err = c.accessLogic.AddPublisher(ctx, act, publisher) - if err != nil { - return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + if historyref.IsZero() { + err = c.accessLogic.AddPublisher(ctx, act, publisher) + if err != nil { + return swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, swarm.ZeroAddress, err + } } granteesToAdd = gl.Get() } else { diff --git a/pkg/dynamicaccess/controller_test.go b/pkg/dynamicaccess/controller_test.go index 0f6950dcf20..2b3065899a1 100644 --- a/pkg/dynamicaccess/controller_test.go +++ b/pkg/dynamicaccess/controller_test.go @@ -47,25 +47,52 @@ func getHistoryFixture(ctx context.Context, ls file.LoadSaver, al dynamicaccess. return h.Store(ctx) } -func TestController_NewUpload(t *testing.T) { +func TestController_UploadHandler(t *testing.T) { ctx := context.Background() publisher := getPrivKey(0) diffieHellman := dynamicaccess.NewDefaultSession(publisher) al := dynamicaccess.NewLogic(diffieHellman) c := dynamicaccess.NewController(al) - ref := swarm.RandAddress(t) ls := createLs() - _, hRef, encRef, err := c.UploadHandler(ctx, ls, ref, &publisher.PublicKey, swarm.ZeroAddress) - h, err := dynamicaccess.NewHistoryReference(ls, hRef) - entry, err := h.Lookup(ctx, time.Now().Unix()) - actRef := entry.Reference() - act, err := kvs.NewReference(ls, actRef) - expRef, err := al.EncryptRef(ctx, act, &publisher.PublicKey, ref) + t.Run("New upload", func(t *testing.T) { + ref := swarm.RandAddress(t) + _, hRef, encRef, err := c.UploadHandler(ctx, ls, ref, &publisher.PublicKey, swarm.ZeroAddress) + assert.NoError(t, err) - assert.NoError(t, err) - assert.Equal(t, encRef, expRef) - assert.NotEqual(t, hRef, swarm.ZeroAddress) + h, _ := dynamicaccess.NewHistoryReference(ls, hRef) + entry, _ := h.Lookup(ctx, time.Now().Unix()) + actRef := entry.Reference() + act, _ := kvs.NewReference(ls, actRef) + expRef, err := al.EncryptRef(ctx, act, &publisher.PublicKey, ref) + + assert.NoError(t, err) + assert.Equal(t, encRef, expRef) + assert.NotEqual(t, hRef, swarm.ZeroAddress) + }) + + t.Run("Upload to same history", func(t *testing.T) { + ref := swarm.RandAddress(t) + _, hRef1, _, err := c.UploadHandler(ctx, ls, ref, &publisher.PublicKey, swarm.ZeroAddress) + assert.NoError(t, err) + _, hRef2, encRef, err := c.UploadHandler(ctx, ls, ref, &publisher.PublicKey, hRef1) + assert.NoError(t, err) + h, err := dynamicaccess.NewHistoryReference(ls, hRef2) + assert.NoError(t, err) + hRef2, err = h.Store(ctx) + assert.NoError(t, err) + assert.True(t, hRef1.Equal(hRef2)) + + h, _ = dynamicaccess.NewHistoryReference(ls, hRef2) + entry, _ := h.Lookup(ctx, time.Now().Unix()) + actRef := entry.Reference() + act, _ := kvs.NewReference(ls, actRef) + expRef, err := al.EncryptRef(ctx, act, &publisher.PublicKey, ref) + + assert.NoError(t, err) + assert.Equal(t, encRef, expRef) + assert.NotEqual(t, hRef2, swarm.ZeroAddress) + }) } func TestController_PublisherDownload(t *testing.T) { @@ -133,6 +160,7 @@ func TestController_HandleGrantees(t *testing.T) { t.Run("add to new list", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} granteeRef, _, _, _, err := c.HandleGrantees(ctx, ls, ls, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + assert.NoError(t, err) gl, err := dynamicaccess.NewGranteeListReference(ls, granteeRef) @@ -142,6 +170,7 @@ func TestController_HandleGrantees(t *testing.T) { t.Run("add to existing list", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} granteeRef, eglref, _, _, err := c.HandleGrantees(ctx, ls, gls, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + assert.NoError(t, err) gl, err := dynamicaccess.NewGranteeListReference(ls, granteeRef) From 2ec09770215818809910e3ad75fc48b2a67dd653 Mon Sep 17 00:00:00 2001 From: kopi-solarpunk Date: Mon, 13 May 2024 11:12:19 +0200 Subject: [PATCH 14/19] refactor: start refactoring for now linter rules --- pkg/api/accounting_test.go | 1 - pkg/api/api_test.go | 8 +++--- pkg/api/balances_test.go | 1 - pkg/api/bytes_test.go | 1 - pkg/api/bzz.go | 9 +++---- pkg/api/bzz_test.go | 3 --- pkg/api/chequebook.go | 1 - pkg/api/chequebook_test.go | 6 ----- pkg/api/chunk.go | 3 +-- pkg/api/chunk_test.go | 9 +++---- pkg/api/cors_test.go | 4 +-- pkg/api/debugstorage_test.go | 1 - pkg/api/dirs.go | 1 - pkg/api/dirs_test.go | 7 ++--- pkg/api/dynamicaccess.go | 8 +++--- pkg/api/dynamicaccess_test.go | 37 +++++++++++--------------- pkg/api/export_test.go | 5 ++-- pkg/api/feed_test.go | 1 - pkg/api/metrics.go | 1 - pkg/api/pin_test.go | 2 -- pkg/api/postage_test.go | 5 +--- pkg/api/probe.go | 1 - pkg/api/pss_test.go | 11 ++++---- pkg/api/settlements_test.go | 1 - pkg/api/soc_test.go | 1 - pkg/api/staking.go | 2 +- pkg/api/staking_test.go | 3 +-- pkg/api/status_test.go | 1 + pkg/api/stewardship.go | 3 +-- pkg/api/tag_test.go | 8 +++--- pkg/api/version.go | 6 +++-- pkg/api/wallet.go | 3 +-- pkg/api/welcome_message_test.go | 3 ++- pkg/dynamicaccess/accesslogic.go | 35 +++++++++++++----------- pkg/dynamicaccess/accesslogic_test.go | 3 --- pkg/dynamicaccess/controller.go | 23 ++++++++-------- pkg/dynamicaccess/controller_test.go | 6 +++-- pkg/dynamicaccess/grantee.go | 16 +++++++---- pkg/dynamicaccess/history.go | 38 +++++++++++++++------------ pkg/dynamicaccess/mock/session.go | 1 - pkg/dynamicaccess/session.go | 24 ++++++++++------- pkg/dynamicaccess/session_test.go | 2 +- pkg/kvs/kvs_test.go | 1 - pkg/kvs/mock/kvs.go | 3 ++- pkg/manifest/mantaray/node.go | 7 +---- 45 files changed, 146 insertions(+), 170 deletions(-) diff --git a/pkg/api/accounting_test.go b/pkg/api/accounting_test.go index 7a807aa811e..6664e48108d 100644 --- a/pkg/api/accounting_test.go +++ b/pkg/api/accounting_test.go @@ -101,7 +101,6 @@ func TestAccountingInfo(t *testing.T) { if !reflect.DeepEqual(got, expected) { t.Errorf("got accounting: %v, expected: %v", got, expected) } - } func TestAccountingInfoError(t *testing.T) { diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index 2c93a20353b..e7f2f92b9c4 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -190,7 +190,7 @@ func newTestServer(t *testing.T, o testServerOptions) (*http.Client, *websocket. erc20 := erc20mock.New(o.Erc20Opts...) backend := backendmock.New(o.BackendOpts...) - var extraOpts = api.ExtraOptions{ + extraOpts := api.ExtraOptions{ TopologyDriver: topologyDriver, Accounting: acc, Pseudosettle: recipient, @@ -344,7 +344,7 @@ func TestParseName(t *testing.T) { const bzzHash = "89c17d0d8018a19057314aa035e61c9d23c47581a61dd3a79a7839692c617e4d" log := log.Noop - var errInvalidNameOrAddress = errors.New("invalid name or bzz address") + errInvalidNameOrAddress := errors.New("invalid name or bzz address") testCases := []struct { desc string @@ -531,9 +531,7 @@ func TestPostageHeaderError(t *testing.T) { func TestOptions(t *testing.T) { t.Parallel() - var ( - client, _, _, _ = newTestServer(t, testServerOptions{}) - ) + client, _, _, _ := newTestServer(t, testServerOptions{}) for _, tc := range []struct { endpoint string expectedMethods string // expectedMethods contains HTTP methods like GET, POST, HEAD, PATCH, DELETE, OPTIONS. These are in alphabetical sorted order diff --git a/pkg/api/balances_test.go b/pkg/api/balances_test.go index 174196d253a..da3ea24cb73 100644 --- a/pkg/api/balances_test.go +++ b/pkg/api/balances_test.go @@ -216,7 +216,6 @@ func TestConsumedBalances(t *testing.T) { if !equalBalances(got, expected) { t.Errorf("got balances: %v, expected: %v", got, expected) } - } func TestConsumedError(t *testing.T) { diff --git a/pkg/api/bytes_test.go b/pkg/api/bytes_test.go index e2acc99a9d6..88ed06d2f5b 100644 --- a/pkg/api/bytes_test.go +++ b/pkg/api/bytes_test.go @@ -271,7 +271,6 @@ func TestBytesInvalidStamp(t *testing.T) { jsonhttptest.WithRequestBody(bytes.NewReader(content)), ) }) - } func TestBytesUploadHandlerInvalidInputs(t *testing.T) { diff --git a/pkg/api/bzz.go b/pkg/api/bzz.go index b49bc89baea..3d85b81973a 100644 --- a/pkg/api/bzz.go +++ b/pkg/api/bzz.go @@ -16,10 +16,6 @@ import ( "strings" "time" - "github.com/opentracing/opentracing-go" - "github.com/opentracing/opentracing-go/ext" - olog "github.com/opentracing/opentracing-go/log" - "github.com/ethereum/go-ethereum/common" "github.com/ethersphere/bee/v2/pkg/feeds" "github.com/ethersphere/bee/v2/pkg/file/joiner" @@ -37,6 +33,9 @@ import ( "github.com/ethersphere/bee/v2/pkg/tracing" "github.com/ethersphere/langos" "github.com/gorilla/mux" + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + olog "github.com/opentracing/opentracing-go/log" ) // The size of buffer used for prefetching content with Langos when not using erasure coding @@ -394,7 +393,7 @@ FETCH: // go on normally. if !feedDereferenced { if l, err := s.manifestFeed(ctx, m); err == nil { - //we have a feed manifest here + // we have a feed manifest here ch, cur, _, err := l.At(ctx, time.Now().Unix(), 0) if err != nil { logger.Debug("bzz download: feed lookup failed", "error", err) diff --git a/pkg/api/bzz_test.go b/pkg/api/bzz_test.go index 7d1e1b27bfe..236768a2bf6 100644 --- a/pkg/api/bzz_test.go +++ b/pkg/api/bzz_test.go @@ -934,7 +934,6 @@ func TestInvalidBzzParams(t *testing.T) { jsonhttptest.WithRequestBody(tr), jsonhttptest.WithRequestHeader(api.ContentTypeHeader, api.ContentTypeTar), ) - }) t.Run("batch exists", func(t *testing.T) { @@ -962,7 +961,6 @@ func TestInvalidBzzParams(t *testing.T) { jsonhttptest.WithRequestBody(tr), jsonhttptest.WithRequestHeader(api.ContentTypeHeader, api.ContentTypeTar), ) - }) t.Run("batch not found", func(t *testing.T) { @@ -1057,7 +1055,6 @@ func TestInvalidBzzParams(t *testing.T) { address := "f30c0aa7e9e2a0ef4c9b1b750ebfeaeb7c7c24da700bb089da19a46e3677824b" jsonhttptest.Request(t, client, http.MethodGet, fmt.Sprintf("/bzz/%s/", address), http.StatusNotFound) }) - } // TestDirectUploadBzz tests that the direct upload endpoint give correct error message in dev mode diff --git a/pkg/api/chequebook.go b/pkg/api/chequebook.go index 33cd75d9767..b2b30e2443e 100644 --- a/pkg/api/chequebook.go +++ b/pkg/api/chequebook.go @@ -15,7 +15,6 @@ import ( "github.com/ethersphere/bee/v2/pkg/postage/postagecontract" "github.com/ethersphere/bee/v2/pkg/settlement/swap" "github.com/ethersphere/bee/v2/pkg/settlement/swap/chequebook" - "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/gorilla/mux" ) diff --git a/pkg/api/chequebook_test.go b/pkg/api/chequebook_test.go index b9b9cbdef32..d1415b994fc 100644 --- a/pkg/api/chequebook_test.go +++ b/pkg/api/chequebook_test.go @@ -21,7 +21,6 @@ import ( "github.com/ethersphere/bee/v2/pkg/settlement/swap/chequebook" "github.com/ethersphere/bee/v2/pkg/settlement/swap/chequebook/mock" swapmock "github.com/ethersphere/bee/v2/pkg/settlement/swap/mock" - "github.com/ethersphere/bee/v2/pkg/swarm" ) @@ -427,7 +426,6 @@ func TestChequebookLastCheques(t *testing.T) { if !LastChequesEqual(got, expected) { t.Fatalf("Got: \n %+v \n\n Expected: \n %+v \n\n", got, expected) } - } func TestChequebookLastChequesPeer(t *testing.T) { @@ -442,7 +440,6 @@ func TestChequebookLastChequesPeer(t *testing.T) { sig := make([]byte, 65) lastSentChequeFunc := func(swarm.Address) (*chequebook.SignedCheque, error) { - sig := make([]byte, 65) lastSentCheque := &chequebook.SignedCheque{ @@ -458,7 +455,6 @@ func TestChequebookLastChequesPeer(t *testing.T) { } lastReceivedChequeFunc := func(swarm.Address) (*chequebook.SignedCheque, error) { - lastReceivedCheque := &chequebook.SignedCheque{ Cheque: chequebook.Cheque{ Beneficiary: beneficiary0, @@ -498,7 +494,6 @@ func TestChequebookLastChequesPeer(t *testing.T) { if !reflect.DeepEqual(got, expected) { t.Fatalf("Got: \n %+v \n\n Expected: \n %+v \n\n", got, expected) } - } func TestChequebookCashout(t *testing.T) { @@ -780,7 +775,6 @@ func Test_chequebookLastPeerHandler_invalidInputs(t *testing.T) { } func LastChequesEqual(a, b *api.ChequebookLastChequesResponse) bool { - var state bool for akeys := range a.LastCheques { diff --git a/pkg/api/chunk.go b/pkg/api/chunk.go index 21daa0d0f57..5acc9b42df3 100644 --- a/pkg/api/chunk.go +++ b/pkg/api/chunk.go @@ -13,10 +13,9 @@ import ( "strconv" "github.com/ethersphere/bee/v2/pkg/cac" - "github.com/ethersphere/bee/v2/pkg/soc" - "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/postage" + "github.com/ethersphere/bee/v2/pkg/soc" "github.com/ethersphere/bee/v2/pkg/storage" "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/gorilla/mux" diff --git a/pkg/api/chunk_test.go b/pkg/api/chunk_test.go index c0e1fe9de9c..66f8dfae74a 100644 --- a/pkg/api/chunk_test.go +++ b/pkg/api/chunk_test.go @@ -13,16 +13,15 @@ import ( "testing" "time" + "github.com/ethersphere/bee/v2/pkg/api" + "github.com/ethersphere/bee/v2/pkg/jsonhttp" + "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" "github.com/ethersphere/bee/v2/pkg/log" mockbatchstore "github.com/ethersphere/bee/v2/pkg/postage/batchstore/mock" mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" "github.com/ethersphere/bee/v2/pkg/spinlock" - mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" - - "github.com/ethersphere/bee/v2/pkg/api" - "github.com/ethersphere/bee/v2/pkg/jsonhttp" - "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" testingc "github.com/ethersphere/bee/v2/pkg/storage/testing" + mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/ethersphere/bee/v2/pkg/swarm" ) diff --git a/pkg/api/cors_test.go b/pkg/api/cors_test.go index 73c3b343414..08c817c0389 100644 --- a/pkg/api/cors_test.go +++ b/pkg/api/cors_test.go @@ -116,7 +116,6 @@ func TestCORSHeaders(t *testing.T) { } }) } - } // TestCors tests whether CORs work correctly with OPTIONS method @@ -135,7 +134,8 @@ func TestCors(t *testing.T) { { endpoint: "bzz", expectedMethods: "POST", - }, { + }, + { endpoint: "bzz/0101011", expectedMethods: "GET, HEAD", }, diff --git a/pkg/api/debugstorage_test.go b/pkg/api/debugstorage_test.go index bb12a5585fd..0a7c655fdec 100644 --- a/pkg/api/debugstorage_test.go +++ b/pkg/api/debugstorage_test.go @@ -43,5 +43,4 @@ func TestDebugStorage(t *testing.T) { jsonhttptest.WithExpectedJSONResponse(want), ) }) - } diff --git a/pkg/api/dirs.go b/pkg/api/dirs.go index f187fbde01e..ce2b679c076 100644 --- a/pkg/api/dirs.go +++ b/pkg/api/dirs.go @@ -141,7 +141,6 @@ func storeDir( errorFilename string, rLevel redundancy.Level, ) (swarm.Address, error) { - logger := tracing.NewLoggerWithTraceID(ctx, log) loggerV1 := logger.V(1).Build() diff --git a/pkg/api/dirs_test.go b/pkg/api/dirs_test.go index d49f0d281d6..306e561c864 100644 --- a/pkg/api/dirs_test.go +++ b/pkg/api/dirs_test.go @@ -371,7 +371,6 @@ func TestDirs(t *testing.T) { // check error document validateAltPath(t, "_non_existent_file_path_", errorDocumentPath) } - } t.Run(tc.name, func(t *testing.T) { t.Run("tar_upload", func(t *testing.T) { @@ -542,7 +541,7 @@ func tarFiles(t *testing.T, files []f) *bytes.Buffer { // create tar header and write it hdr := &tar.Header{ Name: filePath, - Mode: 0600, + Mode: 0o600, Size: int64(len(file.data)), } if err := tw.WriteHeader(hdr); err != nil { @@ -571,7 +570,7 @@ func tarEmptyDir(t *testing.T) *bytes.Buffer { hdr := &tar.Header{ Name: "empty/", - Mode: 0600, + Mode: 0o600, } if err := tw.WriteHeader(hdr); err != nil { @@ -604,11 +603,9 @@ func multipartFiles(t *testing.T, files []f) (*bytes.Buffer, string) { contentType := file.header.Get(api.ContentTypeHeader) if contentType != "" { hdr.Set(api.ContentTypeHeader, contentType) - } if len(file.data) > 0 { hdr.Set(api.ContentLengthHeader, strconv.Itoa(len(file.data))) - } part, err := mw.CreatePart(hdr) if err != nil { diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index bbf3abbc69e..5a6295696bc 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "encoding/json" "errors" + "fmt" "io" "net/http" "time" @@ -114,7 +115,6 @@ func (s *Service) actDecryptionHandler() func(h http.Handler) http.Handler { h.ServeHTTP(w, r.WithContext(setAddressInContext(ctx, reference))) }) } - } // actEncryptionHandler is a middleware that encrypts the given address using the publisher's public key @@ -133,7 +133,7 @@ func (s *Service) actEncryptionHandler( if err != nil { logger.Debug("act failed to encrypt reference", "error", err) logger.Error(nil, "act failed to encrypt reference") - return swarm.ZeroAddress, err + return swarm.ZeroAddress, fmt.Errorf("act failed to encrypt reference: %w", err) } // only need to upload history and kvs if a new history is created, // meaning that the publsher uploaded to the history for the first time @@ -142,13 +142,13 @@ func (s *Service) actEncryptionHandler( if err != nil { logger.Debug("done split keyvaluestore failed", "error", err) logger.Error(nil, "done split keyvaluestore failed") - return swarm.ZeroAddress, err + return swarm.ZeroAddress, fmt.Errorf("done split keyvaluestore failed: %w", err) } err = putter.Done(historyReference) if err != nil { logger.Debug("done split history failed", "error", err) logger.Error(nil, "done split history failed") - return swarm.ZeroAddress, err + return swarm.ZeroAddress, fmt.Errorf("done split history failed: %w", err) } } diff --git a/pkg/api/dynamicaccess_test.go b/pkg/api/dynamicaccess_test.go index a2d0cd6e4b2..96891e13578 100644 --- a/pkg/api/dynamicaccess_test.go +++ b/pkg/api/dynamicaccess_test.go @@ -221,10 +221,11 @@ func TestDacEachEndpointWithAct(t *testing.T) { } } -// nolint:paralleltest,tparallel // TestDacWithoutActHeader [negative tests]: // 1. upload w/ "Swarm-Act" header then try to dowload w/o the header. // 2. upload w/o "Swarm-Act" header then try to dowload w/ the header. +// +//nolint:paralleltest,tparallel func TestDacWithoutAct(t *testing.T) { t.Parallel() var ( @@ -321,8 +322,9 @@ func TestDacWithoutAct(t *testing.T) { }) } -// nolint:paralleltest,tparallel // TestDacInvalidPath [negative test]: Expect Bad request when the path address is invalid. +// +//nolint:paralleltest,tparallel func TestDacInvalidPath(t *testing.T) { t.Parallel() var ( @@ -345,9 +347,7 @@ func TestDacInvalidPath(t *testing.T) { PublicKey: pk.PublicKey, Dac: mockdac.New(), }) - var ( - encryptedRef = "asd" - ) + encryptedRef := "asd" jsonhttptest.Request(t, client, http.MethodGet, fileDownloadResource(encryptedRef), http.StatusBadRequest, jsonhttptest.WithRequestHeader(api.SwarmActTimestampHeader, strconv.FormatInt(now, 10)), @@ -361,7 +361,8 @@ func TestDacInvalidPath(t *testing.T) { Field: "address", Error: api.HexInvalidByteError('s').Error(), }, - }}), + }, + }), jsonhttptest.WithRequestHeader(api.ContentTypeHeader, "text/html; charset=utf-8"), ) }) @@ -516,9 +517,7 @@ func TestDacHistory(t *testing.T) { PublicKey: pk.PublicKey, Dac: mockdac.New(), }) - var ( - testfile = "testfile1" - ) + testfile := "testfile1" jsonhttptest.Request(t, client, http.MethodPost, fileUploadResource+"?name="+fileName, http.StatusInternalServerError, jsonhttptest.WithRequestHeader(api.SwarmActHeader, "true"), @@ -541,9 +540,7 @@ func TestDacHistory(t *testing.T) { PublicKey: pk.PublicKey, Dac: mockdac.New(mockdac.WithHistory(h, fixtureHref.String())), }) - var ( - encryptedRef = "a5df670544eaea29e61b19d8739faa4573b19e4426e58a173e51ed0b5e7e2ade" - ) + encryptedRef := "a5df670544eaea29e61b19d8739faa4573b19e4426e58a173e51ed0b5e7e2ade" jsonhttptest.Request(t, client, http.MethodGet, fileDownloadResource(encryptedRef), http.StatusNotFound, jsonhttptest.WithRequestHeader(api.SwarmActTimestampHeader, strconv.FormatInt(now, 10)), @@ -619,9 +616,7 @@ func TestDacTimestamp(t *testing.T) { }) t.Run("download-w/o-timestamp", func(t *testing.T) { - var ( - encryptedRef = "a5df670544eaea29e61b19d8739faa4573b19e4426e58a173e51ed0b5e7e2ade" - ) + encryptedRef := "a5df670544eaea29e61b19d8739faa4573b19e4426e58a173e51ed0b5e7e2ade" client, _, _, _ := newTestServer(t, testServerOptions{ Storer: storerMock, Logger: logger, @@ -754,7 +749,8 @@ func TestDacPublisher(t *testing.T) { Field: "Swarm-Act-Publisher", Error: "malformed public key: invalid length: 32", }, - }}), + }, + }), jsonhttptest.WithRequestHeader(api.ContentTypeHeader, "text/html; charset=utf-8"), ) }) @@ -785,9 +781,7 @@ func TestDacPublisher(t *testing.T) { }) t.Run("download-w/o-publisher", func(t *testing.T) { - var ( - encryptedRef = "a5df670544eaea29e61b19d8739faa4573b19e4426e58a173e51ed0b5e7e2ade" - ) + encryptedRef := "a5df670544eaea29e61b19d8739faa4573b19e4426e58a173e51ed0b5e7e2ade" client, _, _, _ := newTestServer(t, testServerOptions{ Storer: storerMock, Logger: logger, @@ -862,7 +856,8 @@ func TestDacGrantees(t *testing.T) { Field: "address", Error: api.HexInvalidByteError('s').Error(), }, - }}), + }, + }), ) }) t.Run("add-revoke-grantees", func(t *testing.T) { @@ -904,8 +899,8 @@ func TestDacGrantees(t *testing.T) { jsonhttptest.WithRequestHeader(api.SwarmPostageBatchIdHeader, batchOkStr), jsonhttptest.WithJSONRequestBody(body), ) - }) + t.Run("create-granteelist", func(t *testing.T) { body := api.GranteesPostRequest{ GranteeList: []string{ diff --git a/pkg/api/export_test.go b/pkg/api/export_test.go index fd78ae6974f..916992815a6 100644 --- a/pkg/api/export_test.go +++ b/pkg/api/export_test.go @@ -29,9 +29,7 @@ var ( EmptyDir = errEmptyDir ) -var ( - ContentTypeTar = contentTypeTar -) +var ContentTypeTar = contentTypeTar var ( ErrNoResolver = errNoResolver @@ -139,6 +137,7 @@ type HexInvalidByteError = hexInvalidByteError func MapStructure(input, output interface{}, hooks map[string]func(v string) (string, error)) error { return mapStructure(input, output, hooks) } + func NewParseError(entry, value string, cause error) error { return newParseError(entry, value, cause) } diff --git a/pkg/api/feed_test.go b/pkg/api/feed_test.go index a35b9ce3423..7235ad93636 100644 --- a/pkg/api/feed_test.go +++ b/pkg/api/feed_test.go @@ -161,7 +161,6 @@ func TestFeed_Post(t *testing.T) { ) }) }) - } // TestDirectUploadFeed tests that the direct upload endpoint give correct error message in dev mode diff --git a/pkg/api/metrics.go b/pkg/api/metrics.go index 7635468f4e3..6064595a0ed 100644 --- a/pkg/api/metrics.go +++ b/pkg/api/metrics.go @@ -68,7 +68,6 @@ func newMetrics() metrics { } func toFileSizeBucket(bytes int64) int64 { - for _, s := range fileSizeBucketsKBytes { if (s * bytesInKB) >= bytes { return s * bytesInKB diff --git a/pkg/api/pin_test.go b/pkg/api/pin_test.go index a85c34a9594..00925135efd 100644 --- a/pkg/api/pin_test.go +++ b/pkg/api/pin_test.go @@ -136,7 +136,6 @@ func TestPinHandlers(t *testing.T) { rootHash = strings.Trim(header.Get(api.ETagHeader), "\"") checkPinHandlers(t, client, rootHash, false) }) - } func TestPinHandlersInvalidInputs(t *testing.T) { @@ -194,7 +193,6 @@ func TestPinHandlersInvalidInputs(t *testing.T) { const pinRef = "620fcd78c7ce54da2d1b7cc2274a02e190cbe8fecbc3bd244690ab6517ce8f39" func TestIntegrityHandler(t *testing.T) { - t.Parallel() t.Run("ok", func(t *testing.T) { diff --git a/pkg/api/postage_test.go b/pkg/api/postage_test.go index ebf808c1c7a..56cfb606078 100644 --- a/pkg/api/postage_test.go +++ b/pkg/api/postage_test.go @@ -17,7 +17,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethersphere/bee/v2/pkg/api" "github.com/ethersphere/bee/v2/pkg/bigint" "github.com/ethersphere/bee/v2/pkg/jsonhttp" @@ -373,7 +372,6 @@ func TestPostageGetBuckets(t *testing.T) { jsonhttptest.Request(t, tsNotFound, http.MethodGet, "/stamps/"+batchOkStr+"/buckets", http.StatusNotFound) }) - } func TestReserveState(t *testing.T) { @@ -406,6 +404,7 @@ func TestReserveState(t *testing.T) { ) }) } + func TestChainState(t *testing.T) { t.Parallel() @@ -433,7 +432,6 @@ func TestChainState(t *testing.T) { }), ) }) - } func TestPostageTopUpStamp(t *testing.T) { @@ -703,7 +701,6 @@ func TestPostageDiluteStamp(t *testing.T) { TxHash: txHash.String(), }), ) - }) } diff --git a/pkg/api/probe.go b/pkg/api/probe.go index 8521d050f8d..5d0be5c1d69 100644 --- a/pkg/api/probe.go +++ b/pkg/api/probe.go @@ -58,7 +58,6 @@ func (p *Probe) Healthy() ProbeStatus { return ProbeStatusNOK } return p.healthy.get() - } // SetHealthy updates the value of the healthy status. diff --git a/pkg/api/pss_test.go b/pkg/api/pss_test.go index 6624e6d8d21..c97f6fcf40d 100644 --- a/pkg/api/pss_test.go +++ b/pkg/api/pss_test.go @@ -88,7 +88,6 @@ func TestPssWebsocketSingleHandlerDeregister(t *testing.T) { ) err := cl.SetReadDeadline(time.Now().Add(longTimeout)) - if err != nil { t.Fatal(err) } @@ -446,10 +445,12 @@ func TestPssPostHandlerInvalidInputs(t *testing.T) { } } -type pssSendFn func(context.Context, pss.Targets, swarm.Chunk) error -type mpss struct { - f pssSendFn -} +type ( + pssSendFn func(context.Context, pss.Targets, swarm.Chunk) error + mpss struct { + f pssSendFn + } +) func newMockPss(f pssSendFn) *mpss { return &mpss{f} diff --git a/pkg/api/settlements_test.go b/pkg/api/settlements_test.go index 86f2e2e42e1..8096df88c9d 100644 --- a/pkg/api/settlements_test.go +++ b/pkg/api/settlements_test.go @@ -79,7 +79,6 @@ func TestSettlements(t *testing.T) { if !equalSettlements(got, expected) { t.Errorf("got settlements: %+v, expected: %+v", got, expected) } - } func TestSettlementsError(t *testing.T) { diff --git a/pkg/api/soc_test.go b/pkg/api/soc_test.go index 79e72ffb603..3f92e6684ff 100644 --- a/pkg/api/soc_test.go +++ b/pkg/api/soc_test.go @@ -122,7 +122,6 @@ func TestSOC(t *testing.T) { }) t.Run("ok batch", func(t *testing.T) { - s := testingsoc.GenerateMockSOC(t, testData) hexbatch := hex.EncodeToString(batchOk) client, _, _, chanStorer := newTestServer(t, testServerOptions{ diff --git a/pkg/api/staking.go b/pkg/api/staking.go index 5ca5b06d409..df588471ce3 100644 --- a/pkg/api/staking.go +++ b/pkg/api/staking.go @@ -10,7 +10,6 @@ import ( "net/http" "github.com/ethersphere/bee/v2/pkg/bigint" - "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/storageincentives/staking" "github.com/gorilla/mux" @@ -33,6 +32,7 @@ func (s *Service) stakingAccessHandler(h http.Handler) http.Handler { type getStakeResponse struct { StakedAmount *bigint.BigInt `json:"stakedAmount"` } + type stakeDepositResponse struct { TxHash string `json:"txhash"` } diff --git a/pkg/api/staking_test.go b/pkg/api/staking_test.go index e6f4d0b2296..d7d569a8de8 100644 --- a/pkg/api/staking_test.go +++ b/pkg/api/staking_test.go @@ -12,9 +12,8 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" - "github.com/ethersphere/bee/v2/pkg/bigint" - "github.com/ethersphere/bee/v2/pkg/api" + "github.com/ethersphere/bee/v2/pkg/bigint" "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" "github.com/ethersphere/bee/v2/pkg/sctx" diff --git a/pkg/api/status_test.go b/pkg/api/status_test.go index cc2c568abf4..991806dbb86 100644 --- a/pkg/api/status_test.go +++ b/pkg/api/status_test.go @@ -102,6 +102,7 @@ func (m *topologyPeersIterNoopMock) EachConnectedPeer(_ topology.EachPeerFunc, _ func (m *topologyPeersIterNoopMock) EachConnectedPeerRev(_ topology.EachPeerFunc, _ topology.Select) error { return nil } + func (m *topologyPeersIterNoopMock) IsReachable() bool { return true } diff --git a/pkg/api/stewardship.go b/pkg/api/stewardship.go index 99d330f78cc..bf4d93f0356 100644 --- a/pkg/api/stewardship.go +++ b/pkg/api/stewardship.go @@ -8,11 +8,10 @@ import ( "errors" "net/http" + "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/postage" storage "github.com/ethersphere/bee/v2/pkg/storage" "github.com/ethersphere/bee/v2/pkg/swarm" - - "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/gorilla/mux" ) diff --git a/pkg/api/tag_test.go b/pkg/api/tag_test.go index d3b8edeb4dc..4536883c888 100644 --- a/pkg/api/tag_test.go +++ b/pkg/api/tag_test.go @@ -11,21 +11,19 @@ import ( "strconv" "testing" + "github.com/ethersphere/bee/v2/pkg/api" + "github.com/ethersphere/bee/v2/pkg/jsonhttp" + "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/google/go-cmp/cmp" - - "github.com/ethersphere/bee/v2/pkg/api" - "github.com/ethersphere/bee/v2/pkg/jsonhttp" - "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" ) func tagsWithIdResource(id uint64) string { return fmt.Sprintf("/tags/%d", id) } // nolint:paralleltest func TestTags(t *testing.T) { - var ( tagsResource = "/tags" storerMock = mockstorer.New() diff --git a/pkg/api/version.go b/pkg/api/version.go index b9bf36154c4..6838f773ca8 100644 --- a/pkg/api/version.go +++ b/pkg/api/version.go @@ -5,5 +5,7 @@ package api // Version is set in the build process. -var Version = "0.0.0" -var DebugVersion = "0.0.0" +var ( + Version = "0.0.0" + DebugVersion = "0.0.0" +) diff --git a/pkg/api/wallet.go b/pkg/api/wallet.go index 5cdd0de087d..75674e1f48b 100644 --- a/pkg/api/wallet.go +++ b/pkg/api/wallet.go @@ -7,9 +7,8 @@ package api import ( "math/big" "net/http" - "strings" - "slices" + "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethersphere/bee/v2/pkg/bigint" diff --git a/pkg/api/welcome_message_test.go b/pkg/api/welcome_message_test.go index 39d7c19a039..faca74f8c9f 100644 --- a/pkg/api/welcome_message_test.go +++ b/pkg/api/welcome_message_test.go @@ -26,7 +26,8 @@ func TestGetWelcomeMessage(t *testing.T) { DebugAPI: true, P2P: mock.New(mock.WithGetWelcomeMessageFunc(func() string { return DefaultTestWelcomeMessage - }))}) + })), + }) jsonhttptest.Request(t, srv, http.MethodGet, "/welcome-message", http.StatusOK, jsonhttptest.WithExpectedJSONResponse(api.WelcomeMessageResponse{ diff --git a/pkg/dynamicaccess/accesslogic.go b/pkg/dynamicaccess/accesslogic.go index 33b8ba819ba..2d369ca951d 100644 --- a/pkg/dynamicaccess/accesslogic.go +++ b/pkg/dynamicaccess/accesslogic.go @@ -3,6 +3,7 @@ package dynamicaccess import ( "context" "crypto/ecdsa" + "fmt" encryption "github.com/ethersphere/bee/v2/pkg/encryption" "github.com/ethersphere/bee/v2/pkg/kvs" @@ -10,11 +11,14 @@ import ( "golang.org/x/crypto/sha3" ) -var hashFunc = sha3.NewLegacyKeccak256 -var oneByteArray = []byte{1} -var zeroByteArray = []byte{0} +//nolint:gochecknoglobals +var ( + hashFunc = sha3.NewLegacyKeccak256 + oneByteArray = []byte{1} + zeroByteArray = []byte{0} +) -// Read-only interface for the ACT +// Decryptor is a read-only interface for the ACT. type Decryptor interface { // DecryptRef will return a decrypted reference, for given encrypted reference and grantee DecryptRef(ctx context.Context, storage kvs.KeyValueStore, encryptedRef swarm.Address, publisher *ecdsa.PublicKey) (swarm.Address, error) @@ -22,13 +26,13 @@ type Decryptor interface { Session } -// Control interface for the ACT (does write operations) +// Control interface for the ACT (does write operations). type Control interface { // Embedding the Decryptor interface Decryptor - // Adds a new grantee to the ACT + // AddGrantee adds a new grantee to the ACT AddGrantee(ctx context.Context, storage kvs.KeyValueStore, publisherPubKey, granteePubKey *ecdsa.PublicKey, accessKey *encryption.Key) error - // Encrypts a Swarm reference for a given grantee + // EncryptRef encrypts a Swarm reference for a given grantee EncryptRef(ctx context.Context, storage kvs.KeyValueStore, grantee *ecdsa.PublicKey, ref swarm.Address) (swarm.Address, error) } @@ -38,14 +42,14 @@ type ActLogic struct { var _ Control = (*ActLogic)(nil) -// Adds a new publisher to an empty act +// AddPublisher adds a new publisher to an empty act. func (al ActLogic) AddPublisher(ctx context.Context, storage kvs.KeyValueStore, publisher *ecdsa.PublicKey) error { accessKey := encryption.GenerateRandomKey(encryption.KeyLength) return al.AddGrantee(ctx, storage, publisher, publisher, &accessKey) } -// Encrypts a SWARM reference for a publisher +// EncryptRef encrypts a SWARM reference for a publisher. func (al ActLogic) EncryptRef(ctx context.Context, storage kvs.KeyValueStore, publisherPubKey *ecdsa.PublicKey, ref swarm.Address) (swarm.Address, error) { accessKey, err := al.getAccessKey(ctx, storage, publisherPubKey) if err != nil { @@ -54,13 +58,13 @@ func (al ActLogic) EncryptRef(ctx context.Context, storage kvs.KeyValueStore, pu refCipher := encryption.New(accessKey, 0, uint32(0), hashFunc) encryptedRef, err := refCipher.Encrypt(ref.Bytes()) if err != nil { - return swarm.ZeroAddress, err + return swarm.ZeroAddress, fmt.Errorf("failed to encrypt reference: %w", err) } return swarm.NewAddress(encryptedRef), nil } -// Adds a new grantee to the ACT +// AddGrantee adds a new grantee to the ACT. func (al ActLogic) AddGrantee(ctx context.Context, storage kvs.KeyValueStore, publisherPubKey, granteePubKey *ecdsa.PublicKey, accessKeyPointer *encryption.Key) error { var ( accessKey encryption.Key @@ -91,14 +95,15 @@ func (al ActLogic) AddGrantee(ctx context.Context, storage kvs.KeyValueStore, pu cipher := encryption.New(encryption.Key(accessKeyDecryptionKey), 0, uint32(0), hashFunc) granteeEncryptedAccessKey, err := cipher.Encrypt(accessKey) if err != nil { - return err + return fmt.Errorf("failed to encrypt access key: %w", err) } // Add the new encrypted access key for the Act + //nolint:wrapcheck return storage.Put(ctx, lookupKey, granteeEncryptedAccessKey) } -// Will return the access key for a publisher (public key) +// Will return the access key for a publisher (public key). func (al *ActLogic) getAccessKey(ctx context.Context, storage kvs.KeyValueStore, publisherPubKey *ecdsa.PublicKey) ([]byte, error) { keys, err := al.getKeys(publisherPubKey) if err != nil { @@ -110,7 +115,7 @@ func (al *ActLogic) getAccessKey(ctx context.Context, storage kvs.KeyValueStore, accessKeyDecryptionCipher := encryption.New(encryption.Key(publisherAKDecryptionKey), 0, uint32(0), hashFunc) encryptedAK, err := storage.Get(ctx, publisherLookupKey) if err != nil { - return nil, err + return nil, fmt.Errorf("failed go get value from KVS: %w", err) } return accessKeyDecryptionCipher.Decrypt(encryptedAK) @@ -133,7 +138,7 @@ func (al ActLogic) DecryptRef(ctx context.Context, storage kvs.KeyValueStore, en // Lookup encrypted access key from the ACT manifest encryptedAccessKey, err := storage.Get(ctx, lookupKey) if err != nil { - return swarm.ZeroAddress, err + return swarm.ZeroAddress, fmt.Errorf("failed to get access key from KVS: %w", err) } // Decrypt access key diff --git a/pkg/dynamicaccess/accesslogic_test.go b/pkg/dynamicaccess/accesslogic_test.go index 66a3f8930e3..3df2f28a197 100644 --- a/pkg/dynamicaccess/accesslogic_test.go +++ b/pkg/dynamicaccess/accesslogic_test.go @@ -79,7 +79,6 @@ func TestDecryptRef_Success(t *testing.T) { } if expectedRef.Compare(acutalRef) != 0 { - t.Errorf("Get gave back wrong Swarm reference!") } } @@ -123,7 +122,6 @@ func TestDecryptRefWithGrantee_Success(t *testing.T) { } if expectedRef.Compare(acutalRef) != 0 { - t.Errorf("Get gave back wrong Swarm reference!") } } @@ -184,7 +182,6 @@ func TestAddPublisher(t *testing.T) { } func TestAddNewGranteeToContent(t *testing.T) { - id0 := getPrivKey(0) id1 := getPrivKey(1) id2 := getPrivKey(2) diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index 5deb69c9ffe..8eb8fb4b275 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -33,13 +33,13 @@ type Controller interface { io.Closer } -type controller struct { +type ControllerStruct struct { accessLogic ActLogic } -var _ Controller = (*controller)(nil) +var _ Controller = (*ControllerStruct)(nil) -func (c *controller) DownloadHandler( +func (c *ControllerStruct) DownloadHandler( ctx context.Context, ls file.LoadSaver, encryptedRef swarm.Address, @@ -63,7 +63,7 @@ func (c *controller) DownloadHandler( return c.accessLogic.DecryptRef(ctx, act, encryptedRef, publisher) } -func (c *controller) UploadHandler( +func (c *ControllerStruct) UploadHandler( ctx context.Context, ls file.LoadSaver, refrefence swarm.Address, @@ -76,6 +76,7 @@ func (c *controller) UploadHandler( actRef swarm.Address ) now := time.Now().Unix() + //nolint:nestif if historyRef.IsZero() { history, err := NewHistory(ls) if err != nil { @@ -121,13 +122,13 @@ func (c *controller) UploadHandler( return actRef, historyRef, encryptedRef, err } -func NewController(accessLogic ActLogic) Controller { - return &controller{ +func NewController(accessLogic ActLogic) *ControllerStruct { + return &ControllerStruct{ accessLogic: accessLogic, } } -func (c *controller) HandleGrantees( +func (c *ControllerStruct) HandleGrantees( ctx context.Context, ls file.LoadSaver, gls file.LoadSaver, @@ -254,7 +255,7 @@ func (c *controller) HandleGrantees( return glref, eglref, href, actref, nil } -func (c *controller) GetGrantees(ctx context.Context, ls file.LoadSaver, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) { +func (c *ControllerStruct) GetGrantees(ctx context.Context, ls file.LoadSaver, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) { granteeRef, err := c.decryptRefForPublisher(publisher, encryptedglref) if err != nil { return nil, err @@ -266,7 +267,7 @@ func (c *controller) GetGrantees(ctx context.Context, ls file.LoadSaver, publish return gl.Get(), nil } -func (c *controller) encryptRefForPublisher(publisherPubKey *ecdsa.PublicKey, ref swarm.Address) (swarm.Address, error) { +func (c *ControllerStruct) encryptRefForPublisher(publisherPubKey *ecdsa.PublicKey, ref swarm.Address) (swarm.Address, error) { keys, err := c.accessLogic.Session.Key(publisherPubKey, [][]byte{oneByteArray}) if err != nil { return swarm.ZeroAddress, err @@ -280,7 +281,7 @@ func (c *controller) encryptRefForPublisher(publisherPubKey *ecdsa.PublicKey, re return swarm.NewAddress(encryptedRef), nil } -func (c *controller) decryptRefForPublisher(publisherPubKey *ecdsa.PublicKey, encryptedRef swarm.Address) (swarm.Address, error) { +func (c *ControllerStruct) decryptRefForPublisher(publisherPubKey *ecdsa.PublicKey, encryptedRef swarm.Address) (swarm.Address, error) { keys, err := c.accessLogic.Session.Key(publisherPubKey, [][]byte{oneByteArray}) if err != nil { return swarm.ZeroAddress, err @@ -301,6 +302,6 @@ func requestPipelineFactory(ctx context.Context, s storage.Putter, encrypt bool, } // TODO: what to do in close ? -func (s *controller) Close() error { +func (s *ControllerStruct) Close() error { return nil } diff --git a/pkg/dynamicaccess/controller_test.go b/pkg/dynamicaccess/controller_test.go index 2b3065899a1..58087171892 100644 --- a/pkg/dynamicaccess/controller_test.go +++ b/pkg/dynamicaccess/controller_test.go @@ -15,9 +15,11 @@ import ( "github.com/ethersphere/bee/v2/pkg/kvs" "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "golang.org/x/crypto/sha3" ) +//nolint:errcheck,gosec,wrapcheck func getHistoryFixture(ctx context.Context, ls file.LoadSaver, al dynamicaccess.ActLogic, publisher *ecdsa.PublicKey) (swarm.Address, error) { h, err := dynamicaccess.NewHistory(ls) if err != nil { @@ -67,14 +69,14 @@ func TestController_UploadHandler(t *testing.T) { expRef, err := al.EncryptRef(ctx, act, &publisher.PublicKey, ref) assert.NoError(t, err) - assert.Equal(t, encRef, expRef) + assert.Equal(t, expRef, encRef) assert.NotEqual(t, hRef, swarm.ZeroAddress) }) t.Run("Upload to same history", func(t *testing.T) { ref := swarm.RandAddress(t) _, hRef1, _, err := c.UploadHandler(ctx, ls, ref, &publisher.PublicKey, swarm.ZeroAddress) - assert.NoError(t, err) + require.NoError(t, err) // If assert fails, the test continues, if require fails, the test stops we need to consider which to use _, hRef2, encRef, err := c.UploadHandler(ctx, ls, ref, &publisher.PublicKey, hRef1) assert.NoError(t, err) h, err := dynamicaccess.NewHistoryReference(ls, hRef2) diff --git a/pkg/dynamicaccess/grantee.go b/pkg/dynamicaccess/grantee.go index 02cd8099021..2cb77236b44 100644 --- a/pkg/dynamicaccess/grantee.go +++ b/pkg/dynamicaccess/grantee.go @@ -4,6 +4,7 @@ import ( "context" "crypto/ecdsa" "crypto/elliptic" + "errors" "fmt" "github.com/btcsuite/btcd/btcec/v2" @@ -76,13 +77,18 @@ func (g *GranteeListStruct) Save(ctx context.Context) (swarm.Address, error) { return swarm.NewAddress(refBytes), nil } +var ( + ErrNothingToRemove = errors.New("nothing to remove") + ErrNoGranteeFound = errors.New("no grantee found") +) + func (g *GranteeListStruct) Remove(keysToRemove []*ecdsa.PublicKey) error { if len(keysToRemove) == 0 { - return fmt.Errorf("nothing to remove") + return ErrNothingToRemove } if len(g.grantees) == 0 { - return fmt.Errorf("no grantee found") + return ErrNoGranteeFound } grantees := g.grantees @@ -99,17 +105,17 @@ func (g *GranteeListStruct) Remove(keysToRemove []*ecdsa.PublicKey) error { return nil } -func NewGranteeList(ls file.LoadSaver) (GranteeList, error) { +func NewGranteeList(ls file.LoadSaver) (*GranteeListStruct, error) { // Why is the error necessary? return &GranteeListStruct{ grantees: []*ecdsa.PublicKey{}, loadSave: ls, }, nil } -func NewGranteeListReference(ls file.LoadSaver, reference swarm.Address) (GranteeList, error) { +func NewGranteeListReference(ls file.LoadSaver, reference swarm.Address) (*GranteeListStruct, error) { data, err := ls.Load(context.Background(), reference.Bytes()) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to load reference, %w", err) } grantees := deserialize(data) diff --git a/pkg/dynamicaccess/history.go b/pkg/dynamicaccess/history.go index 25193adf886..7543007ad0c 100644 --- a/pkg/dynamicaccess/history.go +++ b/pkg/dynamicaccess/history.go @@ -20,44 +20,47 @@ type History interface { Store(ctx context.Context) (swarm.Address, error) } -var _ History = (*history)(nil) +var _ History = (*HistoryStruct)(nil) -var ErrEndIteration = errors.New("end iteration") +var ( + ErrEndIteration = errors.New("end iteration") + ErrUnexpectedType = errors.New("unexpected type") +) -type history struct { +type HistoryStruct struct { manifest *manifest.MantarayManifest ls file.LoadSaver } -func NewHistory(ls file.LoadSaver) (History, error) { +func NewHistory(ls file.LoadSaver) (*HistoryStruct, error) { m, err := manifest.NewDefaultManifest(ls, false) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to create default manifest: %w", err) } mm, ok := m.(*manifest.MantarayManifest) if !ok { - return nil, fmt.Errorf("expected MantarayManifest, got %T", m) + return nil, fmt.Errorf("%w: expected MantarayManifest, got %T", ErrUnexpectedType, m) } - return &history{manifest: mm, ls: ls}, nil + return &HistoryStruct{manifest: mm, ls: ls}, nil } -func NewHistoryReference(ls file.LoadSaver, ref swarm.Address) (History, error) { +func NewHistoryReference(ls file.LoadSaver, ref swarm.Address) (*HistoryStruct, error) { m, err := manifest.NewDefaultManifestReference(ref, ls) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to create default manifest: %w", err) } mm, ok := m.(*manifest.MantarayManifest) if !ok { - return nil, fmt.Errorf("expected MantarayManifest, got %T", m) + return nil, fmt.Errorf("%w: expected MantarayManifest, got %T", ErrUnexpectedType, m) } - return &history{manifest: mm, ls: ls}, nil + return &HistoryStruct{manifest: mm, ls: ls}, nil } -func (h *history) Add(ctx context.Context, ref swarm.Address, timestamp *int64, metadata *map[string]string) error { +func (h *HistoryStruct) Add(ctx context.Context, ref swarm.Address, timestamp *int64, metadata *map[string]string) error { mtdt := map[string]string{} if metadata != nil { mtdt = *metadata @@ -74,10 +77,12 @@ func (h *history) Add(ctx context.Context, ref swarm.Address, timestamp *int64, return h.manifest.Add(ctx, key, manifest.NewEntry(ref, mtdt)) } +var ErrInvalidTimestamp = errors.New("invalid timestamp") + // Lookup finds the entry for a path or returns error if not found -func (h *history) Lookup(ctx context.Context, timestamp int64) (manifest.Entry, error) { +func (h *HistoryStruct) Lookup(ctx context.Context, timestamp int64) (manifest.Entry, error) { if timestamp <= 0 { - return manifest.NewEntry(swarm.ZeroAddress, map[string]string{}), errors.New("invalid timestamp") + return manifest.NewEntry(swarm.ZeroAddress, map[string]string{}), ErrInvalidTimestamp } reversedTimestamp := math.MaxInt64 - timestamp @@ -93,7 +98,7 @@ func (h *history) Lookup(ctx context.Context, timestamp int64) (manifest.Entry, return manifest.NewEntry(swarm.ZeroAddress, map[string]string{}), nil } -func (h *history) lookupNode(ctx context.Context, searchedTimestamp int64) (*mantaray.Node, error) { +func (h *HistoryStruct) lookupNode(ctx context.Context, searchedTimestamp int64) (*mantaray.Node, error) { // before node's timestamp is the closest one that is less than or equal to the searched timestamp // for instance: 2030, 2020, 1994 -> search for 2021 -> before is 2020 var beforeNode *mantaray.Node @@ -134,12 +139,11 @@ func (h *history) lookupNode(ctx context.Context, searchedTimestamp int64) (*man } if afterNode != nil { return afterNode, nil - } return nil, nil } -func (h *history) Store(ctx context.Context) (swarm.Address, error) { +func (h *HistoryStruct) Store(ctx context.Context) (swarm.Address, error) { return h.manifest.Store(ctx) } diff --git a/pkg/dynamicaccess/mock/session.go b/pkg/dynamicaccess/mock/session.go index 9613aacedfa..f6a398e75a9 100644 --- a/pkg/dynamicaccess/mock/session.go +++ b/pkg/dynamicaccess/mock/session.go @@ -17,7 +17,6 @@ func (s *SessionMock) Key(publicKey *ecdsa.PublicKey, nonces [][]byte) ([][]byte return nil, nil } return s.KeyFunc(publicKey, nonces) - } func NewSessionMock(key *ecdsa.PrivateKey) *SessionMock { diff --git a/pkg/dynamicaccess/session.go b/pkg/dynamicaccess/session.go index 0b58c1aa3dd..76491daad46 100644 --- a/pkg/dynamicaccess/session.go +++ b/pkg/dynamicaccess/session.go @@ -3,6 +3,7 @@ package dynamicaccess import ( "crypto/ecdsa" "errors" + "fmt" "github.com/ethersphere/bee/v2/pkg/crypto" "github.com/ethersphere/bee/v2/pkg/keystore" @@ -14,19 +15,24 @@ type Session interface { Key(publicKey *ecdsa.PublicKey, nonces [][]byte) ([][]byte, error) } -var _ Session = (*session)(nil) +var _ Session = (*SessionStruct)(nil) -type session struct { +type SessionStruct struct { key *ecdsa.PrivateKey } -func (s *session) Key(publicKey *ecdsa.PublicKey, nonces [][]byte) ([][]byte, error) { +var ( + ErrInvalidPublicKey = errors.New("invalid public key") + ErrSecretKeyInfinity = errors.New("shared secret is point at infinity") +) + +func (s *SessionStruct) Key(publicKey *ecdsa.PublicKey, nonces [][]byte) ([][]byte, error) { if publicKey == nil { - return nil, errors.New("invalid public key") + return nil, ErrInvalidPublicKey } x, y := publicKey.Curve.ScalarMult(publicKey.X, publicKey.Y, s.key.D.Bytes()) if x == nil || y == nil { - return nil, errors.New("shared secret is point at infinity") + return nil, ErrSecretKeyInfinity } if len(nonces) == 0 { @@ -37,7 +43,7 @@ func (s *session) Key(publicKey *ecdsa.PublicKey, nonces [][]byte) ([][]byte, er for _, nonce := range nonces { key, err := crypto.LegacyKeccak256(append(x.Bytes(), nonce...)) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get Keccak256 hash: %w", err) } keys = append(keys, key) } @@ -45,13 +51,13 @@ func (s *session) Key(publicKey *ecdsa.PublicKey, nonces [][]byte) ([][]byte, er return keys, nil } -func NewDefaultSession(key *ecdsa.PrivateKey) Session { - return &session{ +func NewDefaultSession(key *ecdsa.PrivateKey) *SessionStruct { + return &SessionStruct{ key: key, } } // Currently implemented only in mock/session.go -func NewFromKeystore(ks keystore.Service, tag, password string) Session { +func NewFromKeystore(keystore.Service, string, string) Session { return nil } diff --git a/pkg/dynamicaccess/session_test.go b/pkg/dynamicaccess/session_test.go index 493b998a805..382a79190d5 100644 --- a/pkg/dynamicaccess/session_test.go +++ b/pkg/dynamicaccess/session_test.go @@ -14,7 +14,7 @@ import ( memkeystore "github.com/ethersphere/bee/v2/pkg/keystore/mem" ) -func mockKeyFunc(publicKey *ecdsa.PublicKey, nonces [][]byte) ([][]byte, error) { +func mockKeyFunc(*ecdsa.PublicKey, [][]byte) ([][]byte, error) { return [][]byte{{1}}, nil } diff --git a/pkg/kvs/kvs_test.go b/pkg/kvs/kvs_test.go index 462e092d532..f542c86144b 100644 --- a/pkg/kvs/kvs_test.go +++ b/pkg/kvs/kvs_test.go @@ -37,7 +37,6 @@ func keyValuePair(t *testing.T) ([]byte, []byte) { } func TestKvs(t *testing.T) { - s, err := kvs.New(createLs()) assert.NoError(t, err) diff --git a/pkg/kvs/mock/kvs.go b/pkg/kvs/mock/kvs.go index 0203cc52ce6..767c8868dcf 100644 --- a/pkg/kvs/mock/kvs.go +++ b/pkg/kvs/mock/kvs.go @@ -24,7 +24,8 @@ func getInMemorySwarm() *single { defer lock.Unlock() if singleInMemorySwarm == nil { singleInMemorySwarm = &single{ - memoryMock: make(map[string]map[string][]byte)} + memoryMock: make(map[string]map[string][]byte), + } } } return singleInMemorySwarm diff --git a/pkg/manifest/mantaray/node.go b/pkg/manifest/mantaray/node.go index 5a59c010d52..9561c299db5 100644 --- a/pkg/manifest/mantaray/node.go +++ b/pkg/manifest/mantaray/node.go @@ -16,13 +16,8 @@ const ( ) var ( - ZeroObfuscationKey []byte -) - -// nolint:gochecknoinits -func init() { ZeroObfuscationKey = make([]byte, 32) -} +) // Error used when lookup path does not match var ( From 2098dc061590aa17fe96f6dd30478e8e111555b1 Mon Sep 17 00:00:00 2001 From: kopi-solarpunk Date: Mon, 13 May 2024 15:06:49 +0200 Subject: [PATCH 15/19] refactor: revert non ACT related files --- pkg/api/accounting_test.go | 1 + pkg/api/api_test.go | 8 +++++--- pkg/api/balances_test.go | 1 + pkg/api/bytes_test.go | 1 + pkg/api/bzz.go | 9 +++++---- pkg/api/bzz_test.go | 3 +++ pkg/api/chequebook.go | 1 + pkg/api/chequebook_test.go | 6 ++++++ pkg/api/chunk.go | 3 ++- pkg/api/chunk_test.go | 9 +++++---- pkg/api/cors_test.go | 4 ++-- pkg/api/debugstorage_test.go | 1 + pkg/api/dirs.go | 1 + pkg/api/dirs_test.go | 7 +++++-- pkg/api/export_test.go | 5 +++-- pkg/api/feed_test.go | 1 + pkg/api/metrics.go | 1 + pkg/api/pin_test.go | 2 ++ pkg/api/postage_test.go | 5 ++++- pkg/api/probe.go | 1 + pkg/api/pss_test.go | 11 +++++------ pkg/api/settlements_test.go | 1 + pkg/api/soc_test.go | 1 + pkg/api/staking.go | 2 +- pkg/api/staking_test.go | 3 ++- pkg/api/status_test.go | 1 - pkg/api/stewardship.go | 3 ++- pkg/api/tag_test.go | 8 +++++--- pkg/api/version.go | 6 ++---- pkg/api/wallet.go | 3 ++- pkg/api/welcome_message_test.go | 3 +-- 31 files changed, 73 insertions(+), 39 deletions(-) diff --git a/pkg/api/accounting_test.go b/pkg/api/accounting_test.go index 6664e48108d..7a807aa811e 100644 --- a/pkg/api/accounting_test.go +++ b/pkg/api/accounting_test.go @@ -101,6 +101,7 @@ func TestAccountingInfo(t *testing.T) { if !reflect.DeepEqual(got, expected) { t.Errorf("got accounting: %v, expected: %v", got, expected) } + } func TestAccountingInfoError(t *testing.T) { diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index e7f2f92b9c4..2c93a20353b 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -190,7 +190,7 @@ func newTestServer(t *testing.T, o testServerOptions) (*http.Client, *websocket. erc20 := erc20mock.New(o.Erc20Opts...) backend := backendmock.New(o.BackendOpts...) - extraOpts := api.ExtraOptions{ + var extraOpts = api.ExtraOptions{ TopologyDriver: topologyDriver, Accounting: acc, Pseudosettle: recipient, @@ -344,7 +344,7 @@ func TestParseName(t *testing.T) { const bzzHash = "89c17d0d8018a19057314aa035e61c9d23c47581a61dd3a79a7839692c617e4d" log := log.Noop - errInvalidNameOrAddress := errors.New("invalid name or bzz address") + var errInvalidNameOrAddress = errors.New("invalid name or bzz address") testCases := []struct { desc string @@ -531,7 +531,9 @@ func TestPostageHeaderError(t *testing.T) { func TestOptions(t *testing.T) { t.Parallel() - client, _, _, _ := newTestServer(t, testServerOptions{}) + var ( + client, _, _, _ = newTestServer(t, testServerOptions{}) + ) for _, tc := range []struct { endpoint string expectedMethods string // expectedMethods contains HTTP methods like GET, POST, HEAD, PATCH, DELETE, OPTIONS. These are in alphabetical sorted order diff --git a/pkg/api/balances_test.go b/pkg/api/balances_test.go index da3ea24cb73..174196d253a 100644 --- a/pkg/api/balances_test.go +++ b/pkg/api/balances_test.go @@ -216,6 +216,7 @@ func TestConsumedBalances(t *testing.T) { if !equalBalances(got, expected) { t.Errorf("got balances: %v, expected: %v", got, expected) } + } func TestConsumedError(t *testing.T) { diff --git a/pkg/api/bytes_test.go b/pkg/api/bytes_test.go index 88ed06d2f5b..e2acc99a9d6 100644 --- a/pkg/api/bytes_test.go +++ b/pkg/api/bytes_test.go @@ -271,6 +271,7 @@ func TestBytesInvalidStamp(t *testing.T) { jsonhttptest.WithRequestBody(bytes.NewReader(content)), ) }) + } func TestBytesUploadHandlerInvalidInputs(t *testing.T) { diff --git a/pkg/api/bzz.go b/pkg/api/bzz.go index 3d85b81973a..b49bc89baea 100644 --- a/pkg/api/bzz.go +++ b/pkg/api/bzz.go @@ -16,6 +16,10 @@ import ( "strings" "time" + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + olog "github.com/opentracing/opentracing-go/log" + "github.com/ethereum/go-ethereum/common" "github.com/ethersphere/bee/v2/pkg/feeds" "github.com/ethersphere/bee/v2/pkg/file/joiner" @@ -33,9 +37,6 @@ import ( "github.com/ethersphere/bee/v2/pkg/tracing" "github.com/ethersphere/langos" "github.com/gorilla/mux" - "github.com/opentracing/opentracing-go" - "github.com/opentracing/opentracing-go/ext" - olog "github.com/opentracing/opentracing-go/log" ) // The size of buffer used for prefetching content with Langos when not using erasure coding @@ -393,7 +394,7 @@ FETCH: // go on normally. if !feedDereferenced { if l, err := s.manifestFeed(ctx, m); err == nil { - // we have a feed manifest here + //we have a feed manifest here ch, cur, _, err := l.At(ctx, time.Now().Unix(), 0) if err != nil { logger.Debug("bzz download: feed lookup failed", "error", err) diff --git a/pkg/api/bzz_test.go b/pkg/api/bzz_test.go index 236768a2bf6..7d1e1b27bfe 100644 --- a/pkg/api/bzz_test.go +++ b/pkg/api/bzz_test.go @@ -934,6 +934,7 @@ func TestInvalidBzzParams(t *testing.T) { jsonhttptest.WithRequestBody(tr), jsonhttptest.WithRequestHeader(api.ContentTypeHeader, api.ContentTypeTar), ) + }) t.Run("batch exists", func(t *testing.T) { @@ -961,6 +962,7 @@ func TestInvalidBzzParams(t *testing.T) { jsonhttptest.WithRequestBody(tr), jsonhttptest.WithRequestHeader(api.ContentTypeHeader, api.ContentTypeTar), ) + }) t.Run("batch not found", func(t *testing.T) { @@ -1055,6 +1057,7 @@ func TestInvalidBzzParams(t *testing.T) { address := "f30c0aa7e9e2a0ef4c9b1b750ebfeaeb7c7c24da700bb089da19a46e3677824b" jsonhttptest.Request(t, client, http.MethodGet, fmt.Sprintf("/bzz/%s/", address), http.StatusNotFound) }) + } // TestDirectUploadBzz tests that the direct upload endpoint give correct error message in dev mode diff --git a/pkg/api/chequebook.go b/pkg/api/chequebook.go index b2b30e2443e..33cd75d9767 100644 --- a/pkg/api/chequebook.go +++ b/pkg/api/chequebook.go @@ -15,6 +15,7 @@ import ( "github.com/ethersphere/bee/v2/pkg/postage/postagecontract" "github.com/ethersphere/bee/v2/pkg/settlement/swap" "github.com/ethersphere/bee/v2/pkg/settlement/swap/chequebook" + "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/gorilla/mux" ) diff --git a/pkg/api/chequebook_test.go b/pkg/api/chequebook_test.go index d1415b994fc..b9b9cbdef32 100644 --- a/pkg/api/chequebook_test.go +++ b/pkg/api/chequebook_test.go @@ -21,6 +21,7 @@ import ( "github.com/ethersphere/bee/v2/pkg/settlement/swap/chequebook" "github.com/ethersphere/bee/v2/pkg/settlement/swap/chequebook/mock" swapmock "github.com/ethersphere/bee/v2/pkg/settlement/swap/mock" + "github.com/ethersphere/bee/v2/pkg/swarm" ) @@ -426,6 +427,7 @@ func TestChequebookLastCheques(t *testing.T) { if !LastChequesEqual(got, expected) { t.Fatalf("Got: \n %+v \n\n Expected: \n %+v \n\n", got, expected) } + } func TestChequebookLastChequesPeer(t *testing.T) { @@ -440,6 +442,7 @@ func TestChequebookLastChequesPeer(t *testing.T) { sig := make([]byte, 65) lastSentChequeFunc := func(swarm.Address) (*chequebook.SignedCheque, error) { + sig := make([]byte, 65) lastSentCheque := &chequebook.SignedCheque{ @@ -455,6 +458,7 @@ func TestChequebookLastChequesPeer(t *testing.T) { } lastReceivedChequeFunc := func(swarm.Address) (*chequebook.SignedCheque, error) { + lastReceivedCheque := &chequebook.SignedCheque{ Cheque: chequebook.Cheque{ Beneficiary: beneficiary0, @@ -494,6 +498,7 @@ func TestChequebookLastChequesPeer(t *testing.T) { if !reflect.DeepEqual(got, expected) { t.Fatalf("Got: \n %+v \n\n Expected: \n %+v \n\n", got, expected) } + } func TestChequebookCashout(t *testing.T) { @@ -775,6 +780,7 @@ func Test_chequebookLastPeerHandler_invalidInputs(t *testing.T) { } func LastChequesEqual(a, b *api.ChequebookLastChequesResponse) bool { + var state bool for akeys := range a.LastCheques { diff --git a/pkg/api/chunk.go b/pkg/api/chunk.go index 5acc9b42df3..21daa0d0f57 100644 --- a/pkg/api/chunk.go +++ b/pkg/api/chunk.go @@ -13,9 +13,10 @@ import ( "strconv" "github.com/ethersphere/bee/v2/pkg/cac" + "github.com/ethersphere/bee/v2/pkg/soc" + "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/postage" - "github.com/ethersphere/bee/v2/pkg/soc" "github.com/ethersphere/bee/v2/pkg/storage" "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/gorilla/mux" diff --git a/pkg/api/chunk_test.go b/pkg/api/chunk_test.go index 66f8dfae74a..c0e1fe9de9c 100644 --- a/pkg/api/chunk_test.go +++ b/pkg/api/chunk_test.go @@ -13,15 +13,16 @@ import ( "testing" "time" - "github.com/ethersphere/bee/v2/pkg/api" - "github.com/ethersphere/bee/v2/pkg/jsonhttp" - "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" "github.com/ethersphere/bee/v2/pkg/log" mockbatchstore "github.com/ethersphere/bee/v2/pkg/postage/batchstore/mock" mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" "github.com/ethersphere/bee/v2/pkg/spinlock" - testingc "github.com/ethersphere/bee/v2/pkg/storage/testing" mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" + + "github.com/ethersphere/bee/v2/pkg/api" + "github.com/ethersphere/bee/v2/pkg/jsonhttp" + "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" + testingc "github.com/ethersphere/bee/v2/pkg/storage/testing" "github.com/ethersphere/bee/v2/pkg/swarm" ) diff --git a/pkg/api/cors_test.go b/pkg/api/cors_test.go index 08c817c0389..73c3b343414 100644 --- a/pkg/api/cors_test.go +++ b/pkg/api/cors_test.go @@ -116,6 +116,7 @@ func TestCORSHeaders(t *testing.T) { } }) } + } // TestCors tests whether CORs work correctly with OPTIONS method @@ -134,8 +135,7 @@ func TestCors(t *testing.T) { { endpoint: "bzz", expectedMethods: "POST", - }, - { + }, { endpoint: "bzz/0101011", expectedMethods: "GET, HEAD", }, diff --git a/pkg/api/debugstorage_test.go b/pkg/api/debugstorage_test.go index 0a7c655fdec..bb12a5585fd 100644 --- a/pkg/api/debugstorage_test.go +++ b/pkg/api/debugstorage_test.go @@ -43,4 +43,5 @@ func TestDebugStorage(t *testing.T) { jsonhttptest.WithExpectedJSONResponse(want), ) }) + } diff --git a/pkg/api/dirs.go b/pkg/api/dirs.go index ce2b679c076..f187fbde01e 100644 --- a/pkg/api/dirs.go +++ b/pkg/api/dirs.go @@ -141,6 +141,7 @@ func storeDir( errorFilename string, rLevel redundancy.Level, ) (swarm.Address, error) { + logger := tracing.NewLoggerWithTraceID(ctx, log) loggerV1 := logger.V(1).Build() diff --git a/pkg/api/dirs_test.go b/pkg/api/dirs_test.go index 306e561c864..d49f0d281d6 100644 --- a/pkg/api/dirs_test.go +++ b/pkg/api/dirs_test.go @@ -371,6 +371,7 @@ func TestDirs(t *testing.T) { // check error document validateAltPath(t, "_non_existent_file_path_", errorDocumentPath) } + } t.Run(tc.name, func(t *testing.T) { t.Run("tar_upload", func(t *testing.T) { @@ -541,7 +542,7 @@ func tarFiles(t *testing.T, files []f) *bytes.Buffer { // create tar header and write it hdr := &tar.Header{ Name: filePath, - Mode: 0o600, + Mode: 0600, Size: int64(len(file.data)), } if err := tw.WriteHeader(hdr); err != nil { @@ -570,7 +571,7 @@ func tarEmptyDir(t *testing.T) *bytes.Buffer { hdr := &tar.Header{ Name: "empty/", - Mode: 0o600, + Mode: 0600, } if err := tw.WriteHeader(hdr); err != nil { @@ -603,9 +604,11 @@ func multipartFiles(t *testing.T, files []f) (*bytes.Buffer, string) { contentType := file.header.Get(api.ContentTypeHeader) if contentType != "" { hdr.Set(api.ContentTypeHeader, contentType) + } if len(file.data) > 0 { hdr.Set(api.ContentLengthHeader, strconv.Itoa(len(file.data))) + } part, err := mw.CreatePart(hdr) if err != nil { diff --git a/pkg/api/export_test.go b/pkg/api/export_test.go index 916992815a6..fd78ae6974f 100644 --- a/pkg/api/export_test.go +++ b/pkg/api/export_test.go @@ -29,7 +29,9 @@ var ( EmptyDir = errEmptyDir ) -var ContentTypeTar = contentTypeTar +var ( + ContentTypeTar = contentTypeTar +) var ( ErrNoResolver = errNoResolver @@ -137,7 +139,6 @@ type HexInvalidByteError = hexInvalidByteError func MapStructure(input, output interface{}, hooks map[string]func(v string) (string, error)) error { return mapStructure(input, output, hooks) } - func NewParseError(entry, value string, cause error) error { return newParseError(entry, value, cause) } diff --git a/pkg/api/feed_test.go b/pkg/api/feed_test.go index 7235ad93636..a35b9ce3423 100644 --- a/pkg/api/feed_test.go +++ b/pkg/api/feed_test.go @@ -161,6 +161,7 @@ func TestFeed_Post(t *testing.T) { ) }) }) + } // TestDirectUploadFeed tests that the direct upload endpoint give correct error message in dev mode diff --git a/pkg/api/metrics.go b/pkg/api/metrics.go index 6064595a0ed..7635468f4e3 100644 --- a/pkg/api/metrics.go +++ b/pkg/api/metrics.go @@ -68,6 +68,7 @@ func newMetrics() metrics { } func toFileSizeBucket(bytes int64) int64 { + for _, s := range fileSizeBucketsKBytes { if (s * bytesInKB) >= bytes { return s * bytesInKB diff --git a/pkg/api/pin_test.go b/pkg/api/pin_test.go index 00925135efd..a85c34a9594 100644 --- a/pkg/api/pin_test.go +++ b/pkg/api/pin_test.go @@ -136,6 +136,7 @@ func TestPinHandlers(t *testing.T) { rootHash = strings.Trim(header.Get(api.ETagHeader), "\"") checkPinHandlers(t, client, rootHash, false) }) + } func TestPinHandlersInvalidInputs(t *testing.T) { @@ -193,6 +194,7 @@ func TestPinHandlersInvalidInputs(t *testing.T) { const pinRef = "620fcd78c7ce54da2d1b7cc2274a02e190cbe8fecbc3bd244690ab6517ce8f39" func TestIntegrityHandler(t *testing.T) { + t.Parallel() t.Run("ok", func(t *testing.T) { diff --git a/pkg/api/postage_test.go b/pkg/api/postage_test.go index 56cfb606078..ebf808c1c7a 100644 --- a/pkg/api/postage_test.go +++ b/pkg/api/postage_test.go @@ -17,6 +17,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethersphere/bee/v2/pkg/api" "github.com/ethersphere/bee/v2/pkg/bigint" "github.com/ethersphere/bee/v2/pkg/jsonhttp" @@ -372,6 +373,7 @@ func TestPostageGetBuckets(t *testing.T) { jsonhttptest.Request(t, tsNotFound, http.MethodGet, "/stamps/"+batchOkStr+"/buckets", http.StatusNotFound) }) + } func TestReserveState(t *testing.T) { @@ -404,7 +406,6 @@ func TestReserveState(t *testing.T) { ) }) } - func TestChainState(t *testing.T) { t.Parallel() @@ -432,6 +433,7 @@ func TestChainState(t *testing.T) { }), ) }) + } func TestPostageTopUpStamp(t *testing.T) { @@ -701,6 +703,7 @@ func TestPostageDiluteStamp(t *testing.T) { TxHash: txHash.String(), }), ) + }) } diff --git a/pkg/api/probe.go b/pkg/api/probe.go index 5d0be5c1d69..8521d050f8d 100644 --- a/pkg/api/probe.go +++ b/pkg/api/probe.go @@ -58,6 +58,7 @@ func (p *Probe) Healthy() ProbeStatus { return ProbeStatusNOK } return p.healthy.get() + } // SetHealthy updates the value of the healthy status. diff --git a/pkg/api/pss_test.go b/pkg/api/pss_test.go index c97f6fcf40d..6624e6d8d21 100644 --- a/pkg/api/pss_test.go +++ b/pkg/api/pss_test.go @@ -88,6 +88,7 @@ func TestPssWebsocketSingleHandlerDeregister(t *testing.T) { ) err := cl.SetReadDeadline(time.Now().Add(longTimeout)) + if err != nil { t.Fatal(err) } @@ -445,12 +446,10 @@ func TestPssPostHandlerInvalidInputs(t *testing.T) { } } -type ( - pssSendFn func(context.Context, pss.Targets, swarm.Chunk) error - mpss struct { - f pssSendFn - } -) +type pssSendFn func(context.Context, pss.Targets, swarm.Chunk) error +type mpss struct { + f pssSendFn +} func newMockPss(f pssSendFn) *mpss { return &mpss{f} diff --git a/pkg/api/settlements_test.go b/pkg/api/settlements_test.go index 8096df88c9d..86f2e2e42e1 100644 --- a/pkg/api/settlements_test.go +++ b/pkg/api/settlements_test.go @@ -79,6 +79,7 @@ func TestSettlements(t *testing.T) { if !equalSettlements(got, expected) { t.Errorf("got settlements: %+v, expected: %+v", got, expected) } + } func TestSettlementsError(t *testing.T) { diff --git a/pkg/api/soc_test.go b/pkg/api/soc_test.go index 3f92e6684ff..79e72ffb603 100644 --- a/pkg/api/soc_test.go +++ b/pkg/api/soc_test.go @@ -122,6 +122,7 @@ func TestSOC(t *testing.T) { }) t.Run("ok batch", func(t *testing.T) { + s := testingsoc.GenerateMockSOC(t, testData) hexbatch := hex.EncodeToString(batchOk) client, _, _, chanStorer := newTestServer(t, testServerOptions{ diff --git a/pkg/api/staking.go b/pkg/api/staking.go index df588471ce3..5ca5b06d409 100644 --- a/pkg/api/staking.go +++ b/pkg/api/staking.go @@ -10,6 +10,7 @@ import ( "net/http" "github.com/ethersphere/bee/v2/pkg/bigint" + "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/storageincentives/staking" "github.com/gorilla/mux" @@ -32,7 +33,6 @@ func (s *Service) stakingAccessHandler(h http.Handler) http.Handler { type getStakeResponse struct { StakedAmount *bigint.BigInt `json:"stakedAmount"` } - type stakeDepositResponse struct { TxHash string `json:"txhash"` } diff --git a/pkg/api/staking_test.go b/pkg/api/staking_test.go index d7d569a8de8..e6f4d0b2296 100644 --- a/pkg/api/staking_test.go +++ b/pkg/api/staking_test.go @@ -12,8 +12,9 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" - "github.com/ethersphere/bee/v2/pkg/api" "github.com/ethersphere/bee/v2/pkg/bigint" + + "github.com/ethersphere/bee/v2/pkg/api" "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" "github.com/ethersphere/bee/v2/pkg/sctx" diff --git a/pkg/api/status_test.go b/pkg/api/status_test.go index 991806dbb86..cc2c568abf4 100644 --- a/pkg/api/status_test.go +++ b/pkg/api/status_test.go @@ -102,7 +102,6 @@ func (m *topologyPeersIterNoopMock) EachConnectedPeer(_ topology.EachPeerFunc, _ func (m *topologyPeersIterNoopMock) EachConnectedPeerRev(_ topology.EachPeerFunc, _ topology.Select) error { return nil } - func (m *topologyPeersIterNoopMock) IsReachable() bool { return true } diff --git a/pkg/api/stewardship.go b/pkg/api/stewardship.go index bf4d93f0356..99d330f78cc 100644 --- a/pkg/api/stewardship.go +++ b/pkg/api/stewardship.go @@ -8,10 +8,11 @@ import ( "errors" "net/http" - "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/postage" storage "github.com/ethersphere/bee/v2/pkg/storage" "github.com/ethersphere/bee/v2/pkg/swarm" + + "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/gorilla/mux" ) diff --git a/pkg/api/tag_test.go b/pkg/api/tag_test.go index 4536883c888..d3b8edeb4dc 100644 --- a/pkg/api/tag_test.go +++ b/pkg/api/tag_test.go @@ -11,19 +11,21 @@ import ( "strconv" "testing" - "github.com/ethersphere/bee/v2/pkg/api" - "github.com/ethersphere/bee/v2/pkg/jsonhttp" - "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" mockpost "github.com/ethersphere/bee/v2/pkg/postage/mock" mockstorer "github.com/ethersphere/bee/v2/pkg/storer/mock" "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/google/go-cmp/cmp" + + "github.com/ethersphere/bee/v2/pkg/api" + "github.com/ethersphere/bee/v2/pkg/jsonhttp" + "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" ) func tagsWithIdResource(id uint64) string { return fmt.Sprintf("/tags/%d", id) } // nolint:paralleltest func TestTags(t *testing.T) { + var ( tagsResource = "/tags" storerMock = mockstorer.New() diff --git a/pkg/api/version.go b/pkg/api/version.go index 6838f773ca8..b9bf36154c4 100644 --- a/pkg/api/version.go +++ b/pkg/api/version.go @@ -5,7 +5,5 @@ package api // Version is set in the build process. -var ( - Version = "0.0.0" - DebugVersion = "0.0.0" -) +var Version = "0.0.0" +var DebugVersion = "0.0.0" diff --git a/pkg/api/wallet.go b/pkg/api/wallet.go index 75674e1f48b..5cdd0de087d 100644 --- a/pkg/api/wallet.go +++ b/pkg/api/wallet.go @@ -7,9 +7,10 @@ package api import ( "math/big" "net/http" - "slices" "strings" + "slices" + "github.com/ethereum/go-ethereum/common" "github.com/ethersphere/bee/v2/pkg/bigint" "github.com/ethersphere/bee/v2/pkg/jsonhttp" diff --git a/pkg/api/welcome_message_test.go b/pkg/api/welcome_message_test.go index faca74f8c9f..39d7c19a039 100644 --- a/pkg/api/welcome_message_test.go +++ b/pkg/api/welcome_message_test.go @@ -26,8 +26,7 @@ func TestGetWelcomeMessage(t *testing.T) { DebugAPI: true, P2P: mock.New(mock.WithGetWelcomeMessageFunc(func() string { return DefaultTestWelcomeMessage - })), - }) + }))}) jsonhttptest.Request(t, srv, http.MethodGet, "/welcome-message", http.StatusOK, jsonhttptest.WithExpectedJSONResponse(api.WelcomeMessageResponse{ From 896e9b924979ff8b144654e33e8c34fefc243449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Ujv=C3=A1ri?= Date: Tue, 14 May 2024 12:54:37 +0200 Subject: [PATCH 16/19] CHG: accesslogic getkeys refactor --- pkg/dynamicaccess/accesslogic.go | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/pkg/dynamicaccess/accesslogic.go b/pkg/dynamicaccess/accesslogic.go index 2d369ca951d..80f3a61a332 100644 --- a/pkg/dynamicaccess/accesslogic.go +++ b/pkg/dynamicaccess/accesslogic.go @@ -83,13 +83,10 @@ func (al ActLogic) AddGrantee(ctx context.Context, storage kvs.KeyValueStore, pu } // Encrypt the access key for the new Grantee - keys, err := al.getKeys(granteePubKey) + lookupKey, accessKeyDecryptionKey, err := al.getKeys(granteePubKey) if err != nil { return err } - lookupKey := keys[0] - // accessKeyDecryptionKey is used for encryption of the access key - accessKeyDecryptionKey := keys[1] // Encrypt the access key for the new Grantee cipher := encryption.New(encryption.Key(accessKeyDecryptionKey), 0, uint32(0), hashFunc) @@ -98,20 +95,17 @@ func (al ActLogic) AddGrantee(ctx context.Context, storage kvs.KeyValueStore, pu return fmt.Errorf("failed to encrypt access key: %w", err) } - // Add the new encrypted access key for the Act - //nolint:wrapcheck + // Add the new encrypted access key to the Act return storage.Put(ctx, lookupKey, granteeEncryptedAccessKey) } // Will return the access key for a publisher (public key). func (al *ActLogic) getAccessKey(ctx context.Context, storage kvs.KeyValueStore, publisherPubKey *ecdsa.PublicKey) ([]byte, error) { - keys, err := al.getKeys(publisherPubKey) + publisherLookupKey, publisherAKDecryptionKey, err := al.getKeys(publisherPubKey) if err != nil { return nil, err } - publisherLookupKey := keys[0] - publisherAKDecryptionKey := keys[1] - // no need to constructor call if value not found in act + // no need for constructor call if value not found in act accessKeyDecryptionCipher := encryption.New(encryption.Key(publisherAKDecryptionKey), 0, uint32(0), hashFunc) encryptedAK, err := storage.Get(ctx, publisherLookupKey) if err != nil { @@ -122,18 +116,22 @@ func (al *ActLogic) getAccessKey(ctx context.Context, storage kvs.KeyValueStore, } // Generate lookup key and access key decryption key for a given public key -func (al *ActLogic) getKeys(publicKey *ecdsa.PublicKey) ([][]byte, error) { - return al.Session.Key(publicKey, [][]byte{zeroByteArray, oneByteArray}) +func (al *ActLogic) getKeys(publicKey *ecdsa.PublicKey) ([]byte, []byte, error) { + nonces := [][]byte{zeroByteArray, oneByteArray} + // keys := make([][]byte, 0, len(nonces)) + keys, err := al.Session.Key(publicKey, nonces) + if keys == nil { + return nil, nil, err + } + return keys[0], keys[1], err } // DecryptRef will return a decrypted reference, for given encrypted reference and publisher func (al ActLogic) DecryptRef(ctx context.Context, storage kvs.KeyValueStore, encryptedRef swarm.Address, publisher *ecdsa.PublicKey) (swarm.Address, error) { - keys, err := al.getKeys(publisher) + lookupKey, accessKeyDecryptionKey, err := al.getKeys(publisher) if err != nil { return swarm.ZeroAddress, err } - lookupKey := keys[0] - accessKeyDecryptionKey := keys[1] // Lookup encrypted access key from the ACT manifest encryptedAccessKey, err := storage.Get(ctx, lookupKey) From 9c9289a8ac181599bb00e8fd1837a846c1be57c9 Mon Sep 17 00:00:00 2001 From: kopi-solarpunk Date: Wed, 15 May 2024 12:44:43 +0200 Subject: [PATCH 17/19] refactor: fix errcheck and ineffassign linter errors in most cases --- pkg/api/dynamicaccess_test.go | 11 ++++----- pkg/dynamicaccess/controller_test.go | 35 ++++++++++++++-------------- pkg/dynamicaccess/grantee_test.go | 10 ++++++-- pkg/dynamicaccess/history_test.go | 14 +++++------ pkg/dynamicaccess/mock/controller.go | 4 ++-- pkg/kvs/kvs_test.go | 3 ++- 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/pkg/api/dynamicaccess_test.go b/pkg/api/dynamicaccess_test.go index 96891e13578..79eac36327b 100644 --- a/pkg/api/dynamicaccess_test.go +++ b/pkg/api/dynamicaccess_test.go @@ -40,23 +40,23 @@ func prepareHistoryFixture(storer api.Storer) (dynamicaccess.History, swarm.Addr testActRef1 := swarm.NewAddress([]byte("39a5ea87b141fe44aa609c3327ecd891")) firstTime := time.Date(1994, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() - h.Add(ctx, testActRef1, &firstTime, nil) + _ = h.Add(ctx, testActRef1, &firstTime, nil) testActRef2 := swarm.NewAddress([]byte("39a5ea87b141fe44aa609c3327ecd892")) secondTime := time.Date(2000, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() - h.Add(ctx, testActRef2, &secondTime, nil) + _ = h.Add(ctx, testActRef2, &secondTime, nil) testActRef3 := swarm.NewAddress([]byte("39a5ea87b141fe44aa609c3327ecd893")) thirdTime := time.Date(2015, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() - h.Add(ctx, testActRef3, &thirdTime, nil) + _ = h.Add(ctx, testActRef3, &thirdTime, nil) testActRef4 := swarm.NewAddress([]byte("39a5ea87b141fe44aa609c3327ecd894")) fourthTime := time.Date(2020, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() - h.Add(ctx, testActRef4, &fourthTime, nil) + _ = h.Add(ctx, testActRef4, &fourthTime, nil) testActRef5 := swarm.NewAddress([]byte("39a5ea87b141fe44aa609c3327ecd895")) fifthTime := time.Date(2030, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() - h.Add(ctx, testActRef5, &fifthTime, nil) + _ = h.Add(ctx, testActRef5, &fifthTime, nil) ref, _ := h.Store(ctx) return h, ref @@ -389,7 +389,6 @@ func TestDacHistory(t *testing.T) { fileName = "sample.html" now = time.Now().Unix() ) - fmt.Printf("bagoy now: %d\n", now) t.Run("empty-history-upload-then-download-and-check-data", func(t *testing.T) { client, _, _, _ := newTestServer(t, testServerOptions{ diff --git a/pkg/dynamicaccess/controller_test.go b/pkg/dynamicaccess/controller_test.go index e1d1dce6b94..2e6681ba06e 100644 --- a/pkg/dynamicaccess/controller_test.go +++ b/pkg/dynamicaccess/controller_test.go @@ -104,11 +104,11 @@ func TestController_PublisherDownload(t *testing.T) { c := dynamicaccess.NewController(al) ls := createLs() ref := swarm.RandAddress(t) - href, err := getHistoryFixture(ctx, ls, al, &publisher.PublicKey) - h, err := dynamicaccess.NewHistoryReference(ls, href) - entry, err := h.Lookup(ctx, time.Now().Unix()) + href, _ := getHistoryFixture(ctx, ls, al, &publisher.PublicKey) + h, _ := dynamicaccess.NewHistoryReference(ls, href) + entry, _ := h.Lookup(ctx, time.Now().Unix()) actRef := entry.Reference() - act, err := kvs.NewReference(ls, actRef) + act, _ := kvs.NewReference(ls, actRef) encRef, err := al.EncryptRef(ctx, act, &publisher.PublicKey, ref) assert.NoError(t, err) @@ -129,12 +129,12 @@ func TestController_GranteeDownload(t *testing.T) { ls := createLs() c := dynamicaccess.NewController(al) ref := swarm.RandAddress(t) - href, err := getHistoryFixture(ctx, ls, publisherAL, &publisher.PublicKey) - h, err := dynamicaccess.NewHistoryReference(ls, href) + href, _ := getHistoryFixture(ctx, ls, publisherAL, &publisher.PublicKey) + h, _ := dynamicaccess.NewHistoryReference(ls, href) ts := time.Date(2001, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() - entry, err := h.Lookup(ctx, ts) + entry, _ := h.Lookup(ctx, ts) actRef := entry.Reference() - act, err := kvs.NewReference(ls, actRef) + act, _ := kvs.NewReference(ls, actRef) encRef, err := publisherAL.EncryptRef(ctx, act, &publisher.PublicKey, ref) assert.NoError(t, err) @@ -179,7 +179,7 @@ func TestController_HandleGrantees(t *testing.T) { assert.Len(t, gl.Get(), 1) addList = []*ecdsa.PublicKey{&getPrivKey(0).PublicKey} - granteeRef, _, _, _, err = c.HandleGrantees(ctx, ls, ls, eglref, href, &publisher.PublicKey, addList, nil) + granteeRef, _, _, _, _ = c.HandleGrantees(ctx, ls, ls, eglref, href, &publisher.PublicKey, addList, nil) gl, err = dynamicaccess.NewGranteeListReference(ls, granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 2) @@ -188,12 +188,12 @@ func TestController_HandleGrantees(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} revokeList := []*ecdsa.PublicKey{&grantee1.PublicKey} gl, _ := dynamicaccess.NewGranteeList(ls) - gl.Add([]*ecdsa.PublicKey{&publisher.PublicKey, &grantee1.PublicKey}) - granteeRef, err := gl.Save(ctx) + _ = gl.Add([]*ecdsa.PublicKey{&publisher.PublicKey, &grantee1.PublicKey}) + granteeRef, _ := gl.Save(ctx) eglref, _ := refCipher.Encrypt(granteeRef.Bytes()) - granteeRef, _, _, _, err = c.HandleGrantees(ctx, ls, gls, swarm.NewAddress(eglref), href, &publisher.PublicKey, addList, revokeList) - gl, err = dynamicaccess.NewGranteeListReference(ls, granteeRef) + granteeRef, _, _, _, _ = c.HandleGrantees(ctx, ls, gls, swarm.NewAddress(eglref), href, &publisher.PublicKey, addList, revokeList) + gl, err := dynamicaccess.NewGranteeListReference(ls, granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 2) @@ -201,8 +201,9 @@ func TestController_HandleGrantees(t *testing.T) { t.Run("add twice", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey, &grantee.PublicKey} + //nolint:ineffassign,staticcheck,wastedassign granteeRef, eglref, _, _, err := c.HandleGrantees(ctx, ls, gls, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) - granteeRef, _, _, _, err = c.HandleGrantees(ctx, ls, ls, eglref, href, &publisher.PublicKey, addList, nil) + granteeRef, _, _, _, _ = c.HandleGrantees(ctx, ls, ls, eglref, href, &publisher.PublicKey, addList, nil) gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) @@ -210,7 +211,7 @@ func TestController_HandleGrantees(t *testing.T) { }) t.Run("revoke non-existing", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, _, _, _, err := c.HandleGrantees(ctx, ls, ls, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) + granteeRef, _, _, _, _ := c.HandleGrantees(ctx, ls, ls, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) gl, err := dynamicaccess.NewGranteeListReference(createLs(), granteeRef) assert.NoError(t, err) @@ -234,7 +235,7 @@ func TestController_GetGrantees(t *testing.T) { t.Run("get by publisher", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - granteeRef, eglRef, _, _, err := c1.HandleGrantees(ctx, ls, gls, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + granteeRef, eglRef, _, _, _ := c1.HandleGrantees(ctx, ls, gls, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) grantees, err := c1.GetGrantees(ctx, ls, &publisher.PublicKey, eglRef) assert.NoError(t, err) @@ -245,7 +246,7 @@ func TestController_GetGrantees(t *testing.T) { }) t.Run("get by non-publisher", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} - _, eglRef, _, _, err := c1.HandleGrantees(ctx, ls, gls, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) + _, eglRef, _, _, _ := c1.HandleGrantees(ctx, ls, gls, swarm.ZeroAddress, swarm.ZeroAddress, &publisher.PublicKey, addList, nil) grantees, err := c2.GetGrantees(ctx, ls, &publisher.PublicKey, eglRef) assert.Error(t, err) assert.Nil(t, grantees) diff --git a/pkg/dynamicaccess/grantee_test.go b/pkg/dynamicaccess/grantee_test.go index c4ce58ac8aa..66de1ccad12 100644 --- a/pkg/dynamicaccess/grantee_test.go +++ b/pkg/dynamicaccess/grantee_test.go @@ -33,7 +33,13 @@ func createLs() file.LoadSaver { func generateKeyListFixture() ([]*ecdsa.PublicKey, error) { key1, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) + if err != nil { + return nil, err + } key2, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) + if err != nil { + return nil, err + } key3, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { return nil, err @@ -216,8 +222,8 @@ func TestGranteeRemoveTwo(t *testing.T) { if err != nil { t.Errorf("key generation error: %v", err) } - err = gl.Add([]*ecdsa.PublicKey{keys[0]}) - err = gl.Add([]*ecdsa.PublicKey{keys[0]}) + _ = gl.Add([]*ecdsa.PublicKey{keys[0]}) + _ = gl.Add([]*ecdsa.PublicKey{keys[0]}) err = gl.Remove([]*ecdsa.PublicKey{keys[0]}) assert.NoError(t, err) } diff --git a/pkg/dynamicaccess/history_test.go b/pkg/dynamicaccess/history_test.go index 5c7f5670cf6..c348647a86e 100644 --- a/pkg/dynamicaccess/history_test.go +++ b/pkg/dynamicaccess/history_test.go @@ -61,27 +61,27 @@ func TestMultiNodeHistoryLookup(t *testing.T) { testActRef1 := swarm.NewAddress([]byte("39a5ea87b141fe44aa609c3327ecd891")) firstTime := time.Date(1994, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() mtdt1 := map[string]string{"firstTime": "1994-04-01"} - h.Add(ctx, testActRef1, &firstTime, &mtdt1) + _ = h.Add(ctx, testActRef1, &firstTime, &mtdt1) testActRef2 := swarm.NewAddress([]byte("39a5ea87b141fe44aa609c3327ecd892")) secondTime := time.Date(2000, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() mtdt2 := map[string]string{"secondTime": "2000-04-01"} - h.Add(ctx, testActRef2, &secondTime, &mtdt2) + _ = h.Add(ctx, testActRef2, &secondTime, &mtdt2) testActRef3 := swarm.NewAddress([]byte("39a5ea87b141fe44aa609c3327ecd893")) thirdTime := time.Date(2015, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() mtdt3 := map[string]string{"thirdTime": "2015-04-01"} - h.Add(ctx, testActRef3, &thirdTime, &mtdt3) + _ = h.Add(ctx, testActRef3, &thirdTime, &mtdt3) testActRef4 := swarm.NewAddress([]byte("39a5ea87b141fe44aa609c3327ecd894")) fourthTime := time.Date(2020, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() mtdt4 := map[string]string{"fourthTime": "2020-04-01"} - h.Add(ctx, testActRef4, &fourthTime, &mtdt4) + _ = h.Add(ctx, testActRef4, &fourthTime, &mtdt4) testActRef5 := swarm.NewAddress([]byte("39a5ea87b141fe44aa609c3327ecd895")) fifthTime := time.Date(2030, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() mtdt5 := map[string]string{"fifthTime": "2030-04-01"} - h.Add(ctx, testActRef5, &fifthTime, &mtdt5) + _ = h.Add(ctx, testActRef5, &fifthTime, &mtdt5) // latest searchedTime := time.Date(1980, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() @@ -126,7 +126,7 @@ func TestHistoryStore(t *testing.T) { testActRef1 := swarm.NewAddress([]byte("39a5ea87b141fe44aa609c3327ecd891")) firstTime := time.Date(1994, time.April, 1, 0, 0, 0, 0, time.UTC).Unix() mtdt1 := map[string]string{"firstTime": "1994-04-01"} - h1.Add(ctx, testActRef1, &firstTime, &mtdt1) + _ = h1.Add(ctx, testActRef1, &firstTime, &mtdt1) href1, err := h1.Store(ctx) assert.NoError(t, err) @@ -134,7 +134,7 @@ func TestHistoryStore(t *testing.T) { h2, err := dynamicaccess.NewHistoryReference(ls, href1) assert.NoError(t, err) - entry1, err := h2.Lookup(ctx, firstTime) + entry1, _ := h2.Lookup(ctx, firstTime) actRef1 := entry1.Reference() assert.True(t, actRef1.Equal(testActRef1)) assert.True(t, reflect.DeepEqual(mtdt1, entry1.Metadata())) diff --git a/pkg/dynamicaccess/mock/controller.go b/pkg/dynamicaccess/mock/controller.go index 09cacb65145..7f77ca2ca32 100644 --- a/pkg/dynamicaccess/mock/controller.go +++ b/pkg/dynamicaccess/mock/controller.go @@ -126,7 +126,7 @@ func (m *mockDacService) UploadHandler(ctx context.Context, ls file.LoadSaver, r } } else { h, _ = dynamicaccess.NewHistory(m.ls) - h.Add(ctx, kvsRef, &now, nil) + _ = h.Add(ctx, kvsRef, &now, nil) historyRef, _ = h.Store(ctx) m.historyMap[historyRef.String()] = h } @@ -140,7 +140,7 @@ func (m *mockDacService) Close() error { return nil } -func (m *mockDacService) HandleGrantees(ctx context.Context, ls file.LoadSaver, gls file.LoadSaver, encryptedglref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList []*ecdsa.PublicKey, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, swarm.Address, error) { +func (m *mockDacService) HandleGrantees(_ context.Context, ls file.LoadSaver, gls file.LoadSaver, encryptedglref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList []*ecdsa.PublicKey, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, swarm.Address, error) { historyRef, _ := swarm.ParseHexAddress("67bdf80a9bbea8eca9c8480e43fdceb485d2d74d5708e45144b8c4adacd13d9c") glRef, _ := swarm.ParseHexAddress("3339613565613837623134316665343461613630396333333237656364383934") eglRef, _ := swarm.ParseHexAddress("fc4e9fe978991257b897d987bc4ff13058b66ef45a53189a0b4fe84bb3346396") diff --git a/pkg/kvs/kvs_test.go b/pkg/kvs/kvs_test.go index f542c86144b..e2da7aa7030 100644 --- a/pkg/kvs/kvs_test.go +++ b/pkg/kvs/kvs_test.go @@ -33,6 +33,7 @@ func createLs() file.LoadSaver { } func keyValuePair(t *testing.T) ([]byte, []byte) { + t.Helper() return swarm.RandAddress(t).Bytes(), swarm.RandAddress(t).Bytes() } @@ -129,7 +130,7 @@ func TestKvs_Save(t *testing.T) { }) t.Run("Save not empty KVS return valid swarm address", func(t *testing.T) { s, _ := kvs.New(createLs()) - s.Put(ctx, key1, val1) + _ = s.Put(ctx, key1, val1) ref, err := s.Save(ctx) assert.NoError(t, err) assert.True(t, ref.IsValidNonEmpty()) From c61a4b1b915707e22f22177b9e4ef2c5e7d3b198 Mon Sep 17 00:00:00 2001 From: kopi-solarpunk Date: Thu, 16 May 2024 09:12:16 +0200 Subject: [PATCH 18/19] refactor: add headers, and change error handling --- pkg/api/dynamicaccess.go | 4 +++ pkg/dynamicaccess/accesslogic.go | 4 +++ pkg/dynamicaccess/accesslogic_test.go | 49 +++++++++++---------------- pkg/dynamicaccess/controller.go | 4 +++ pkg/dynamicaccess/controller_test.go | 4 +++ pkg/dynamicaccess/grantee.go | 4 +++ pkg/dynamicaccess/grantee_test.go | 4 +++ pkg/dynamicaccess/history.go | 4 +++ pkg/dynamicaccess/history_test.go | 4 +++ pkg/dynamicaccess/mock/accesslogic.go | 3 ++ pkg/dynamicaccess/session.go | 4 +++ pkg/dynamicaccess/session_test.go | 4 +++ pkg/kvs/mock/kvs.go | 4 +++ 13 files changed, 66 insertions(+), 30 deletions(-) diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index 5a6295696bc..32447f905e8 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package api import ( diff --git a/pkg/dynamicaccess/accesslogic.go b/pkg/dynamicaccess/accesslogic.go index 80f3a61a332..1cb9db8b5ba 100644 --- a/pkg/dynamicaccess/accesslogic.go +++ b/pkg/dynamicaccess/accesslogic.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package dynamicaccess import ( diff --git a/pkg/dynamicaccess/accesslogic_test.go b/pkg/dynamicaccess/accesslogic_test.go index 3df2f28a197..8d6c146e468 100644 --- a/pkg/dynamicaccess/accesslogic_test.go +++ b/pkg/dynamicaccess/accesslogic_test.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package dynamicaccess_test import ( @@ -12,6 +16,7 @@ import ( "github.com/ethersphere/bee/v2/pkg/dynamicaccess" kvsmock "github.com/ethersphere/bee/v2/pkg/kvs/mock" "github.com/ethersphere/bee/v2/pkg/swarm" + "github.com/stretchr/testify/assert" ) // Generates a new test environment with a fix private key @@ -133,9 +138,7 @@ func TestDecryptRef_Error(t *testing.T) { s := kvsmock.New() al := setupAccessLogic() err := al.AddPublisher(ctx, s, &id0.PublicKey) - if err != nil { - t.Errorf("AddPublisher: expected no error, got %v", err) - } + assert.NoError(t, err) expectedRef := "39a5ea87b141fe44aa609c3327ecd896c0e2122897f5f4bbacf74db1033c5559" @@ -156,19 +159,14 @@ func TestAddPublisher(t *testing.T) { al := setupAccessLogic() err := al.AddPublisher(ctx, s, &id0.PublicKey) - if err != nil { - t.Errorf("AddPublisher: expected no error, got %v", err) - } + assert.NoError(t, err) decodedSavedLookupKey, err := hex.DecodeString(savedLookupKey) - if err != nil { - t.Errorf("DecodeString: expected no error, got %v", err) - } + assert.NoError(t, err) encryptedAccessKey, err := s.Get(ctx, decodedSavedLookupKey) - if err != nil { - t.Errorf("Lookup: expected no error, got %v", err) - } + assert.NoError(t, err) + decodedEncryptedAccessKey := hex.EncodeToString(encryptedAccessKey) // A random value is returned so it is only possibly to check the length of the returned value @@ -194,24 +192,17 @@ func TestAddNewGranteeToContent(t *testing.T) { s := kvsmock.New() al := setupAccessLogic() err := al.AddPublisher(ctx, s, &id0.PublicKey) - if err != nil { - t.Errorf("AddNewGrantee: expected no error, got %v", err) - } + assert.NoError(t, err) err = al.AddGrantee(ctx, s, &id0.PublicKey, &id1.PublicKey, nil) - if err != nil { - t.Errorf("AddNewGrantee: expected no error, got %v", err) - } + assert.NoError(t, err) err = al.AddGrantee(ctx, s, &id0.PublicKey, &id2.PublicKey, nil) - if err != nil { - t.Errorf("AddNewGrantee: expected no error, got %v", err) - } + assert.NoError(t, err) lookupKeyAsByte, err := hex.DecodeString(publisherLookupKey) - if err != nil { - t.Errorf("AddNewGrantee: expected no error, got %v", err) - } + assert.NoError(t, err) + result, _ := s.Get(ctx, lookupKeyAsByte) hexEncodedEncryptedAK := hex.EncodeToString(result) if len(hexEncodedEncryptedAK) != 64 { @@ -219,9 +210,8 @@ func TestAddNewGranteeToContent(t *testing.T) { } lookupKeyAsByte, err = hex.DecodeString(firstAddedGranteeLookupKey) - if err != nil { - t.Errorf("AddNewGrantee: expected no error, got %v", err) - } + assert.NoError(t, err) + result, _ = s.Get(ctx, lookupKeyAsByte) hexEncodedEncryptedAK = hex.EncodeToString(result) if len(hexEncodedEncryptedAK) != 64 { @@ -229,9 +219,8 @@ func TestAddNewGranteeToContent(t *testing.T) { } lookupKeyAsByte, err = hex.DecodeString(secondAddedGranteeLookupKey) - if err != nil { - t.Errorf("AddNewGrantee: expected no error, got %v", err) - } + assert.NoError(t, err) + result, _ = s.Get(ctx, lookupKeyAsByte) hexEncodedEncryptedAK = hex.EncodeToString(result) if len(hexEncodedEncryptedAK) != 64 { diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index 16678db2a8a..a8998aa12df 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package dynamicaccess import ( diff --git a/pkg/dynamicaccess/controller_test.go b/pkg/dynamicaccess/controller_test.go index 2e6681ba06e..05b4e76db11 100644 --- a/pkg/dynamicaccess/controller_test.go +++ b/pkg/dynamicaccess/controller_test.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package dynamicaccess_test import ( diff --git a/pkg/dynamicaccess/grantee.go b/pkg/dynamicaccess/grantee.go index 2cb77236b44..57e6429f7da 100644 --- a/pkg/dynamicaccess/grantee.go +++ b/pkg/dynamicaccess/grantee.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package dynamicaccess import ( diff --git a/pkg/dynamicaccess/grantee_test.go b/pkg/dynamicaccess/grantee_test.go index 66de1ccad12..cd69aaa752c 100644 --- a/pkg/dynamicaccess/grantee_test.go +++ b/pkg/dynamicaccess/grantee_test.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package dynamicaccess_test import ( diff --git a/pkg/dynamicaccess/history.go b/pkg/dynamicaccess/history.go index 7543007ad0c..27485e95f95 100644 --- a/pkg/dynamicaccess/history.go +++ b/pkg/dynamicaccess/history.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package dynamicaccess import ( diff --git a/pkg/dynamicaccess/history_test.go b/pkg/dynamicaccess/history_test.go index c348647a86e..edc86dc7f22 100644 --- a/pkg/dynamicaccess/history_test.go +++ b/pkg/dynamicaccess/history_test.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package dynamicaccess_test import ( diff --git a/pkg/dynamicaccess/mock/accesslogic.go b/pkg/dynamicaccess/mock/accesslogic.go index 8be8e3a07fd..6b48c824eb9 100644 --- a/pkg/dynamicaccess/mock/accesslogic.go +++ b/pkg/dynamicaccess/mock/accesslogic.go @@ -1,3 +1,6 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. package mock type AccessLogicMock struct { diff --git a/pkg/dynamicaccess/session.go b/pkg/dynamicaccess/session.go index 76491daad46..fb1f44241be 100644 --- a/pkg/dynamicaccess/session.go +++ b/pkg/dynamicaccess/session.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package dynamicaccess import ( diff --git a/pkg/dynamicaccess/session_test.go b/pkg/dynamicaccess/session_test.go index 382a79190d5..701384b93bb 100644 --- a/pkg/dynamicaccess/session_test.go +++ b/pkg/dynamicaccess/session_test.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package dynamicaccess_test import ( diff --git a/pkg/kvs/mock/kvs.go b/pkg/kvs/mock/kvs.go index 767c8868dcf..f5818972004 100644 --- a/pkg/kvs/mock/kvs.go +++ b/pkg/kvs/mock/kvs.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package mock import ( From 424c816dd99bf5a725cadb3a84f2237eeb242900 Mon Sep 17 00:00:00 2001 From: kopi-solarpunk Date: Thu, 16 May 2024 09:16:54 +0200 Subject: [PATCH 19/19] refactor: add headers --- pkg/dynamicaccess/mock/grantee.go | 4 ++++ pkg/dynamicaccess/mock/session.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/pkg/dynamicaccess/mock/grantee.go b/pkg/dynamicaccess/mock/grantee.go index 50689ade08f..6a8f01c87cb 100644 --- a/pkg/dynamicaccess/mock/grantee.go +++ b/pkg/dynamicaccess/mock/grantee.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package mock import ( diff --git a/pkg/dynamicaccess/mock/session.go b/pkg/dynamicaccess/mock/session.go index f6a398e75a9..6e5d43a9576 100644 --- a/pkg/dynamicaccess/mock/session.go +++ b/pkg/dynamicaccess/mock/session.go @@ -1,3 +1,7 @@ +// Copyright 2024 The Swarm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package mock import (