Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: Pavel Karpy <[email protected]>
  • Loading branch information
carpawell committed Feb 26, 2024
1 parent 230faab commit 9a60f81
Show file tree
Hide file tree
Showing 22 changed files with 487 additions and 56 deletions.
102 changes: 81 additions & 21 deletions cmd/neofs-node/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"

lru "github.com/hashicorp/golang-lru/v2"
"github.com/nspcc-dev/neofs-api-go/v2/object"
objectGRPC "github.com/nspcc-dev/neofs-api-go/v2/object/grpc"
replicatorconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/replicator"
Expand All @@ -29,6 +30,7 @@ import (
putsvcV2 "github.com/nspcc-dev/neofs-node/pkg/services/object/put/v2"
searchsvc "github.com/nspcc-dev/neofs-node/pkg/services/object/search"
searchsvcV2 "github.com/nspcc-dev/neofs-node/pkg/services/object/search/v2"
"github.com/nspcc-dev/neofs-node/pkg/services/object/split"
"github.com/nspcc-dev/neofs-node/pkg/services/object/util"
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/placement"
"github.com/nspcc-dev/neofs-node/pkg/services/policer"
Expand Down Expand Up @@ -238,6 +240,26 @@ func initObjectService(c *cfg) {
}
}

sGet := getsvc.New(
getsvc.WithLogger(c.log),
getsvc.WithLocalStorageEngine(ls),
getsvc.WithClientConstructor(coreConstructor),
getsvc.WithTraverserGenerator(
traverseGen.WithTraverseOptions(
placement.SuccessAfter(1),
),
),
getsvc.WithNetMapSource(c.netMapSource),
getsvc.WithKeyStorage(keyStorage),
)

*c.cfgObject.getSvc = *sGet // need smth better

sGetV2 := getsvcV2.NewService(
getsvcV2.WithInternalService(sGet),
getsvcV2.WithKeyStorage(keyStorage),
)

sPut := putsvc.NewService(
putsvc.WithKeyStorage(keyStorage),
putsvc.WithClientConstructor(putConstructor),
Expand All @@ -249,6 +271,7 @@ func initObjectService(c *cfg) {
putsvc.WithNetworkState(c.cfgNetmap.state),
putsvc.WithWorkerPools(c.cfgObject.pool.putRemote, c.cfgObject.pool.putLocal),
putsvc.WithLogger(c.log),
putsvc.WithSplitChainVerifier(split.NewVerifier(sGet)),
)

sPutV2 := putsvcV2.NewService(
Expand All @@ -274,26 +297,6 @@ func initObjectService(c *cfg) {
searchsvcV2.WithKeyStorage(keyStorage),
)

sGet := getsvc.New(
getsvc.WithLogger(c.log),
getsvc.WithLocalStorageEngine(ls),
getsvc.WithClientConstructor(coreConstructor),
getsvc.WithTraverserGenerator(
traverseGen.WithTraverseOptions(
placement.SuccessAfter(1),
),
),
getsvc.WithNetMapSource(c.netMapSource),
getsvc.WithKeyStorage(keyStorage),
)

*c.cfgObject.getSvc = *sGet // need smth better

sGetV2 := getsvcV2.NewService(
getsvcV2.WithInternalService(sGet),
getsvcV2.WithKeyStorage(keyStorage),
)

sDelete := deletesvc.New(
deletesvc.WithLogger(c.log),
deletesvc.WithHeadService(sGet),
Expand Down Expand Up @@ -326,6 +329,13 @@ func initObjectService(c *cfg) {
},
)

// cachedFirstObjectsNumber is a total cached objects number; the V2 split scheme
// expects the first part of the chain to hold a user-defined header of the original
// object which should be treated as a header to use for the eACL rules check; so
// every object part in every chain will try to refer to the first part, so caching
// should help a lot here
const cachedFirstObjectsNumber = 1000

aclSvc := v2.New(
v2.WithLogger(c.log),
v2.WithIRFetcher(newCachedIRFetcher(irFetcher)),
Expand All @@ -339,7 +349,8 @@ func initObjectService(c *cfg) {
SetNetmapState(c.cfgNetmap.state).
SetEACLSource(c.cfgObject.eaclSource).
SetValidator(eaclSDK.NewValidator()).
SetLocalStorage(ls),
SetLocalStorage(ls).
SetHeaderSource(cachedHeaderSource(sGet, cachedFirstObjectsNumber)),
),
),
)
Expand Down Expand Up @@ -590,3 +601,52 @@ func (e engineWithoutNotifications) Lock(locker oid.Address, toLock []oid.ID) er
func (e engineWithoutNotifications) Put(o *objectSDK.Object) error {
return engine.Put(e.engine, o)
}

func cachedHeaderSource(getSvc *getsvc.Service, cacheSize int) headerSource {
hs := headerSource{getsvc: getSvc}

if cacheSize > 0 {
hs.cache, _ = lru.New[oid.Address, *objectSDK.Object](cacheSize)
}

return hs
}

type headerSource struct {
getsvc *getsvc.Service
cache *lru.Cache[oid.Address, *objectSDK.Object]
}

type headerWriter struct {
h *objectSDK.Object
}

func (h *headerWriter) WriteHeader(o *objectSDK.Object) error {
h.h = o
return nil
}

func (h headerSource) Head(address oid.Address) (*objectSDK.Object, error) {
if h.cache != nil {
head, ok := h.cache.Get(address)
if ok {
return head, nil
}
}

var hw headerWriter

// no custom common prms since a caller is expected to be a container
// participant so no additional headers, access tokens, etc
var prm getsvc.HeadPrm
prm.SetHeaderWriter(&hw)
prm.WithAddress(address)
prm.WithRawFlag(true)

err := h.getsvc.Head(context.Background(), prm)
if err != nil {
return nil, fmt.Errorf("reading header: %w", err)
}

return hw.h, nil
}
14 changes: 7 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ require (
github.com/chzyer/readline v1.5.1
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568
github.com/google/go-github/v39 v39.2.0
github.com/google/uuid v1.3.1
github.com/google/uuid v1.6.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/klauspost/compress v1.17.2
github.com/klauspost/compress v1.17.6
github.com/mitchellh/go-homedir v1.1.0
github.com/mr-tron/base58 v1.2.0
github.com/multiformats/go-multiaddr v0.12.0
github.com/nats-io/nats.go v1.31.0
github.com/nspcc-dev/hrw/v2 v2.0.0
github.com/nspcc-dev/locode-db v0.5.0
github.com/nspcc-dev/neo-go v0.105.1
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0
github.com/nspcc-dev/neofs-api-go/v2 v2.14.1-0.20240213170208-cfca09b5acbe
github.com/nspcc-dev/neofs-contract v0.19.1
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240130073207-03ed6db7e1cd
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240215154601-e1a82c5e589c
github.com/nspcc-dev/tzhash v1.7.1
github.com/olekukonko/tablewriter v0.0.5
github.com/panjf2000/ants/v2 v2.8.2
Expand All @@ -33,8 +33,8 @@ require (
go.uber.org/zap v1.26.0
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/sync v0.3.0
golang.org/x/sys v0.15.0
golang.org/x/term v0.15.0
golang.org/x/sys v0.17.0
golang.org/x/term v0.17.0
google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.31.0
gopkg.in/yaml.v3 v3.0.1
Expand Down Expand Up @@ -97,7 +97,7 @@ require (
github.com/twmb/murmur3 v1.1.8 // indirect
github.com/urfave/cli v1.22.5 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/crypto v0.19.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect
Expand Down
28 changes: 14 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLe
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
Expand All @@ -186,8 +186,8 @@ github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svo
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
Expand Down Expand Up @@ -251,14 +251,14 @@ github.com/nspcc-dev/neo-go v0.105.1 h1:r0b2yIwLBi+ARBKU94gHL9oTFEB/XMJ0YlS2HN9Q
github.com/nspcc-dev/neo-go v0.105.1/go.mod h1:GNh0cRALV/cuj+/xg2ZHDsrFbqcInqG7jjhqsLEnlNc=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231127165613-b35f351f0ba0 h1:N+dMIBmteXjJpkH6UZ7HmNftuFxkqszfGLbhsEctnv0=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231127165613-b35f351f0ba0/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkboMX5QVZhHVk=
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM=
github.com/nspcc-dev/neofs-api-go/v2 v2.14.1-0.20240213170208-cfca09b5acbe h1:Hoq88+PWS6tNnX4Y0jxE0C8wvxPI8UlVnCs2ZJDEy4Y=
github.com/nspcc-dev/neofs-api-go/v2 v2.14.1-0.20240213170208-cfca09b5acbe/go.mod h1:eaffSBIGhXUIMYvRBGXmlgQRLyyCWlzOft9jGYlqwrw=
github.com/nspcc-dev/neofs-contract v0.19.1 h1:U1Uh+MlzfkalO0kRJ2pADZyHrmAOroC6KLFjdWnTNR0=
github.com/nspcc-dev/neofs-contract v0.19.1/go.mod h1:ZOGouuwuHpgvYkx/LCGufGncIzEUhYEO18LL4cWEbyw=
github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=
github.com/nspcc-dev/neofs-crypto v0.4.0/go.mod h1:6XJ8kbXgOfevbI2WMruOtI+qUJXNwSGM/E9eClXxPHs=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240130073207-03ed6db7e1cd h1:kRIn6i7BTa55ae4cH+UcqRfH//XC20mSC4E9WcWxkmM=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240130073207-03ed6db7e1cd/go.mod h1:2PKUuH7kQaAmQ/USBgmiD/k08ssnSvayor6JAFhrC1c=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240215154601-e1a82c5e589c h1:t5Ta7JGqhYiAP3I56U91xX8kmq8HQtX3kHusISPyzas=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240215154601-e1a82c5e589c/go.mod h1:GED7qcgut188OQYY7lak/cGN8DHtjqQbrXdSt/82QNE=
github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE=
github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso=
github.com/nspcc-dev/tzhash v1.7.1 h1:6zmexLqdTF/ssbUAh7XJS7RxgKWaw28kdNpE/4UFdEU=
Expand Down Expand Up @@ -365,8 +365,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
Expand Down Expand Up @@ -508,11 +508,11 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
73 changes: 71 additions & 2 deletions pkg/core/object/fmt.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package object

import (
"context"
"errors"
"fmt"
"strconv"
Expand All @@ -23,6 +24,7 @@ type FormatValidatorOption func(*cfg)
type cfg struct {
netState netmap.State
e LockSource
sv SplitVerifier
}

// DeleteHandler is an interface of delete queue processor.
Expand All @@ -49,6 +51,12 @@ type Locker interface {
Lock(idCnr cid.ID, locker oid.ID, locked []oid.ID) error
}

// todo

Check failure on line 54 in pkg/core/object/fmt.go

View workflow job for this annotation

GitHub Actions / lint

Comment should end in a period (godot)
type SplitVerifier interface {
// todo
VerifySplit(context.Context, oid.Address, []object.MeasuredObject) error
}

var errNilObject = errors.New("object is nil")

var errNilID = errors.New("missing identifier")
Expand Down Expand Up @@ -103,6 +111,41 @@ func (v *FormatValidator) Validate(obj *object.Object, unprepared bool) error {
return err
}

_, firstSet := obj.FirstID()
splitID := obj.SplitID()
par := obj.Parent()

if obj.HasParent() {
if splitID != nil {
// V1 split
if firstSet {
return errors.New("v1 split: first ID object is set")
}
} else {
// V2 split

if !firstSet {
// first part only
if obj.Parent() == nil {
return errors.New("v2 split: first object part does not have parent header")
}
} else {
// 2nd+ parts

typ := obj.Type()

// link object only
if typ == object.TypeLink && (par == nil || par.Signature() == nil) {
return errors.New("v2 split: incorrect link object's parent header")
}

if _, hasPrevious := obj.PreviousID(); typ != object.TypeLink && !hasPrevious {
return errors.New("v2 split: middle part does not have previous object ID")
}
}
}
}

if err := v.checkAttributes(obj); err != nil {
return fmt.Errorf("invalid attributes: %w", err)
}
Expand All @@ -121,9 +164,9 @@ func (v *FormatValidator) Validate(obj *object.Object, unprepared bool) error {
}
}

if obj = obj.Parent(); obj != nil {
if par != nil {
// Parent object already exists.
return v.Validate(obj, false)
return v.Validate(obj, firstSet)
}

return nil
Expand Down Expand Up @@ -161,6 +204,7 @@ func (v *FormatValidator) validateSignatureKey(obj *object.Object) error {
// is one of:
// - object.TypeTombstone;
// - object.TypeStorageGroup;
// - object.TypeLink;
// - object.TypeLock.
type ContentMeta struct {
typ object.Type
Expand Down Expand Up @@ -191,6 +235,24 @@ func (v *FormatValidator) ValidateContent(o *object.Object) (ContentMeta, error)
switch o.Type() {
case object.TypeRegular:
// ignore regular objects, they do not need payload formatting
case object.TypeLink:
if len(o.Payload()) == 0 {
return ContentMeta{}, fmt.Errorf("(%T) empty payload in the link object", v)
}

var testLink object.Link

err := o.ReadLink(&testLink)
if err != nil {
return ContentMeta{}, fmt.Errorf("reading link object's payload: %w", err)
}

AddressOf(o)

err = v.sv.VerifySplit(context.Background(), AddressOf(o), testLink.Objects())
if err != nil {
return ContentMeta{}, fmt.Errorf("link object's split chain verification: %w", err)
}
case object.TypeTombstone:
if len(o.Payload()) == 0 {
return ContentMeta{}, fmt.Errorf("(%T) empty payload in tombstone", v)
Expand Down Expand Up @@ -392,3 +454,10 @@ func WithLockSource(e LockSource) FormatValidatorOption {
c.e = e
}
}

// todo

Check failure on line 458 in pkg/core/object/fmt.go

View workflow job for this annotation

GitHub Actions / lint

Comment should end in a period (godot)
func WithSplitVerifier(sv SplitVerifier) FormatValidatorOption {
return func(c *cfg) {
c.sv = sv
}
}
Loading

0 comments on commit 9a60f81

Please sign in to comment.