From 694153843fb2551725804dc28b7e25e474d13bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Levente=20T=C3=B3th?= Date: Wed, 4 Sep 2024 17:44:29 +0200 Subject: [PATCH 1/5] feat: soc replica logic --- pkg/replicas/soc_getter.go | 148 +++++++++++++++++++++++++++++++++++ pkg/replicas/soc_putter.go | 58 ++++++++++++++ pkg/replicas/soc_replicas.go | 99 +++++++++++++++++++++++ 3 files changed, 305 insertions(+) create mode 100644 pkg/replicas/soc_getter.go create mode 100644 pkg/replicas/soc_putter.go create mode 100644 pkg/replicas/soc_replicas.go diff --git a/pkg/replicas/soc_getter.go b/pkg/replicas/soc_getter.go new file mode 100644 index 00000000000..055cf85f0e1 --- /dev/null +++ b/pkg/replicas/soc_getter.go @@ -0,0 +1,148 @@ +// Copyright 2023 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. + +// the code below implements the integration of dispersed replicas in chunk fetching. +// using storage.Getter interface. +package replicas + +import ( + "context" + "errors" + "sync" + "time" + + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + "github.com/ethersphere/bee/v2/pkg/soc" + "github.com/ethersphere/bee/v2/pkg/storage" + "github.com/ethersphere/bee/v2/pkg/swarm" +) + +// getter is the private implementation of storage.Getter, an interface for +// retrieving chunks. This getter embeds the original simple chunk getter and extends it +// to a multiplexed variant that fetches chunks with replicas. +// +// the strategy to retrieve a chunk that has replicas can be configured with a few parameters: +// - RetryInterval: the delay before a new batch of replicas is fetched. +// - depth: 2^{depth} is the total number of additional replicas that have been uploaded +// (by default, it is assumed to be 4, ie. total of 16) +// - (not implemented) pivot: replicas with address in the proximity of pivot will be tried first +type socGetter struct { + wg sync.WaitGroup + storage.Getter + level redundancy.Level +} + +// NewGetter is the getter constructor +func NewSocGetter(g storage.Getter, level redundancy.Level) storage.Getter { + return &socGetter{Getter: g, level: level} +} + +// Get makes the getter satisfy the storage.Getter interface +func (g *socGetter) Get(ctx context.Context, addr swarm.Address) (ch swarm.Chunk, err error) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // channel that the results (retrieved chunks) are gathered to from concurrent + // workers each fetching a replica + resultC := make(chan swarm.Chunk) + // errc collects the errors + errc := make(chan error, 17) + var errs error + errcnt := 0 + + // concurrently call to retrieve chunk using original SOC address + g.wg.Add(1) + go func() { + defer g.wg.Done() + ch, err := g.Getter.Get(ctx, addr) + if err != nil { + errc <- err + return + } + + select { + case resultC <- ch: + case <-ctx.Done(): + } + }() + // counters + n := 0 // counts the replica addresses tried + target := 2 // the number of replicas attempted to download in this batch + total := g.level.GetReplicaCount() + + // + rr := newSocReplicator(addr, g.level) + next := rr.c + var wait <-chan time.Time // nil channel to disable case + // addresses used are doubling each period of search expansion + // (at intervals of RetryInterval) + ticker := time.NewTicker(RetryInterval) + defer ticker.Stop() + for level := uint8(0); level <= uint8(g.level); { + select { + // at least one chunk is retrieved, cancel the rest and return early + case chunk := <-resultC: + cancel() + return chunk, nil + + case err = <-errc: + errs = errors.Join(errs, err) + errcnt++ + if errcnt > total { + return nil, errors.Join(ErrSwarmageddon, errs) + } + + // ticker switches on the address channel + case <-wait: + wait = nil + next = rr.c + level++ + target = 1 << level + n = 0 + continue + + // getting the addresses in order + case so := <-next: + if so == nil { + next = nil + continue + } + + g.wg.Add(1) + go func() { + defer g.wg.Done() + ch, err := g.Getter.Get(ctx, swarm.NewAddress(so.addr)) + if err != nil { + errc <- err + return + } + + soc, err := soc.FromChunk(ch) + if err != nil { + errc <- err + return + } + + returnCh, err := soc.Chunk() + if err != nil { + errc <- err + return + } + + select { + case resultC <- returnCh: + case <-ctx.Done(): + } + }() + n++ + if n < target { + continue + } + next = nil + wait = ticker.C + } + } + + return nil, nil +} diff --git a/pkg/replicas/soc_putter.go b/pkg/replicas/soc_putter.go new file mode 100644 index 00000000000..ae740b645db --- /dev/null +++ b/pkg/replicas/soc_putter.go @@ -0,0 +1,58 @@ +// Copyright 2020 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. + +// the code below implements the integration of dispersed replicas in chunk upload. +// using storage.Putter interface. +package replicas + +import ( + "context" + "errors" + "sync" + + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + "github.com/ethersphere/bee/v2/pkg/storage" + "github.com/ethersphere/bee/v2/pkg/swarm" +) + +// putter is the private implementation of the public storage.Putter interface +// putter extends the original putter to a concurrent multiputter +type socPutter struct { + putter storage.Putter +} + +// NewSocPutter is the putter constructor +func NewSocPutter(p storage.Putter) storage.Putter { + return &socPutter{p} +} + +// Put makes the getter satisfy the storage.Getter interface +func (p *socPutter) Put(ctx context.Context, ch swarm.Chunk) (err error) { + rlevel := redundancy.GetLevelFromContext(ctx) + errs := []error{} + if rlevel == 0 { + return nil + } + + rr := newSocReplicator(ch.Address(), rlevel) + errc := make(chan error, rlevel.GetReplicaCount()) + wg := sync.WaitGroup{} + for r := range rr.c { + r := r + wg.Add(1) + go func() { + defer wg.Done() + sch := swarm.NewChunk(swarm.NewAddress(r.addr), ch.Data()) + err = p.putter.Put(ctx, sch) + errc <- err + }() + } + + wg.Wait() + close(errc) + for err := range errc { + errs = append(errs, err) + } + return errors.Join(errs...) +} diff --git a/pkg/replicas/soc_replicas.go b/pkg/replicas/soc_replicas.go new file mode 100644 index 00000000000..a5d3f576113 --- /dev/null +++ b/pkg/replicas/soc_replicas.go @@ -0,0 +1,99 @@ +// 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 replicas implements a scheme to replicate SOC chunks +// in such a way that +// - the replicas are optimally dispersed to aid cross-neighbourhood redundancy +// - the replicas addresses can be deduced by retrievers only knowing the address +// of the original content addressed chunk +// - no new chunk validation rules are introduced +package replicas + +import ( + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + "github.com/ethersphere/bee/v2/pkg/swarm" +) + +// replicator running the find for replicas +type socReplicator struct { + addr []byte // chunk address + queue [16]*socReplica // to sort addresses according to di + exist [30]bool // maps the 16 distinct nibbles on all levels + sizes [5]int // number of distinct neighnourhoods redcorded for each depth + c chan *socReplica + rLevel redundancy.Level +} + +// newSocReplicator replicator constructor +func newSocReplicator(addr swarm.Address, rLevel redundancy.Level) *socReplicator { + rr := &socReplicator{ + addr: addr.Bytes(), + sizes: redundancy.GetReplicaCounts(), + c: make(chan *socReplica, 16), + rLevel: rLevel, + } + go rr.replicas() + return rr +} + +// socReplica of the mined SOC chunk (address) that serve as replicas +type socReplica struct { + addr []byte // byte slice of the generated SOC address + nonce uint8 // used nonce to generate the address +} + +// replicate returns a replica for SOC seeded with a byte of entropy as argument +func (rr *socReplicator) replicate(i uint8) (sp *socReplica) { + // calculate SOC address for potential replica + h := swarm.NewHasher() + _, _ = h.Write(rr.addr) + _, _ = h.Write([]byte{i}) + return &socReplica{h.Sum(nil), i} +} + +// replicas enumerates replica parameters (SOC ID) pushing it in a channel given as argument +// the order of replicas is so that addresses are always maximally dispersed +// in successive sets of addresses. +// I.e., the binary tree representing the new addresses prefix bits up to depth is balanced +func (rr *socReplicator) replicas() { + defer close(rr.c) + n := 0 + for i := uint8(0); n < rr.rLevel.GetReplicaCount() && i < 255; i++ { + // create soc replica (ID and address using constant owner) + // the soc is added to neighbourhoods of depths in the closed interval [from...to] + r := rr.replicate(i) + d, m := rr.add(r, rr.rLevel) + if d == 0 { + continue + } + for m, r = range rr.queue[n:] { + if r == nil { + break + } + rr.c <- r + } + n += m + } +} + +// add inserts the soc replica into a replicator so that addresses are balanced +func (rr *socReplicator) add(r *socReplica, rLevel redundancy.Level) (depth int, rank int) { + if rLevel == redundancy.NONE { + return 0, 0 + } + nh := nh(rLevel, r.addr) + if rr.exist[nh] { + return 0, 0 + } + rr.exist[nh] = true + l, o := rr.add(r, rLevel.Decrement()) + d := uint8(rLevel) - 1 + if l == 0 { + o = rr.sizes[d] + rr.sizes[d]++ + rr.queue[o] = r + l = rLevel.GetReplicaCount() + } + return l, o +} From c11129674baebda0a6b839889afbee70d18147ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Levente=20T=C3=B3th?= Date: Wed, 4 Sep 2024 17:44:59 +0200 Subject: [PATCH 2/5] feat: adjust feed logic --- pkg/feeds/getter.go | 6 +++++- pkg/feeds/putter.go | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/feeds/getter.go b/pkg/feeds/getter.go index 77b7599dd9e..e8e7a62d9be 100644 --- a/pkg/feeds/getter.go +++ b/pkg/feeds/getter.go @@ -11,6 +11,8 @@ import ( "fmt" "time" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" + "github.com/ethersphere/bee/v2/pkg/replicas" "github.com/ethersphere/bee/v2/pkg/soc" storage "github.com/ethersphere/bee/v2/pkg/storage" "github.com/ethersphere/bee/v2/pkg/swarm" @@ -46,7 +48,9 @@ func (f *Getter) Get(ctx context.Context, i Index) (swarm.Chunk, error) { if err != nil { return nil, err } - return f.getter.Get(ctx, addr) + rLevel := redundancy.GetLevelFromContext(ctx) + getter := replicas.NewSocGetter(f.getter, rLevel) + return getter.Get(ctx, addr) } // FromChunk parses out the timestamp and the payload diff --git a/pkg/feeds/putter.go b/pkg/feeds/putter.go index 633276f8f63..b5bef90c33d 100644 --- a/pkg/feeds/putter.go +++ b/pkg/feeds/putter.go @@ -10,6 +10,7 @@ import ( "github.com/ethersphere/bee/v2/pkg/cac" "github.com/ethersphere/bee/v2/pkg/crypto" + "github.com/ethersphere/bee/v2/pkg/replicas" "github.com/ethersphere/bee/v2/pkg/soc" storage "github.com/ethersphere/bee/v2/pkg/storage" "github.com/ethersphere/bee/v2/pkg/swarm" @@ -53,7 +54,8 @@ func (u *Putter) Put(ctx context.Context, i Index, at int64, payload []byte) err if err != nil { return err } - return u.putter.Put(ctx, ch) + putter := replicas.NewSocPutter(u.putter) + return putter.Put(ctx, ch) } func toChunk(at uint64, payload []byte) (swarm.Chunk, error) { From 741bbc5f86bb2f32ae3e5dab8d2e016aaad6867d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Levente=20T=C3=B3th?= Date: Wed, 4 Sep 2024 17:58:52 +0200 Subject: [PATCH 3/5] feat: soc api put --- pkg/api/soc.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pkg/api/soc.go b/pkg/api/soc.go index 9eff4bd3c99..f3b89d80f16 100644 --- a/pkg/api/soc.go +++ b/pkg/api/soc.go @@ -11,8 +11,10 @@ import ( "github.com/ethersphere/bee/v2/pkg/accesscontrol" "github.com/ethersphere/bee/v2/pkg/cac" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/postage" + "github.com/ethersphere/bee/v2/pkg/replicas" "github.com/ethersphere/bee/v2/pkg/soc" storage "github.com/ethersphere/bee/v2/pkg/storage" storer "github.com/ethersphere/bee/v2/pkg/storer" @@ -45,11 +47,12 @@ func (s *Service) socUploadHandler(w http.ResponseWriter, r *http.Request) { } headers := struct { - BatchID []byte `map:"Swarm-Postage-Batch-Id"` - StampSig []byte `map:"Swarm-Postage-Stamp"` - Pin bool `map:"Swarm-Pin"` - Act bool `map:"Swarm-Act"` - HistoryAddress swarm.Address `map:"Swarm-Act-History-Address"` + BatchID []byte `map:"Swarm-Postage-Batch-Id"` + StampSig []byte `map:"Swarm-Postage-Stamp"` + Pin bool `map:"Swarm-Pin"` + RLevel redundancy.Level `map:"Swarm-Redundancy-Level"` + Act bool `map:"Swarm-Act"` + HistoryAddress swarm.Address `map:"Swarm-Act-History-Address"` }{} if response := s.mapStructure(r.Header, &headers); response != nil { response("invalid header params", logger, w) @@ -208,7 +211,8 @@ func (s *Service) socUploadHandler(w http.ResponseWriter, r *http.Request) { } } - err = putter.Put(r.Context(), sch) + replicaPutter := replicas.NewSocPutter(putter) + err = replicaPutter.Put(r.Context(), sch) if err != nil { logger.Debug("write chunk failed", "chunk_address", sch.Address(), "error", err) logger.Error(nil, "write chunk failed") From b9baf94bbdda12e89afeb4d39a470e39ff261bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Levente=20T=C3=B3th?= Date: Fri, 6 Sep 2024 11:48:18 +0200 Subject: [PATCH 4/5] feat: soc validation --- pkg/replicas/soc_getter.go | 9 ++-- pkg/replicas/soc_putter.go | 7 +-- .../replicas_soc.go} | 49 +++++++++++++++---- pkg/soc/validator.go | 14 +++++- 4 files changed, 62 insertions(+), 17 deletions(-) rename pkg/{replicas/soc_replicas.go => replicas_soc/replicas_soc.go} (71%) diff --git a/pkg/replicas/soc_getter.go b/pkg/replicas/soc_getter.go index 055cf85f0e1..2933c6506af 100644 --- a/pkg/replicas/soc_getter.go +++ b/pkg/replicas/soc_getter.go @@ -13,6 +13,7 @@ import ( "time" "github.com/ethersphere/bee/v2/pkg/file/redundancy" + "github.com/ethersphere/bee/v2/pkg/replicas_soc" "github.com/ethersphere/bee/v2/pkg/soc" "github.com/ethersphere/bee/v2/pkg/storage" "github.com/ethersphere/bee/v2/pkg/swarm" @@ -72,8 +73,8 @@ func (g *socGetter) Get(ctx context.Context, addr swarm.Address) (ch swarm.Chunk total := g.level.GetReplicaCount() // - rr := newSocReplicator(addr, g.level) - next := rr.c + rr := replicas_soc.NewSocReplicator(addr, g.level) + next := rr.C var wait <-chan time.Time // nil channel to disable case // addresses used are doubling each period of search expansion // (at intervals of RetryInterval) @@ -96,7 +97,7 @@ func (g *socGetter) Get(ctx context.Context, addr swarm.Address) (ch swarm.Chunk // ticker switches on the address channel case <-wait: wait = nil - next = rr.c + next = rr.C level++ target = 1 << level n = 0 @@ -112,7 +113,7 @@ func (g *socGetter) Get(ctx context.Context, addr swarm.Address) (ch swarm.Chunk g.wg.Add(1) go func() { defer g.wg.Done() - ch, err := g.Getter.Get(ctx, swarm.NewAddress(so.addr)) + ch, err := g.Getter.Get(ctx, swarm.NewAddress(so.Addr)) if err != nil { errc <- err return diff --git a/pkg/replicas/soc_putter.go b/pkg/replicas/soc_putter.go index ae740b645db..b07d892e4f3 100644 --- a/pkg/replicas/soc_putter.go +++ b/pkg/replicas/soc_putter.go @@ -12,6 +12,7 @@ import ( "sync" "github.com/ethersphere/bee/v2/pkg/file/redundancy" + "github.com/ethersphere/bee/v2/pkg/replicas_soc" "github.com/ethersphere/bee/v2/pkg/storage" "github.com/ethersphere/bee/v2/pkg/swarm" ) @@ -35,15 +36,15 @@ func (p *socPutter) Put(ctx context.Context, ch swarm.Chunk) (err error) { return nil } - rr := newSocReplicator(ch.Address(), rlevel) + rr := replicas_soc.NewSocReplicator(ch.Address(), rlevel) errc := make(chan error, rlevel.GetReplicaCount()) wg := sync.WaitGroup{} - for r := range rr.c { + for r := range rr.C { r := r wg.Add(1) go func() { defer wg.Done() - sch := swarm.NewChunk(swarm.NewAddress(r.addr), ch.Data()) + sch := swarm.NewChunk(swarm.NewAddress(r.Addr), ch.Data()) err = p.putter.Put(ctx, sch) errc <- err }() diff --git a/pkg/replicas/soc_replicas.go b/pkg/replicas_soc/replicas_soc.go similarity index 71% rename from pkg/replicas/soc_replicas.go rename to pkg/replicas_soc/replicas_soc.go index a5d3f576113..8f589ef186b 100644 --- a/pkg/replicas/soc_replicas.go +++ b/pkg/replicas_soc/replicas_soc.go @@ -8,38 +8,57 @@ // - the replicas addresses can be deduced by retrievers only knowing the address // of the original content addressed chunk // - no new chunk validation rules are introduced -package replicas +package replicas_soc import ( + "time" + "github.com/ethersphere/bee/v2/pkg/file/redundancy" "github.com/ethersphere/bee/v2/pkg/swarm" ) +var ( + // RetryInterval is the duration between successive additional requests + RetryInterval = 300 * time.Millisecond +) + // replicator running the find for replicas type socReplicator struct { addr []byte // chunk address queue [16]*socReplica // to sort addresses according to di exist [30]bool // maps the 16 distinct nibbles on all levels sizes [5]int // number of distinct neighnourhoods redcorded for each depth - c chan *socReplica + C chan *socReplica rLevel redundancy.Level } -// newSocReplicator replicator constructor -func newSocReplicator(addr swarm.Address, rLevel redundancy.Level) *socReplicator { +// NewSocReplicator replicator constructor +func NewSocReplicator(addr swarm.Address, rLevel redundancy.Level) *socReplicator { rr := &socReplicator{ addr: addr.Bytes(), sizes: redundancy.GetReplicaCounts(), - c: make(chan *socReplica, 16), + C: make(chan *socReplica, 16), rLevel: rLevel, } go rr.replicas() return rr } +func AllAddresses(addr swarm.Address) []swarm.Address { + r := redundancy.PARANOID + rr := NewSocReplicator(addr, r) + addresses := make([]swarm.Address, r.GetReplicaCount()) + n := 0 + for r := range rr.C { + addresses[n] = swarm.NewAddress(r.Addr) + n++ + } + return addresses +} + // socReplica of the mined SOC chunk (address) that serve as replicas type socReplica struct { - addr []byte // byte slice of the generated SOC address + Addr []byte // byte slice of the generated SOC address nonce uint8 // used nonce to generate the address } @@ -57,7 +76,7 @@ func (rr *socReplicator) replicate(i uint8) (sp *socReplica) { // in successive sets of addresses. // I.e., the binary tree representing the new addresses prefix bits up to depth is balanced func (rr *socReplicator) replicas() { - defer close(rr.c) + defer close(rr.C) n := 0 for i := uint8(0); n < rr.rLevel.GetReplicaCount() && i < 255; i++ { // create soc replica (ID and address using constant owner) @@ -71,7 +90,7 @@ func (rr *socReplicator) replicas() { if r == nil { break } - rr.c <- r + rr.C <- r } n += m } @@ -82,7 +101,7 @@ func (rr *socReplicator) add(r *socReplica, rLevel redundancy.Level) (depth int, if rLevel == redundancy.NONE { return 0, 0 } - nh := nh(rLevel, r.addr) + nh := nh(rLevel, r.Addr) if rr.exist[nh] { return 0, 0 } @@ -97,3 +116,15 @@ func (rr *socReplicator) add(r *socReplica, rLevel redundancy.Level) (depth int, } return l, o } + +// UTILS + +// index bases needed to keep track how many addresses were mined for a level. +var replicaIndexBases = [5]int{0, 2, 6, 14} + +// nh returns the lookup key based on the redundancy level +// to be used as index to the replicators exist array +func nh(rLevel redundancy.Level, addr []byte) int { + d := uint8(rLevel) + return replicaIndexBases[d-1] + int(addr[0]>>(8-d)) +} diff --git a/pkg/soc/validator.go b/pkg/soc/validator.go index 06f2fb72e0a..0698ebf57f9 100644 --- a/pkg/soc/validator.go +++ b/pkg/soc/validator.go @@ -7,6 +7,7 @@ package soc import ( "bytes" + "github.com/ethersphere/bee/v2/pkg/replicas_soc" "github.com/ethersphere/bee/v2/pkg/swarm" ) @@ -26,5 +27,16 @@ func Valid(ch swarm.Chunk) bool { if err != nil { return false } - return ch.Address().Equal(address) + + // SOC dispersed replica validation + if !ch.Address().Equal(address) { + dispersedAddresses := replicas_soc.AllAddresses(ch.Address()) + for _, v := range dispersedAddresses { + if v.Equal(ch.Address()) { + return true + } + } + } + + return false } From 4972e75109153e64afa3f0992166847391d99802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Levente=20T=C3=B3th?= Date: Fri, 6 Sep 2024 12:10:01 +0200 Subject: [PATCH 5/5] refactor: soc subpackage for replicas --- .../replicas_soc.go => replicas/soc/soc.go} | 9 +-------- pkg/replicas/soc_getter.go | 2 +- pkg/replicas/soc_putter.go | 2 +- pkg/soc/validator.go | 2 +- 4 files changed, 4 insertions(+), 11 deletions(-) rename pkg/{replicas_soc/replicas_soc.go => replicas/soc/soc.go} (96%) diff --git a/pkg/replicas_soc/replicas_soc.go b/pkg/replicas/soc/soc.go similarity index 96% rename from pkg/replicas_soc/replicas_soc.go rename to pkg/replicas/soc/soc.go index 8f589ef186b..c82082a9d7c 100644 --- a/pkg/replicas_soc/replicas_soc.go +++ b/pkg/replicas/soc/soc.go @@ -8,20 +8,13 @@ // - the replicas addresses can be deduced by retrievers only knowing the address // of the original content addressed chunk // - no new chunk validation rules are introduced -package replicas_soc +package soc import ( - "time" - "github.com/ethersphere/bee/v2/pkg/file/redundancy" "github.com/ethersphere/bee/v2/pkg/swarm" ) -var ( - // RetryInterval is the duration between successive additional requests - RetryInterval = 300 * time.Millisecond -) - // replicator running the find for replicas type socReplicator struct { addr []byte // chunk address diff --git a/pkg/replicas/soc_getter.go b/pkg/replicas/soc_getter.go index 2933c6506af..66250ca2bdc 100644 --- a/pkg/replicas/soc_getter.go +++ b/pkg/replicas/soc_getter.go @@ -13,7 +13,7 @@ import ( "time" "github.com/ethersphere/bee/v2/pkg/file/redundancy" - "github.com/ethersphere/bee/v2/pkg/replicas_soc" + replicas_soc "github.com/ethersphere/bee/v2/pkg/replicas/soc" "github.com/ethersphere/bee/v2/pkg/soc" "github.com/ethersphere/bee/v2/pkg/storage" "github.com/ethersphere/bee/v2/pkg/swarm" diff --git a/pkg/replicas/soc_putter.go b/pkg/replicas/soc_putter.go index b07d892e4f3..eb995d1687b 100644 --- a/pkg/replicas/soc_putter.go +++ b/pkg/replicas/soc_putter.go @@ -12,7 +12,7 @@ import ( "sync" "github.com/ethersphere/bee/v2/pkg/file/redundancy" - "github.com/ethersphere/bee/v2/pkg/replicas_soc" + replicas_soc "github.com/ethersphere/bee/v2/pkg/replicas/soc" "github.com/ethersphere/bee/v2/pkg/storage" "github.com/ethersphere/bee/v2/pkg/swarm" ) diff --git a/pkg/soc/validator.go b/pkg/soc/validator.go index 0698ebf57f9..da7e6f188a3 100644 --- a/pkg/soc/validator.go +++ b/pkg/soc/validator.go @@ -7,7 +7,7 @@ package soc import ( "bytes" - "github.com/ethersphere/bee/v2/pkg/replicas_soc" + replicas_soc "github.com/ethersphere/bee/v2/pkg/replicas/soc" "github.com/ethersphere/bee/v2/pkg/swarm" )