From cf1fae8d2c6b508909a554a1721bbc41c19d4d7a Mon Sep 17 00:00:00 2001
From: Pavel Gross
Date: Tue, 12 Nov 2024 04:00:26 +0300
Subject: [PATCH] span and memory
---
src/FrostFS.SDK.Client/FrostFSClient.cs | 2 +-
.../Interfaces/IFrostFSClient.cs | 2 +-
src/FrostFS.SDK.Client/Mappers/ContainerId.cs | 2 +-
.../Mappers/Netmap/NodeInfo.cs | 2 +-
.../Mappers/Object/Object.cs | 2 +-
.../Mappers/Object/ObjectHeaderMapper.cs | 2 +-
.../Mappers/Object/ObjectId.cs | 2 +-
src/FrostFS.SDK.Client/Mappers/OwnerId.cs | 2 +-
.../Models/Chain/ChainTarget.cs | 4 +-
.../Models/Containers/FrostFsContainerId.cs | 2 +-
.../Models/Object/FrostFsObjectId.cs | 7 +-
src/FrostFS.SDK.Client/Pool/ClientWrapper.cs | 2 +-
src/FrostFS.SDK.Client/Pool/Pool.cs | 2 +-
.../Services/ApeManagerServiceProvider.cs | 4 +-
.../Services/ContainerServiceProvider.cs | 2 +-
.../Services/NetmapServiceProvider.cs | 68 ++++++---
.../Services/ObjectServiceProvider.cs | 6 +-
src/FrostFS.SDK.Client/Tools/ObjectTools.cs | 4 +-
src/FrostFS.SDK.Client/Tools/RequestSigner.cs | 40 +++---
src/FrostFS.SDK.Client/Tools/Verifier.cs | 22 +--
src/FrostFS.SDK.Cryptography/Extentions.cs | 5 +-
.../FrostFS.SDK.Cryptography.csproj | 8 ++
src/FrostFS.SDK.Cryptography/UUID.cs | 6 +-
.../Mocks/AsyncStreamRangeReaderMock.cs | 5 -
.../Mocks/AsyncStreamReaderMock.cs | 2 +-
.../ContainerServiceBase.cs | 6 +-
src/FrostFS.SDK.Tests/Mocks/ObjectMock.cs | 9 +-
src/FrostFS.SDK.Tests/ObjectTest.cs | 6 +-
src/FrostFS.SDK.Tests/SmokeClientTests.cs | 132 +++++++++---------
29 files changed, 193 insertions(+), 165 deletions(-)
diff --git a/src/FrostFS.SDK.Client/FrostFSClient.cs b/src/FrostFS.SDK.Client/FrostFSClient.cs
index 8dc4d3f..281e5f3 100644
--- a/src/FrostFS.SDK.Client/FrostFSClient.cs
+++ b/src/FrostFS.SDK.Client/FrostFSClient.cs
@@ -175,7 +175,7 @@ public class FrostFSClient : IFrostFSClient
}
#region ApeManagerImplementation
- public Task AddChainAsync(PrmApeChainAdd args)
+ public Task> AddChainAsync(PrmApeChainAdd args)
{
if (args is null)
{
diff --git a/src/FrostFS.SDK.Client/Interfaces/IFrostFSClient.cs b/src/FrostFS.SDK.Client/Interfaces/IFrostFSClient.cs
index 5749249..5aacc58 100644
--- a/src/FrostFS.SDK.Client/Interfaces/IFrostFSClient.cs
+++ b/src/FrostFS.SDK.Client/Interfaces/IFrostFSClient.cs
@@ -21,7 +21,7 @@ public interface IFrostFSClient : IDisposable
#endregion
#region ApeManager
- Task AddChainAsync(PrmApeChainAdd args);
+ Task> AddChainAsync(PrmApeChainAdd args);
Task RemoveChainAsync(PrmApeChainRemove args);
diff --git a/src/FrostFS.SDK.Client/Mappers/ContainerId.cs b/src/FrostFS.SDK.Client/Mappers/ContainerId.cs
index fe8632f..df27320 100644
--- a/src/FrostFS.SDK.Client/Mappers/ContainerId.cs
+++ b/src/FrostFS.SDK.Client/Mappers/ContainerId.cs
@@ -43,6 +43,6 @@ public static class ContainerIdMapper
throw new ArgumentNullException(nameof(message));
}
- return new FrostFsContainerId(Base58.Encode(message.Value.ToByteArray()));
+ return new FrostFsContainerId(Base58.Encode(message.Value.Span));
}
}
\ No newline at end of file
diff --git a/src/FrostFS.SDK.Client/Mappers/Netmap/NodeInfo.cs b/src/FrostFS.SDK.Client/Mappers/Netmap/NodeInfo.cs
index 747468b..d7340eb 100644
--- a/src/FrostFS.SDK.Client/Mappers/Netmap/NodeInfo.cs
+++ b/src/FrostFS.SDK.Client/Mappers/Netmap/NodeInfo.cs
@@ -39,7 +39,7 @@ public static class NodeInfoMapper
state: state,
addresses: [.. nodeInfo.Addresses],
attributes: nodeInfo.Attributes.ToDictionary(n => n.Key, n => n.Value),
- publicKey: nodeInfo.PublicKey.ToByteArray()
+ publicKey: nodeInfo.PublicKey.Memory
);
}
}
\ No newline at end of file
diff --git a/src/FrostFS.SDK.Client/Mappers/Object/Object.cs b/src/FrostFS.SDK.Client/Mappers/Object/Object.cs
index b9d1520..5f85fc5 100644
--- a/src/FrostFS.SDK.Client/Mappers/Object/Object.cs
+++ b/src/FrostFS.SDK.Client/Mappers/Object/Object.cs
@@ -6,7 +6,7 @@ internal static class ObjectMapper
{
return new FrostFsObject(obj.Header.ToModel())
{
- ObjectId = FrostFsObjectId.FromHash(obj.ObjectId.Value.ToByteArray())
+ ObjectId = FrostFsObjectId.FromHash(obj.ObjectId.Value.Span)
};
}
}
diff --git a/src/FrostFS.SDK.Client/Mappers/Object/ObjectHeaderMapper.cs b/src/FrostFS.SDK.Client/Mappers/Object/ObjectHeaderMapper.cs
index 1ee29a6..317b31c 100644
--- a/src/FrostFS.SDK.Client/Mappers/Object/ObjectHeaderMapper.cs
+++ b/src/FrostFS.SDK.Client/Mappers/Object/ObjectHeaderMapper.cs
@@ -40,7 +40,7 @@ public static class ObjectHeaderMapper
}
var model = new FrostFsObjectHeader(
- new FrostFsContainerId(Base58.Encode(header.ContainerId.Value.ToByteArray())),
+ new FrostFsContainerId(Base58.Encode(header.ContainerId.Value.Span)),
objTypeName,
header.Attributes.Select(attribute => attribute.ToModel()).ToArray(),
split,
diff --git a/src/FrostFS.SDK.Client/Mappers/Object/ObjectId.cs b/src/FrostFS.SDK.Client/Mappers/Object/ObjectId.cs
index 373edfb..343e3de 100644
--- a/src/FrostFS.SDK.Client/Mappers/Object/ObjectId.cs
+++ b/src/FrostFS.SDK.Client/Mappers/Object/ObjectId.cs
@@ -28,6 +28,6 @@ public static class ObjectIdMapper
throw new ArgumentNullException(nameof(objectId));
}
- return FrostFsObjectId.FromHash(objectId.Value.ToByteArray());
+ return FrostFsObjectId.FromHash(objectId.Value.Span);
}
}
\ No newline at end of file
diff --git a/src/FrostFS.SDK.Client/Mappers/OwnerId.cs b/src/FrostFS.SDK.Client/Mappers/OwnerId.cs
index 297178a..6739a0b 100644
--- a/src/FrostFS.SDK.Client/Mappers/OwnerId.cs
+++ b/src/FrostFS.SDK.Client/Mappers/OwnerId.cs
@@ -44,7 +44,7 @@ public static class OwnerIdMapper
if (!Caches.Owners.TryGetValue(message, out FrostFsOwner? model))
{
- model = new FrostFsOwner(Base58.Encode(message.Value.ToByteArray()));
+ model = new FrostFsOwner(Base58.Encode(message.Value.Span));
Caches.Owners.Set(message, model, _oneHourExpiration);
}
diff --git a/src/FrostFS.SDK.Client/Models/Chain/ChainTarget.cs b/src/FrostFS.SDK.Client/Models/Chain/ChainTarget.cs
index dd52835..8a17363 100644
--- a/src/FrostFS.SDK.Client/Models/Chain/ChainTarget.cs
+++ b/src/FrostFS.SDK.Client/Models/Chain/ChainTarget.cs
@@ -45,12 +45,12 @@ public struct FrostFsChainTarget(FrostFsTargetType type, string name) : IEquatab
return $"{Name}{Type}".GetHashCode(StringComparison.InvariantCulture);
}
- public static bool operator == (FrostFsChainTarget left, FrostFsChainTarget right)
+ public static bool operator ==(FrostFsChainTarget left, FrostFsChainTarget right)
{
return left.Equals(right);
}
- public static bool operator != (FrostFsChainTarget left, FrostFsChainTarget right)
+ public static bool operator !=(FrostFsChainTarget left, FrostFsChainTarget right)
{
return !(left == right);
}
diff --git a/src/FrostFS.SDK.Client/Models/Containers/FrostFsContainerId.cs b/src/FrostFS.SDK.Client/Models/Containers/FrostFsContainerId.cs
index f0b3fdf..9f081cd 100644
--- a/src/FrostFS.SDK.Client/Models/Containers/FrostFsContainerId.cs
+++ b/src/FrostFS.SDK.Client/Models/Containers/FrostFsContainerId.cs
@@ -27,7 +27,7 @@ public class FrostFsContainerId
if (containerID != null)
{
- this.modelId = Base58.Encode(containerID.Value.ToByteArray());
+ this.modelId = Base58.Encode(containerID.Value.Span);
return this.modelId;
}
diff --git a/src/FrostFS.SDK.Client/Models/Object/FrostFsObjectId.cs b/src/FrostFS.SDK.Client/Models/Object/FrostFsObjectId.cs
index 49fde5a..57300a3 100644
--- a/src/FrostFS.SDK.Client/Models/Object/FrostFsObjectId.cs
+++ b/src/FrostFS.SDK.Client/Models/Object/FrostFsObjectId.cs
@@ -8,13 +8,8 @@ public class FrostFsObjectId(string id)
{
public string Value { get; } = id;
- public static FrostFsObjectId FromHash(byte[] hash)
+ public static FrostFsObjectId FromHash(ReadOnlySpan hash)
{
- if (hash is null)
- {
- throw new ArgumentNullException(nameof(hash));
- }
-
if (hash.Length != Constants.Sha256HashLength)
throw new FormatException("ObjectID must be a sha256 hash.");
diff --git a/src/FrostFS.SDK.Client/Pool/ClientWrapper.cs b/src/FrostFS.SDK.Client/Pool/ClientWrapper.cs
index 87a80b0..547577b 100644
--- a/src/FrostFS.SDK.Client/Pool/ClientWrapper.cs
+++ b/src/FrostFS.SDK.Client/Pool/ClientWrapper.cs
@@ -106,7 +106,7 @@ public class ClientWrapper : ClientStatusMonitor
try
{
client = new(WrapperPrm, sessionCache);
-
+
//TODO: set additioanl params
var error = await client.Dial(ctx).ConfigureAwait(false);
if (!string.IsNullOrEmpty(error))
diff --git a/src/FrostFS.SDK.Client/Pool/Pool.cs b/src/FrostFS.SDK.Client/Pool/Pool.cs
index 44ae06a..bd43d1e 100644
--- a/src/FrostFS.SDK.Client/Pool/Pool.cs
+++ b/src/FrostFS.SDK.Client/Pool/Pool.cs
@@ -560,7 +560,7 @@ public partial class Pool : IFrostFSClient
return await client.Client!.CreateSessionAsync(args).ConfigureAwait(false);
}
- public async Task AddChainAsync(PrmApeChainAdd args)
+ public async Task> AddChainAsync(PrmApeChainAdd args)
{
if (args is null)
{
diff --git a/src/FrostFS.SDK.Client/Services/ApeManagerServiceProvider.cs b/src/FrostFS.SDK.Client/Services/ApeManagerServiceProvider.cs
index 840223d..84cc60a 100644
--- a/src/FrostFS.SDK.Client/Services/ApeManagerServiceProvider.cs
+++ b/src/FrostFS.SDK.Client/Services/ApeManagerServiceProvider.cs
@@ -16,7 +16,7 @@ internal sealed class ApeManagerServiceProvider : ContextAccessor
_apeManagerServiceClient = apeManagerServiceClient;
}
- internal async Task AddChainAsync(PrmApeChainAdd args)
+ internal async Task> AddChainAsync(PrmApeChainAdd args)
{
var ctx = args.Context!;
ctx.Key ??= ClientContext.Key?.ECDsaKey;
@@ -40,7 +40,7 @@ internal sealed class ApeManagerServiceProvider : ContextAccessor
Verifier.CheckResponse(response);
- return response.Body.ChainId.ToByteArray();
+ return response.Body.ChainId.Memory;
}
internal async Task RemoveChainAsync(PrmApeChainRemove args)
diff --git a/src/FrostFS.SDK.Client/Services/ContainerServiceProvider.cs b/src/FrostFS.SDK.Client/Services/ContainerServiceProvider.cs
index 3a0379e..57ee865 100644
--- a/src/FrostFS.SDK.Client/Services/ContainerServiceProvider.cs
+++ b/src/FrostFS.SDK.Client/Services/ContainerServiceProvider.cs
@@ -68,7 +68,7 @@ internal sealed class ContainerServiceProvider(ContainerService.ContainerService
foreach (var cid in response.Body.ContainerIds)
{
- yield return new FrostFsContainerId(Base58.Encode(cid.Value.ToByteArray()));
+ yield return new FrostFsContainerId(Base58.Encode(cid.Value.Span));
}
}
diff --git a/src/FrostFS.SDK.Client/Services/NetmapServiceProvider.cs b/src/FrostFS.SDK.Client/Services/NetmapServiceProvider.cs
index 18649d8..8df02c9 100644
--- a/src/FrostFS.SDK.Client/Services/NetmapServiceProvider.cs
+++ b/src/FrostFS.SDK.Client/Services/NetmapServiceProvider.cs
@@ -1,6 +1,4 @@
using System;
-using System.Linq;
-using System.Text;
using System.Threading.Tasks;
using FrostFS.Netmap;
@@ -107,12 +105,16 @@ internal sealed class NetmapServiceProvider : ContextAccessor
return response.ToModel();
}
- private static bool GetBoolValue(byte[] bytes)
+ private static bool GetBoolValue(ReadOnlySpan bytes)
{
- return bytes.Any(b => b != 0);
+ for (int i = bytes.Length - 1; i >= 0; i--)
+ if (bytes[i] != 0)
+ return true;
+
+ return false;
}
- private static ulong GetLongValue(byte[] bytes)
+ private static ulong GetLongValue(ReadOnlySpan bytes)
{
ulong val = 0;
for (var i = bytes.Length - 1; i >= 0; i--)
@@ -123,24 +125,50 @@ internal sealed class NetmapServiceProvider : ContextAccessor
private static void SetNetworksParam(Parameter param, NetworkSettings settings)
{
- var key = Encoding.UTF8.GetString(param.Key.ToByteArray());
+ var key = param.Key.ToStringUtf8();
- var valueBytes = param.Value.ToByteArray();
+ var valueBytes = param.Value.Span;
switch (key)
{
- case "AuditFee": settings.AuditFee = GetLongValue(valueBytes); break;
- case "BasicIncomeRate": settings.BasicIncomeRate = GetLongValue(valueBytes); break;
- case "ContainerFee": settings.ContainerFee = GetLongValue(valueBytes); break;
- case "ContainerAliasFee": settings.ContainerAliasFee = GetLongValue(valueBytes); break;
- case "EpochDuration": settings.EpochDuration = GetLongValue(valueBytes); break;
- case "InnerRingCandidateFee": settings.InnerRingCandidateFee = GetLongValue(valueBytes); break;
- case "MaxECDataCount": settings.MaxECDataCount = GetLongValue(valueBytes); break;
- case "MaxECParityCount": settings.MaxECParityCount = GetLongValue(valueBytes); break;
- case "MaxObjectSize": settings.MaxObjectSize = GetLongValue(valueBytes); break;
- case "WithdrawFee": settings.WithdrawFee = GetLongValue(valueBytes); break;
- case "HomomorphicHashingDisabled": settings.HomomorphicHashingDisabled = GetBoolValue(valueBytes); break;
- case "MaintenanceModeAllowed": settings.MaintenanceModeAllowed = GetBoolValue(valueBytes); break;
- default: settings.UnnamedSettings.Add(key, valueBytes); break;
+ case "AuditFee":
+ settings.AuditFee = GetLongValue(valueBytes);
+ break;
+ case "BasicIncomeRate":
+ settings.BasicIncomeRate = GetLongValue(valueBytes);
+ break;
+ case "ContainerFee":
+ settings.ContainerFee = GetLongValue(valueBytes);
+ break;
+ case "ContainerAliasFee":
+ settings.ContainerAliasFee = GetLongValue(valueBytes);
+ break;
+ case "EpochDuration":
+ settings.EpochDuration = GetLongValue(valueBytes);
+ break;
+ case "InnerRingCandidateFee":
+ settings.InnerRingCandidateFee = GetLongValue(valueBytes);
+ break;
+ case "MaxECDataCount":
+ settings.MaxECDataCount = GetLongValue(valueBytes);
+ break;
+ case "MaxECParityCount":
+ settings.MaxECParityCount = GetLongValue(valueBytes);
+ break;
+ case "MaxObjectSize":
+ settings.MaxObjectSize = GetLongValue(valueBytes);
+ break;
+ case "WithdrawFee":
+ settings.WithdrawFee = GetLongValue(valueBytes);
+ break;
+ case "HomomorphicHashingDisabled":
+ settings.HomomorphicHashingDisabled = GetBoolValue(valueBytes);
+ break;
+ case "MaintenanceModeAllowed":
+ settings.MaintenanceModeAllowed = GetBoolValue(valueBytes);
+ break;
+ default:
+ settings.UnnamedSettings.Add(key, valueBytes.ToArray());
+ break;
}
}
}
diff --git a/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs b/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs
index cc1440a..8c42b43 100644
--- a/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs
+++ b/src/FrostFS.SDK.Client/Services/ObjectServiceProvider.cs
@@ -271,7 +271,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
await foreach (var oid in objectsIds)
{
- yield return FrostFsObjectId.FromHash(oid.Value.ToByteArray());
+ yield return FrostFsObjectId.FromHash(oid.Value.Span);
}
}
@@ -332,7 +332,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
Verifier.CheckResponse(response);
- return FrostFsObjectId.FromHash(grpcObject.ObjectId.Value.ToByteArray());
+ return FrostFsObjectId.FromHash(grpcObject.ObjectId.Value.Span);
}
internal async Task PatchObjectAsync(PrmObjectPatch args)
@@ -589,7 +589,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
var response = await stream.Close().ConfigureAwait(false);
Verifier.CheckResponse(response);
- return new PutObjectResult(FrostFsObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray()), sentBytes);
+ return new PutObjectResult(FrostFsObjectId.FromHash(response.Body.ObjectId.Value.Span), sentBytes);
}
finally
{
diff --git a/src/FrostFS.SDK.Client/Tools/ObjectTools.cs b/src/FrostFS.SDK.Client/Tools/ObjectTools.cs
index f20cacd..621069b 100644
--- a/src/FrostFS.SDK.Client/Tools/ObjectTools.cs
+++ b/src/FrostFS.SDK.Client/Tools/ObjectTools.cs
@@ -47,7 +47,7 @@ internal static class ObjectTools
obj.Signature = new Signature
{
Key = ctx.GetPublicKeyCache(),
- Sign = ByteString.CopyFrom(ctx.Key!.SignData(obj.ObjectId.ToByteArray())),
+ Sign = ctx.Key!.SignData(obj.ObjectId.ToByteArray()),
};
return obj;
@@ -78,7 +78,7 @@ internal static class ObjectTools
grpcHeader.Split.ParentSignature = new Signature
{
Key = ctx.GetPublicKeyCache(),
- Sign = ByteString.CopyFrom(ctx.Key.SignData(grpcHeader.Split.Parent.ToByteArray())),
+ Sign = ctx.Key.SignData(grpcHeader.Split.Parent.ToByteArray()),
};
}
diff --git a/src/FrostFS.SDK.Client/Tools/RequestSigner.cs b/src/FrostFS.SDK.Client/Tools/RequestSigner.cs
index a45c569..9222e11 100644
--- a/src/FrostFS.SDK.Client/Tools/RequestSigner.cs
+++ b/src/FrostFS.SDK.Client/Tools/RequestSigner.cs
@@ -20,18 +20,13 @@ public static class RequestSigner
{
internal const int RFC6979SignatureSize = 64;
- internal static byte[] SignRFC6979(this ECDsa key, byte[] data)
+ internal static ByteString SignRFC6979(this ECDsa key, byte[] data)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
- if (data is null)
- {
- throw new ArgumentNullException(nameof(data));
- }
-
var digest = new Sha256Digest();
var secp256R1 = SecNamedCurves.GetByName("secp256r1");
var ecParameters = new ECDomainParameters(secp256R1.Curve, secp256R1.G, secp256R1.N);
@@ -44,16 +39,18 @@ public static class RequestSigner
signer.Init(true, privateKey);
var rs = signer.GenerateSignature(hash);
- var signature = new byte[RFC6979SignatureSize];
+
+ Span signature = stackalloc byte[RFC6979SignatureSize];
+
var rbytes = rs[0].ToByteArrayUnsigned();
var sbytes = rs[1].ToByteArrayUnsigned();
var index = RFC6979SignatureSize / 2 - rbytes.Length;
- rbytes.CopyTo(signature, index);
+ rbytes.AsSpan().CopyTo(signature[index..]);
index = RFC6979SignatureSize - sbytes.Length;
- sbytes.CopyTo(signature, index);
+ sbytes.AsSpan().CopyTo(signature[index..]);
- return signature;
+ return ByteString.CopyFrom(signature);
}
internal static SignatureRFC6979 SignRFC6979(this ECDsa key, IMessage message)
@@ -61,7 +58,7 @@ public static class RequestSigner
return new SignatureRFC6979
{
Key = ByteString.CopyFrom(key.PublicKey()),
- Sign = ByteString.CopyFrom(key.SignRFC6979(message.ToByteArray())),
+ Sign = key.SignRFC6979(message.ToByteArray())
};
}
@@ -70,23 +67,29 @@ public static class RequestSigner
return new SignatureRFC6979
{
Key = ByteString.CopyFrom(key.PublicKey()),
- Sign = ByteString.CopyFrom(key.SignRFC6979(data.ToByteArray())),
+ Sign = key.SignRFC6979(data.ToByteArray()),
};
}
- public static byte[] SignData(this ECDsa key, byte[] data)
+ public static ByteString SignData(this ECDsa key, ReadOnlySpan data)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
- var hash = new byte[65];
- hash[0] = 0x04;
+ Span dataHash = stackalloc byte[64];
+ data.Sha512(ref dataHash);
- key.SignHash(data.Sha512()).CopyTo(hash, 1);
+ Span hash = stackalloc byte[64];
+ key.TrySignHash(dataHash, hash, out _);
- return hash;
+ Span result = stackalloc byte[65];
+ result[0] = 0x04;
+
+ hash.CopyTo(result[1..]);
+
+ return ByteString.CopyFrom(result);
}
internal static Signature SignMessagePart(this ECDsa key, IMessage? data)
@@ -95,12 +98,11 @@ public static class RequestSigner
var sig = new Signature
{
Key = ByteString.CopyFrom(key.PublicKey()),
- Sign = ByteString.CopyFrom(key.SignData(data2Sign)),
+ Sign = key.SignData(data2Sign),
};
return sig;
}
-
internal static void Sign(this IVerifiableMessage message, ECDsa key)
{
var meta = message.GetMetaHeader();
diff --git a/src/FrostFS.SDK.Client/Tools/Verifier.cs b/src/FrostFS.SDK.Client/Tools/Verifier.cs
index bc8dd31..c4df11a 100644
--- a/src/FrostFS.SDK.Client/Tools/Verifier.cs
+++ b/src/FrostFS.SDK.Client/Tools/Verifier.cs
@@ -33,11 +33,14 @@ public static class Verifier
return rs;
}
- public static bool VerifyRFC6979(this byte[] publicKey, byte[] data, byte[] sig)
+ public static bool VerifyRFC6979(this byte[] publicKey, IMessage message, ByteString signature)
{
- if (publicKey is null || data is null || sig is null)
+ if (publicKey is null || message is null || signature is null)
return false;
+ byte[] sig = signature.ToByteArray();
+ byte[] data = message.ToByteArray();
+
var rs = DecodeSignature(sig);
var digest = new Sha256Digest();
var signer = new ECDsaSigner(new HMacDsaKCalculator(digest));
@@ -60,21 +63,22 @@ public static class Verifier
throw new ArgumentNullException(nameof(signature));
}
- return signature.Key.ToByteArray().VerifyRFC6979(message.ToByteArray(), signature.Sign.ToByteArray());
+ return signature.Key.ToByteArray().VerifyRFC6979(message, signature.Sign);
}
- public static bool VerifyData(this ECDsa key, byte[] data, byte[] sig)
+ public static bool VerifyData(this ECDsa key, ReadOnlySpan data, ByteString sig)
{
if (key is null)
throw new ArgumentNullException(nameof(key));
- if (data is null)
- throw new ArgumentNullException(nameof(data));
-
if (sig is null)
throw new ArgumentNullException(nameof(sig));
- return key.VerifyHash(data.Sha512(), sig[1..]);
+ Span hash = stackalloc byte[64];
+
+ data.Sha512(ref hash);
+
+ return key.VerifyHash(hash, sig.Span[1..]);
}
public static bool VerifyMessagePart(this Signature sig, IMessage data)
@@ -85,7 +89,7 @@ public static class Verifier
using var key = sig.Key.ToByteArray().LoadPublicKey();
var data2Verify = data is null ? [] : data.ToByteArray();
- return key.VerifyData(data2Verify, sig.Sign.ToByteArray());
+ return key.VerifyData(data2Verify, sig.Sign);
}
internal static bool VerifyMatryoskaLevel(IMessage body, IMetaHeader meta, IVerificationHeader verification)
diff --git a/src/FrostFS.SDK.Cryptography/Extentions.cs b/src/FrostFS.SDK.Cryptography/Extentions.cs
index 9d61972..cb68153 100644
--- a/src/FrostFS.SDK.Cryptography/Extentions.cs
+++ b/src/FrostFS.SDK.Cryptography/Extentions.cs
@@ -1,3 +1,4 @@
+using System;
using System.Security.Cryptography;
using System.Threading;
@@ -46,14 +47,14 @@ public static class Extentions
}
}
- public static byte[] Sha512(this byte[] value)
+ public static void Sha512(this ReadOnlySpan value, ref Span hash)
{
bool lockTaken = false;
try
{
_spinlockSha512.Enter(ref lockTaken);
- return _sha512.ComputeHash(value);
+ _sha512.TryComputeHash(value, hash, out _);
}
finally
{
diff --git a/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj b/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj
index f33a107..5cbd8d5 100644
--- a/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj
+++ b/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj
@@ -10,6 +10,14 @@
true
+
+ $(DefineConstants);NETSTANDARD2_1_OR_GREATER
+
+
+
+ $(DefineConstants);NETSTANDARD2_1_OR_GREATER
+
+
diff --git a/src/FrostFS.SDK.Cryptography/UUID.cs b/src/FrostFS.SDK.Cryptography/UUID.cs
index c92a874..94fba3f 100644
--- a/src/FrostFS.SDK.Cryptography/UUID.cs
+++ b/src/FrostFS.SDK.Cryptography/UUID.cs
@@ -11,9 +11,7 @@ public static class UUIDExtension
if (id == null)
throw new ArgumentNullException(nameof(id));
- var bytes = id.ToByteArray();
-
- var orderedBytes = GetGuidBytesDirectOrder(bytes);
+ var orderedBytes = GetGuidBytesDirectOrder(id.Span);
return new Guid(orderedBytes);
}
@@ -32,7 +30,7 @@ public static class UUIDExtension
return orderedBytes;
}
- private static byte[] GetGuidBytesDirectOrder(byte[] source)
+ private static byte[] GetGuidBytesDirectOrder(ReadOnlySpan source)
{
if (source.Length != 16)
throw new ArgumentException("Wrong uuid binary format");
diff --git a/src/FrostFS.SDK.Tests/Mocks/AsyncStreamRangeReaderMock.cs b/src/FrostFS.SDK.Tests/Mocks/AsyncStreamRangeReaderMock.cs
index d1366c7..bd9d858 100644
--- a/src/FrostFS.SDK.Tests/Mocks/AsyncStreamRangeReaderMock.cs
+++ b/src/FrostFS.SDK.Tests/Mocks/AsyncStreamRangeReaderMock.cs
@@ -1,9 +1,4 @@
-using System.Security.Cryptography;
-
using FrostFS.Object;
-using FrostFS.SDK.Client;
-using FrostFS.SDK.Client.Mappers.GRPC;
-using FrostFS.SDK.Cryptography;
using FrostFS.Session;
using Google.Protobuf;
diff --git a/src/FrostFS.SDK.Tests/Mocks/AsyncStreamReaderMock.cs b/src/FrostFS.SDK.Tests/Mocks/AsyncStreamReaderMock.cs
index c09df83..c2e30a4 100644
--- a/src/FrostFS.SDK.Tests/Mocks/AsyncStreamReaderMock.cs
+++ b/src/FrostFS.SDK.Tests/Mocks/AsyncStreamReaderMock.cs
@@ -43,7 +43,7 @@ public class AsyncStreamReaderMock(string key, FrostFsObjectHeader objectHeader)
Signature = new Refs.Signature
{
Key = ByteString.CopyFrom(Key.PublicKey()),
- Sign = ByteString.CopyFrom(Key.SignData(header.ToByteArray())),
+ Sign = Key.SignData(header.ToByteArray())
}
}
},
diff --git a/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/ContainerServiceBase.cs b/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/ContainerServiceBase.cs
index ca1c670..8d4230c 100644
--- a/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/ContainerServiceBase.cs
+++ b/src/FrostFS.SDK.Tests/Mocks/ContainerServiceMocks/ContainerServiceBase.cs
@@ -46,19 +46,19 @@ public abstract class ServiceBase(string key)
{
Key = ByteString.CopyFrom(Key.PublicKey()),
Scheme = Refs.SignatureScheme.EcdsaRfc6979Sha256,
- Sign = ByteString.CopyFrom(Key.SignData(response.MetaHeader.ToByteArray()))
+ Sign = Key.SignData(response.MetaHeader.ToByteArray())
},
BodySignature = new Refs.Signature
{
Key = ByteString.CopyFrom(Key.PublicKey()),
Scheme = Refs.SignatureScheme.EcdsaRfc6979Sha256,
- Sign = ByteString.CopyFrom(Key.SignData(response.GetBody().ToByteArray()))
+ Sign = Key.SignData(response.GetBody().ToByteArray())
},
OriginSignature = new Refs.Signature
{
Key = ByteString.CopyFrom(Key.PublicKey()),
Scheme = Refs.SignatureScheme.EcdsaRfc6979Sha256,
- Sign = ByteString.CopyFrom(Key.SignData([]))
+ Sign = Key.SignData([])
}
};
diff --git a/src/FrostFS.SDK.Tests/Mocks/ObjectMock.cs b/src/FrostFS.SDK.Tests/Mocks/ObjectMock.cs
index 4b2b5c1..4f07e41 100644
--- a/src/FrostFS.SDK.Tests/Mocks/ObjectMock.cs
+++ b/src/FrostFS.SDK.Tests/Mocks/ObjectMock.cs
@@ -5,7 +5,6 @@ using FrostFS.Object;
using FrostFS.SDK.Client;
using FrostFS.SDK.Client.Mappers.GRPC;
using FrostFS.SDK.Cryptography;
-using FrostFS.Session;
using Google.Protobuf;
@@ -41,7 +40,7 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
public GetRangeHashRequest? GetRangeHashRequest { get; set; }
- public Collection RangeHashResponses { get; } = [];
+ public Collection RangeHashResponses { get; } = [];
public override Mock GetMock()
{
@@ -94,7 +93,7 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
headResponse.Body.Header.Signature = new Refs.Signature
{
Key = ByteString.CopyFrom(Key.PublicKey()),
- Sign = ByteString.CopyFrom(Key.SignData(headResponse.Body.Header.ToByteArray())),
+ Sign = Key.SignData(headResponse.Body.Header.ToByteArray()),
};
headResponse.VerifyHeader = GetResponseVerificationHeader(headResponse);
@@ -259,7 +258,7 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
response.Body.HashList.Add(hash);
}
}
-
+
response.VerifyHeader = GetResponseVerificationHeader(response);
return new AsyncUnaryCall(
@@ -281,7 +280,7 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
{
Body = new PatchResponse.Types.Body
{
- ObjectId = new Refs.ObjectID { Value = ByteString.CopyFrom(SHA256.HashData([1,2,3])) },
+ ObjectId = new Refs.ObjectID { Value = ByteString.CopyFrom(SHA256.HashData([1, 2, 3])) },
},
MetaHeader = ResponseMetaHeader
};
diff --git a/src/FrostFS.SDK.Tests/ObjectTest.cs b/src/FrostFS.SDK.Tests/ObjectTest.cs
index a5f9f01..d11dc60 100644
--- a/src/FrostFS.SDK.Tests/ObjectTest.cs
+++ b/src/FrostFS.SDK.Tests/ObjectTest.cs
@@ -10,8 +10,6 @@ using FrostFS.SDK.Cryptography;
using Google.Protobuf;
-using static FrostFS.Object.ECInfo.Types;
-
namespace FrostFS.SDK.Tests;
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for tests")]
@@ -339,9 +337,9 @@ public class ObjectTest : ObjectTestsBase
Assert.Equal(address.ContainerId, body.Address.ContainerId);
Assert.Equal(address.ObjectId, body.Address.ObjectId);
-
+
Assert.Equal(32, body.Patch.Chunk.Length);
-
+
Assert.Equal(SHA256.HashData(patch), SHA256.HashData(body.Patch.Chunk.ToArray()));
}
}
diff --git a/src/FrostFS.SDK.Tests/SmokeClientTests.cs b/src/FrostFS.SDK.Tests/SmokeClientTests.cs
index ba822c7..1909526 100644
--- a/src/FrostFS.SDK.Tests/SmokeClientTests.cs
+++ b/src/FrostFS.SDK.Tests/SmokeClientTests.cs
@@ -248,83 +248,83 @@ public class SmokeClientTests : SmokeTestsBase
[InlineData(6 * 1024 * 1024 + 100)]
public async void SimpleScenarioTest(int objectSize)
{
- using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url));
+ using var client = FrostFSClient.GetSingleOwnerInstance(GetSingleOwnerOptions(this.keyString, this.url));
- await Cleanup(client);
+ await Cleanup(client);
- bool callbackInvoked = false;
- var ctx = new CallContext
+ bool callbackInvoked = false;
+ var ctx = new CallContext
+ {
+ // Timeout = TimeSpan.FromSeconds(20),
+ Callback = new((CallStatistics cs) =>
{
- // Timeout = TimeSpan.FromSeconds(20),
- Callback = new((CallStatistics cs) =>
- {
- callbackInvoked = true;
- Assert.True(cs.ElapsedMicroSeconds > 0);
- })
- };
-
- var createContainerParam = new PrmContainerCreate(
- new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, new FrostFsReplica(1)), [new("testKey", "testValue")]), ctx);
-
- var createdContainer = await client.CreateContainerAsync(createContainerParam);
-
- var container = await client.GetContainerAsync(new PrmContainerGet(createdContainer, ctx));
- Assert.NotNull(container);
- Assert.True(callbackInvoked);
-
- var bytes = GetRandomBytes(objectSize);
-
- var param = new PrmObjectPut(new CallContext
- {
- Callback = new((CallStatistics cs) => Assert.True(cs.ElapsedMicroSeconds > 0))
+ callbackInvoked = true;
+ Assert.True(cs.ElapsedMicroSeconds > 0);
})
- {
- Header = new FrostFsObjectHeader(
- containerId: createdContainer,
- type: FrostFsObjectType.Regular,
- [new FrostFsAttributePair("fileName", "test")]),
- Payload = new MemoryStream(bytes),
- ClientCut = false
- };
+ };
- var objectId = await client.PutObjectAsync(param);
+ var createContainerParam = new PrmContainerCreate(
+ new FrostFsContainerInfo(new FrostFsPlacementPolicy(true, new FrostFsReplica(1)), [new("testKey", "testValue")]), ctx);
- var filter = new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test");
+ var createdContainer = await client.CreateContainerAsync(createContainerParam);
- bool hasObject = false;
- await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(createdContainer) { Filters = [filter] }))
- {
- hasObject = true;
+ var container = await client.GetContainerAsync(new PrmContainerGet(createdContainer, ctx));
+ Assert.NotNull(container);
+ Assert.True(callbackInvoked);
- var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(createdContainer, objectId));
- Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength);
- Assert.NotNull(objHeader.Attributes);
- Assert.Single(objHeader.Attributes);
- Assert.Equal("fileName", objHeader.Attributes.First().Key);
- Assert.Equal("test", objHeader.Attributes.First().Value);
- }
+ var bytes = GetRandomBytes(objectSize);
- Assert.True(hasObject);
+ var param = new PrmObjectPut(new CallContext
+ {
+ Callback = new((CallStatistics cs) => Assert.True(cs.ElapsedMicroSeconds > 0))
+ })
+ {
+ Header = new FrostFsObjectHeader(
+ containerId: createdContainer,
+ type: FrostFsObjectType.Regular,
+ [new FrostFsAttributePair("fileName", "test")]),
+ Payload = new MemoryStream(bytes),
+ ClientCut = false
+ };
- var @object = await client.GetObjectAsync(new PrmObjectGet(createdContainer, objectId));
+ var objectId = await client.PutObjectAsync(param);
- var downloadedBytes = new byte[@object.Header.PayloadLength];
- MemoryStream ms = new(downloadedBytes);
+ var filter = new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test");
- ReadOnlyMemory? chunk = null;
- while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
- {
- ms.Write(chunk.Value.Span);
- }
+ bool hasObject = false;
+ await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(createdContainer) { Filters = [filter] }))
+ {
+ hasObject = true;
- Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
+ var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(createdContainer, objectId));
+ Assert.Equal((ulong)bytes.Length, objHeader.PayloadLength);
+ Assert.NotNull(objHeader.Attributes);
+ Assert.Single(objHeader.Attributes);
+ Assert.Equal("fileName", objHeader.Attributes.First().Key);
+ Assert.Equal("test", objHeader.Attributes.First().Value);
+ }
- await Cleanup(client);
+ Assert.True(hasObject);
- await foreach (var _ in client.ListContainersAsync())
- {
- Assert.Fail("Containers exist");
- }
+ var @object = await client.GetObjectAsync(new PrmObjectGet(createdContainer, objectId));
+
+ var downloadedBytes = new byte[@object.Header.PayloadLength];
+ MemoryStream ms = new(downloadedBytes);
+
+ ReadOnlyMemory? chunk = null;
+ while ((chunk = await @object.ObjectReader!.ReadChunk()) != null)
+ {
+ ms.Write(chunk.Value.Span);
+ }
+
+ Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(downloadedBytes));
+
+ await Cleanup(client);
+
+ await foreach (var _ in client.ListContainersAsync())
+ {
+ Assert.Fail("Containers exist");
+ }
}
[Fact]
@@ -388,7 +388,7 @@ public class SmokeClientTests : SmokeTestsBase
ms.Write(chunk.Value.Span);
}
- for(int i = 0; i < (int)range.Offset; i++)
+ for (int i = 0; i < (int)range.Offset; i++)
Assert.Equal(downloadedBytes[i], bytes[i]);
var rangeEnd = range.Offset + range.Length;
@@ -494,15 +494,15 @@ public class SmokeClientTests : SmokeTestsBase
var objectId = await client.PutObjectAsync(param);
- var rangeParam = new PrmRangeHashGet(createdContainer, objectId, [ new FrostFsRange(100, 64)], bytes);
+ var rangeParam = new PrmRangeHashGet(createdContainer, objectId, [new FrostFsRange(100, 64)], bytes);
var hashes = await client.GetRangeHashAsync(rangeParam);
foreach (var hash in hashes)
{
- var x = hash.Slice(0, 32).ToArray();
+ var x = hash[..32].ToArray();
}
-
+
await Cleanup(client);
await foreach (var _ in client.ListContainersAsync())