diff --git a/cmd/neofs-node/object.go b/cmd/neofs-node/object.go index 24addfe663..4fd8b12790 100644 --- a/cmd/neofs-node/object.go +++ b/cmd/neofs-node/object.go @@ -257,7 +257,11 @@ func initObjectService(c *cfg) { searchsvcV2.WithKeyStorage(keyStorage), ) + mNumber, err := c.shared.basics.cli.MagicNumber() + fatalOnErr(err) + sPut := putsvc.NewService(&transport{clients: putConstructor}, c, + putsvc.WithNetworkMagic(mNumber), putsvc.WithKeyStorage(keyStorage), putsvc.WithClientConstructor(putConstructor), putsvc.WithMaxSizeSource(newCachedMaxObjectSizeSource(c)), @@ -351,7 +355,7 @@ func initObjectService(c *cfg) { firstSvc = objectService.NewMetricCollector(signSvc, c.metricsCollector) } - server := objectTransportGRPC.New(firstSvc, objNode, neofsecdsa.SignerRFC6979(c.shared.basics.key.PrivateKey)) + server := objectTransportGRPC.New(firstSvc, mNumber, objNode, neofsecdsa.SignerRFC6979(c.shared.basics.key.PrivateKey)) for _, srv := range c.cfgGRPC.servers { objectGRPC.RegisterObjectServiceServer(srv, server) diff --git a/pkg/core/object/replicate.go b/pkg/core/object/replicate.go index 3a1daf23ea..398d8d5b54 100644 --- a/pkg/core/object/replicate.go +++ b/pkg/core/object/replicate.go @@ -10,16 +10,17 @@ import ( const ( validInterval = 10 // in epochs - currentVersion = 6 // it is also a number of fields + currentVersion = 7 // it is also a number of fields ) const ( - cidKey = "cid" - oidKey = "oid" - sizeKey = "size" - deletedKey = "deleted" - lockedKey = "locked" - validUntilKey = "validuntil" + networkMagicKey = "network" + cidKey = "cid" + oidKey = "oid" + sizeKey = "size" + deletedKey = "deleted" + lockedKey = "locked" + validUntilKey = "validuntil" ) // EncodeReplicationMetaInfo uses NEO's map (strict order) serialized format as a raw @@ -27,6 +28,7 @@ const ( // // This (ordered) format is used (keys are strings): // +// "network": network magic // "cid": _raw_ container ID (32 bytes) // "oid": _raw_ object ID (32 bytes) // "size": payload size @@ -35,8 +37,10 @@ const ( // "validuntil": last valid epoch number for meta information // // Last valid epoch is object's creation epoch + 10. -func EncodeReplicationMetaInfo(cID cid.ID, oID oid.ID, pSize uint64, deleted, locked []oid.ID, createdAt uint64) []byte { +func EncodeReplicationMetaInfo(cID cid.ID, oID oid.ID, pSize uint64, + deleted, locked []oid.ID, createdAt uint64, magicNumber uint32) []byte { kvs := []stackitem.MapElement{ + kv(networkMagicKey, magicNumber), kv(cidKey, cID[:]), kv(oidKey, oID[:]), kv(sizeKey, pSize), diff --git a/pkg/core/object/replicate_test.go b/pkg/core/object/replicate_test.go index 2503cf3e05..3f14669163 100644 --- a/pkg/core/object/replicate_test.go +++ b/pkg/core/object/replicate_test.go @@ -13,6 +13,7 @@ import ( ) func TestMetaInfo(t *testing.T) { + network := rand.Uint32() oID := oidtest.ID() cID := cidtest.ID() size := rand.Uint64() @@ -20,7 +21,7 @@ func TestMetaInfo(t *testing.T) { locked := oidtest.IDs(10) validUntil := rand.Uint64() - raw := EncodeReplicationMetaInfo(cID, oID, size, deleted, locked, validUntil) + raw := EncodeReplicationMetaInfo(cID, oID, size, deleted, locked, validUntil, network) item, err := stackitem.Deserialize(raw) require.NoError(t, err) @@ -30,23 +31,26 @@ func TestMetaInfo(t *testing.T) { require.Len(t, mm, currentVersion) - require.Equal(t, cidKey, string(mm[0].Key.Value().([]byte))) - require.Equal(t, cID[:], mm[0].Value.Value().([]byte)) + require.Equal(t, networkMagicKey, string(mm[0].Key.Value().([]byte))) + require.Equal(t, network, uint32(mm[0].Value.Value().(*big.Int).Uint64())) - require.Equal(t, oidKey, string(mm[1].Key.Value().([]byte))) - require.Equal(t, oID[:], mm[1].Value.Value().([]byte)) + require.Equal(t, cidKey, string(mm[1].Key.Value().([]byte))) + require.Equal(t, cID[:], mm[1].Value.Value().([]byte)) - require.Equal(t, sizeKey, string(mm[2].Key.Value().([]byte))) - require.Equal(t, size, mm[2].Value.Value().(*big.Int).Uint64()) + require.Equal(t, oidKey, string(mm[2].Key.Value().([]byte))) + require.Equal(t, oID[:], mm[2].Value.Value().([]byte)) - require.Equal(t, deletedKey, string(mm[3].Key.Value().([]byte))) - require.Equal(t, deleted, stackItemToOIDs(t, mm[3].Value)) + require.Equal(t, sizeKey, string(mm[3].Key.Value().([]byte))) + require.Equal(t, size, mm[3].Value.Value().(*big.Int).Uint64()) - require.Equal(t, lockedKey, string(mm[4].Key.Value().([]byte))) - require.Equal(t, locked, stackItemToOIDs(t, mm[4].Value)) + require.Equal(t, deletedKey, string(mm[4].Key.Value().([]byte))) + require.Equal(t, deleted, stackItemToOIDs(t, mm[4].Value)) - require.Equal(t, validUntilKey, string(mm[5].Key.Value().([]byte))) - require.Equal(t, validUntil+validInterval, mm[5].Value.Value().(*big.Int).Uint64()) + require.Equal(t, lockedKey, string(mm[5].Key.Value().([]byte))) + require.Equal(t, locked, stackItemToOIDs(t, mm[5].Value)) + + require.Equal(t, validUntilKey, string(mm[6].Key.Value().([]byte))) + require.Equal(t, validUntil+validInterval, mm[6].Value.Value().(*big.Int).Uint64()) } func stackItemToOIDs(t *testing.T, value stackitem.Item) []oid.ID { diff --git a/pkg/network/transport/object/grpc/replication.go b/pkg/network/transport/object/grpc/replication.go index 90f74595d0..e73f89c1ba 100644 --- a/pkg/network/transport/object/grpc/replication.go +++ b/pkg/network/transport/object/grpc/replication.go @@ -228,7 +228,8 @@ func (s *Server) metaInfoSignature(o object.Object) ([]byte, error) { default: } - metaInfo := objectcore.EncodeReplicationMetaInfo(o.GetContainerID(), o.GetID(), o.PayloadSize(), deleted, locked, o.CreationEpoch()) + metaInfo := objectcore.EncodeReplicationMetaInfo(o.GetContainerID(), o.GetID(), o.PayloadSize(), deleted, locked, + o.CreationEpoch(), s.mNumber) var sig neofscrypto.Signature err := sig.Calculate(s.signer, metaInfo) diff --git a/pkg/network/transport/object/grpc/replication_test.go b/pkg/network/transport/object/grpc/replication_test.go index 4ca247a45f..a8d4490517 100644 --- a/pkg/network/transport/object/grpc/replication_test.go +++ b/pkg/network/transport/object/grpc/replication_test.go @@ -164,7 +164,7 @@ func anyValidRequest(tb testing.TB, signer neofscrypto.Signer, cnr cid.ID, objID func TestServer_Replicate(t *testing.T) { var noCallNode noCallTestNode var noCallObjSvc noCallObjectService - noCallSrv := New(noCallObjSvc, &noCallNode, neofscryptotest.Signer()) + noCallSrv := New(noCallObjSvc, 0, &noCallNode, neofscryptotest.Signer()) clientSigner := neofscryptotest.Signer() clientPubKey := neofscrypto.PublicKeyBytes(clientSigner.Public()) serverPubKey := neofscrypto.PublicKeyBytes(neofscryptotest.Signer().Public()) @@ -328,7 +328,7 @@ func TestServer_Replicate(t *testing.T) { t.Run("apply storage policy failure", func(t *testing.T) { node := newTestNode(t, serverPubKey, clientPubKey, cnr, req.Object) - srv := New(noCallObjSvc, node, neofscryptotest.Signer()) + srv := New(noCallObjSvc, 0, node, neofscryptotest.Signer()) node.cnrErr = errors.New("any error") @@ -340,7 +340,7 @@ func TestServer_Replicate(t *testing.T) { t.Run("client or server mismatches object's storage policy", func(t *testing.T) { node := newTestNode(t, serverPubKey, clientPubKey, cnr, req.Object) - srv := New(noCallObjSvc, node, neofscryptotest.Signer()) + srv := New(noCallObjSvc, 0, node, neofscryptotest.Signer()) node.serverOutsideCnr = true node.clientOutsideCnr = true @@ -360,7 +360,7 @@ func TestServer_Replicate(t *testing.T) { t.Run("local storage failure", func(t *testing.T) { node := newTestNode(t, serverPubKey, clientPubKey, cnr, req.Object) - srv := New(noCallObjSvc, node, neofscryptotest.Signer()) + srv := New(noCallObjSvc, 0, node, neofscryptotest.Signer()) node.storeErr = errors.New("any error") @@ -371,10 +371,11 @@ func TestServer_Replicate(t *testing.T) { }) t.Run("meta information signature", func(t *testing.T) { + var mNumber uint32 = 123 signer := neofscryptotest.Signer() reqForSignature, o := anyValidRequest(t, clientSigner, cnr, objID) node := newTestNode(t, serverPubKey, clientPubKey, cnr, reqForSignature.Object) - srv := New(noCallObjSvc, node, signer) + srv := New(noCallObjSvc, mNumber, node, signer) t.Run("signature not requested", func(t *testing.T) { resp, err := srv.Replicate(context.Background(), reqForSignature) @@ -400,13 +401,13 @@ func TestServer_Replicate(t *testing.T) { require.NoError(t, sig.ReadFromV2(sigV2)) require.Equal(t, signer.PublicKeyBytes, sig.PublicKeyBytes()) - require.True(t, sig.Verify(objectcore.EncodeReplicationMetaInfo(o.GetContainerID(), o.GetID(), o.PayloadSize(), nil, nil, o.CreationEpoch()))) + require.True(t, sig.Verify(objectcore.EncodeReplicationMetaInfo(o.GetContainerID(), o.GetID(), o.PayloadSize(), nil, nil, o.CreationEpoch(), mNumber))) }) }) t.Run("OK", func(t *testing.T) { node := newTestNode(t, serverPubKey, clientPubKey, cnr, req.Object) - srv := New(noCallObjSvc, node, neofscryptotest.Signer()) + srv := New(noCallObjSvc, 0, node, neofscryptotest.Signer()) resp, err := srv.Replicate(context.Background(), req) require.NoError(t, err) @@ -433,7 +434,7 @@ func BenchmarkServer_Replicate(b *testing.B) { ctx := context.Background() var node nopNode - srv := New(nil, node, neofscryptotest.Signer()) + srv := New(nil, 0, node, neofscryptotest.Signer()) for _, tc := range []struct { name string diff --git a/pkg/network/transport/object/grpc/service.go b/pkg/network/transport/object/grpc/service.go index 2b2babdaf6..6ebe90c5c5 100644 --- a/pkg/network/transport/object/grpc/service.go +++ b/pkg/network/transport/object/grpc/service.go @@ -48,16 +48,18 @@ type Node interface { type Server struct { srv objectSvc.ServiceServer - node Node - signer neofscrypto.Signer + node Node + signer neofscrypto.Signer + mNumber uint32 } // New creates, initializes and returns Server instance. -func New(c objectSvc.ServiceServer, node Node, signer neofscrypto.Signer) *Server { +func New(c objectSvc.ServiceServer, magicNumber uint32, node Node, signer neofscrypto.Signer) *Server { return &Server{ - srv: c, - node: node, - signer: signer, + srv: c, + node: node, + signer: signer, + mNumber: magicNumber, } } diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/put/distributed.go index 225c9e6a71..7bad8c22c3 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/put/distributed.go @@ -29,9 +29,10 @@ type preparedObjectTarget interface { type distributedTarget struct { placementIterator placementIterator - obj *objectSDK.Object - objMeta object.ContentMeta - objSharedMeta []byte + obj *objectSDK.Object + objMeta object.ContentMeta + networkMagicNumber uint32 + objSharedMeta []byte localNodeInContainer bool localNodeSigner neofscrypto.Signer @@ -140,7 +141,8 @@ func (t *distributedTarget) Close() (oid.ID, error) { default: } - t.objSharedMeta = object.EncodeReplicationMetaInfo(t.obj.GetContainerID(), t.obj.GetID(), t.obj.PayloadSize(), deletedObjs, lockedObjs, t.obj.CreationEpoch()) + t.objSharedMeta = object.EncodeReplicationMetaInfo(t.obj.GetContainerID(), t.obj.GetID(), t.obj.PayloadSize(), deletedObjs, + lockedObjs, t.obj.CreationEpoch(), t.networkMagicNumber) id, _ := t.obj.ID() return id, t.placementIterator.iterateNodesForObject(id, t.sendObject) } diff --git a/pkg/services/object/put/service.go b/pkg/services/object/put/service.go index 5b14ea6377..e5b2414eb1 100644 --- a/pkg/services/object/put/service.go +++ b/pkg/services/object/put/service.go @@ -100,6 +100,8 @@ type cfg struct { clientConstructor ClientConstructor log *zap.Logger + + networkMagic uint32 } func defaultCfg() *cfg { @@ -203,3 +205,9 @@ func WithLogger(l *zap.Logger) Option { c.log = l } } + +func WithNetworkMagic(m uint32) Option { + return func(c *cfg) { + c.networkMagic = m + } +} diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 7c96e27919..46517b6bf5 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -207,6 +207,7 @@ func (p *Streamer) newCommonTarget(prm *PutInitPrm) internal.Target { withBroadcast := !localOnly && (typ == object.TypeTombstone || typ == object.TypeLock) return &distributedTarget{ + networkMagicNumber: p.networkMagic, placementIterator: placementIterator{ log: p.log, neoFSNet: p.neoFSNet,