span and memory

This commit is contained in:
Pavel Gross 2024-11-12 04:00:26 +03:00
parent 423b5a35b0
commit cf1fae8d2c
29 changed files with 193 additions and 165 deletions

View file

@ -175,7 +175,7 @@ public class FrostFSClient : IFrostFSClient
} }
#region ApeManagerImplementation #region ApeManagerImplementation
public Task<byte[]> AddChainAsync(PrmApeChainAdd args) public Task<ReadOnlyMemory<byte>> AddChainAsync(PrmApeChainAdd args)
{ {
if (args is null) if (args is null)
{ {

View file

@ -21,7 +21,7 @@ public interface IFrostFSClient : IDisposable
#endregion #endregion
#region ApeManager #region ApeManager
Task<byte[]> AddChainAsync(PrmApeChainAdd args); Task<ReadOnlyMemory<byte>> AddChainAsync(PrmApeChainAdd args);
Task RemoveChainAsync(PrmApeChainRemove args); Task RemoveChainAsync(PrmApeChainRemove args);

View file

@ -43,6 +43,6 @@ public static class ContainerIdMapper
throw new ArgumentNullException(nameof(message)); throw new ArgumentNullException(nameof(message));
} }
return new FrostFsContainerId(Base58.Encode(message.Value.ToByteArray())); return new FrostFsContainerId(Base58.Encode(message.Value.Span));
} }
} }

View file

@ -39,7 +39,7 @@ public static class NodeInfoMapper
state: state, state: state,
addresses: [.. nodeInfo.Addresses], addresses: [.. nodeInfo.Addresses],
attributes: nodeInfo.Attributes.ToDictionary(n => n.Key, n => n.Value), attributes: nodeInfo.Attributes.ToDictionary(n => n.Key, n => n.Value),
publicKey: nodeInfo.PublicKey.ToByteArray() publicKey: nodeInfo.PublicKey.Memory
); );
} }
} }

View file

@ -6,7 +6,7 @@ internal static class ObjectMapper
{ {
return new FrostFsObject(obj.Header.ToModel()) return new FrostFsObject(obj.Header.ToModel())
{ {
ObjectId = FrostFsObjectId.FromHash(obj.ObjectId.Value.ToByteArray()) ObjectId = FrostFsObjectId.FromHash(obj.ObjectId.Value.Span)
}; };
} }
} }

View file

@ -40,7 +40,7 @@ public static class ObjectHeaderMapper
} }
var model = new FrostFsObjectHeader( var model = new FrostFsObjectHeader(
new FrostFsContainerId(Base58.Encode(header.ContainerId.Value.ToByteArray())), new FrostFsContainerId(Base58.Encode(header.ContainerId.Value.Span)),
objTypeName, objTypeName,
header.Attributes.Select(attribute => attribute.ToModel()).ToArray(), header.Attributes.Select(attribute => attribute.ToModel()).ToArray(),
split, split,

View file

@ -28,6 +28,6 @@ public static class ObjectIdMapper
throw new ArgumentNullException(nameof(objectId)); throw new ArgumentNullException(nameof(objectId));
} }
return FrostFsObjectId.FromHash(objectId.Value.ToByteArray()); return FrostFsObjectId.FromHash(objectId.Value.Span);
} }
} }

View file

@ -44,7 +44,7 @@ public static class OwnerIdMapper
if (!Caches.Owners.TryGetValue(message, out FrostFsOwner? model)) 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); Caches.Owners.Set(message, model, _oneHourExpiration);
} }

View file

@ -45,12 +45,12 @@ public struct FrostFsChainTarget(FrostFsTargetType type, string name) : IEquatab
return $"{Name}{Type}".GetHashCode(StringComparison.InvariantCulture); 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); return left.Equals(right);
} }
public static bool operator != (FrostFsChainTarget left, FrostFsChainTarget right) public static bool operator !=(FrostFsChainTarget left, FrostFsChainTarget right)
{ {
return !(left == right); return !(left == right);
} }

View file

@ -27,7 +27,7 @@ public class FrostFsContainerId
if (containerID != null) if (containerID != null)
{ {
this.modelId = Base58.Encode(containerID.Value.ToByteArray()); this.modelId = Base58.Encode(containerID.Value.Span);
return this.modelId; return this.modelId;
} }

View file

@ -8,13 +8,8 @@ public class FrostFsObjectId(string id)
{ {
public string Value { get; } = id; public string Value { get; } = id;
public static FrostFsObjectId FromHash(byte[] hash) public static FrostFsObjectId FromHash(ReadOnlySpan<byte> hash)
{ {
if (hash is null)
{
throw new ArgumentNullException(nameof(hash));
}
if (hash.Length != Constants.Sha256HashLength) if (hash.Length != Constants.Sha256HashLength)
throw new FormatException("ObjectID must be a sha256 hash."); throw new FormatException("ObjectID must be a sha256 hash.");

View file

@ -106,7 +106,7 @@ public class ClientWrapper : ClientStatusMonitor
try try
{ {
client = new(WrapperPrm, sessionCache); client = new(WrapperPrm, sessionCache);
//TODO: set additioanl params //TODO: set additioanl params
var error = await client.Dial(ctx).ConfigureAwait(false); var error = await client.Dial(ctx).ConfigureAwait(false);
if (!string.IsNullOrEmpty(error)) if (!string.IsNullOrEmpty(error))

View file

@ -560,7 +560,7 @@ public partial class Pool : IFrostFSClient
return await client.Client!.CreateSessionAsync(args).ConfigureAwait(false); return await client.Client!.CreateSessionAsync(args).ConfigureAwait(false);
} }
public async Task<byte[]> AddChainAsync(PrmApeChainAdd args) public async Task<ReadOnlyMemory<byte>> AddChainAsync(PrmApeChainAdd args)
{ {
if (args is null) if (args is null)
{ {

View file

@ -16,7 +16,7 @@ internal sealed class ApeManagerServiceProvider : ContextAccessor
_apeManagerServiceClient = apeManagerServiceClient; _apeManagerServiceClient = apeManagerServiceClient;
} }
internal async Task<byte[]> AddChainAsync(PrmApeChainAdd args) internal async Task<ReadOnlyMemory<byte>> AddChainAsync(PrmApeChainAdd args)
{ {
var ctx = args.Context!; var ctx = args.Context!;
ctx.Key ??= ClientContext.Key?.ECDsaKey; ctx.Key ??= ClientContext.Key?.ECDsaKey;
@ -40,7 +40,7 @@ internal sealed class ApeManagerServiceProvider : ContextAccessor
Verifier.CheckResponse(response); Verifier.CheckResponse(response);
return response.Body.ChainId.ToByteArray(); return response.Body.ChainId.Memory;
} }
internal async Task RemoveChainAsync(PrmApeChainRemove args) internal async Task RemoveChainAsync(PrmApeChainRemove args)

View file

@ -68,7 +68,7 @@ internal sealed class ContainerServiceProvider(ContainerService.ContainerService
foreach (var cid in response.Body.ContainerIds) 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));
} }
} }

View file

@ -1,6 +1,4 @@
using System; using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FrostFS.Netmap; using FrostFS.Netmap;
@ -107,12 +105,16 @@ internal sealed class NetmapServiceProvider : ContextAccessor
return response.ToModel(); return response.ToModel();
} }
private static bool GetBoolValue(byte[] bytes) private static bool GetBoolValue(ReadOnlySpan<byte> 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<byte> bytes)
{ {
ulong val = 0; ulong val = 0;
for (var i = bytes.Length - 1; i >= 0; i--) 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) 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) switch (key)
{ {
case "AuditFee": settings.AuditFee = GetLongValue(valueBytes); break; case "AuditFee":
case "BasicIncomeRate": settings.BasicIncomeRate = GetLongValue(valueBytes); break; settings.AuditFee = GetLongValue(valueBytes);
case "ContainerFee": settings.ContainerFee = GetLongValue(valueBytes); break; break;
case "ContainerAliasFee": settings.ContainerAliasFee = GetLongValue(valueBytes); break; case "BasicIncomeRate":
case "EpochDuration": settings.EpochDuration = GetLongValue(valueBytes); break; settings.BasicIncomeRate = GetLongValue(valueBytes);
case "InnerRingCandidateFee": settings.InnerRingCandidateFee = GetLongValue(valueBytes); break; break;
case "MaxECDataCount": settings.MaxECDataCount = GetLongValue(valueBytes); break; case "ContainerFee":
case "MaxECParityCount": settings.MaxECParityCount = GetLongValue(valueBytes); break; settings.ContainerFee = GetLongValue(valueBytes);
case "MaxObjectSize": settings.MaxObjectSize = GetLongValue(valueBytes); break; break;
case "WithdrawFee": settings.WithdrawFee = GetLongValue(valueBytes); break; case "ContainerAliasFee":
case "HomomorphicHashingDisabled": settings.HomomorphicHashingDisabled = GetBoolValue(valueBytes); break; settings.ContainerAliasFee = GetLongValue(valueBytes);
case "MaintenanceModeAllowed": settings.MaintenanceModeAllowed = GetBoolValue(valueBytes); break; break;
default: settings.UnnamedSettings.Add(key, 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;
} }
} }
} }

View file

@ -271,7 +271,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
await foreach (var oid in objectsIds) 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); Verifier.CheckResponse(response);
return FrostFsObjectId.FromHash(grpcObject.ObjectId.Value.ToByteArray()); return FrostFsObjectId.FromHash(grpcObject.ObjectId.Value.Span);
} }
internal async Task<FrostFsObjectId> PatchObjectAsync(PrmObjectPatch args) internal async Task<FrostFsObjectId> PatchObjectAsync(PrmObjectPatch args)
@ -589,7 +589,7 @@ internal sealed class ObjectServiceProvider(ObjectService.ObjectServiceClient cl
var response = await stream.Close().ConfigureAwait(false); var response = await stream.Close().ConfigureAwait(false);
Verifier.CheckResponse(response); 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 finally
{ {

View file

@ -47,7 +47,7 @@ internal static class ObjectTools
obj.Signature = new Signature obj.Signature = new Signature
{ {
Key = ctx.GetPublicKeyCache(), Key = ctx.GetPublicKeyCache(),
Sign = ByteString.CopyFrom(ctx.Key!.SignData(obj.ObjectId.ToByteArray())), Sign = ctx.Key!.SignData(obj.ObjectId.ToByteArray()),
}; };
return obj; return obj;
@ -78,7 +78,7 @@ internal static class ObjectTools
grpcHeader.Split.ParentSignature = new Signature grpcHeader.Split.ParentSignature = new Signature
{ {
Key = ctx.GetPublicKeyCache(), Key = ctx.GetPublicKeyCache(),
Sign = ByteString.CopyFrom(ctx.Key.SignData(grpcHeader.Split.Parent.ToByteArray())), Sign = ctx.Key.SignData(grpcHeader.Split.Parent.ToByteArray()),
}; };
} }

View file

@ -20,18 +20,13 @@ public static class RequestSigner
{ {
internal const int RFC6979SignatureSize = 64; 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) if (key is null)
{ {
throw new ArgumentNullException(nameof(key)); throw new ArgumentNullException(nameof(key));
} }
if (data is null)
{
throw new ArgumentNullException(nameof(data));
}
var digest = new Sha256Digest(); var digest = new Sha256Digest();
var secp256R1 = SecNamedCurves.GetByName("secp256r1"); var secp256R1 = SecNamedCurves.GetByName("secp256r1");
var ecParameters = new ECDomainParameters(secp256R1.Curve, secp256R1.G, secp256R1.N); var ecParameters = new ECDomainParameters(secp256R1.Curve, secp256R1.G, secp256R1.N);
@ -44,16 +39,18 @@ public static class RequestSigner
signer.Init(true, privateKey); signer.Init(true, privateKey);
var rs = signer.GenerateSignature(hash); var rs = signer.GenerateSignature(hash);
var signature = new byte[RFC6979SignatureSize];
Span<byte> signature = stackalloc byte[RFC6979SignatureSize];
var rbytes = rs[0].ToByteArrayUnsigned(); var rbytes = rs[0].ToByteArrayUnsigned();
var sbytes = rs[1].ToByteArrayUnsigned(); var sbytes = rs[1].ToByteArrayUnsigned();
var index = RFC6979SignatureSize / 2 - rbytes.Length; var index = RFC6979SignatureSize / 2 - rbytes.Length;
rbytes.CopyTo(signature, index); rbytes.AsSpan().CopyTo(signature[index..]);
index = RFC6979SignatureSize - sbytes.Length; 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) internal static SignatureRFC6979 SignRFC6979(this ECDsa key, IMessage message)
@ -61,7 +58,7 @@ public static class RequestSigner
return new SignatureRFC6979 return new SignatureRFC6979
{ {
Key = ByteString.CopyFrom(key.PublicKey()), 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 return new SignatureRFC6979
{ {
Key = ByteString.CopyFrom(key.PublicKey()), 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<byte> data)
{ {
if (key is null) if (key is null)
{ {
throw new ArgumentNullException(nameof(key)); throw new ArgumentNullException(nameof(key));
} }
var hash = new byte[65]; Span<byte> dataHash = stackalloc byte[64];
hash[0] = 0x04; data.Sha512(ref dataHash);
key.SignHash(data.Sha512()).CopyTo(hash, 1); Span<byte> hash = stackalloc byte[64];
key.TrySignHash(dataHash, hash, out _);
return hash; Span<byte> result = stackalloc byte[65];
result[0] = 0x04;
hash.CopyTo(result[1..]);
return ByteString.CopyFrom(result);
} }
internal static Signature SignMessagePart(this ECDsa key, IMessage? data) internal static Signature SignMessagePart(this ECDsa key, IMessage? data)
@ -95,12 +98,11 @@ public static class RequestSigner
var sig = new Signature var sig = new Signature
{ {
Key = ByteString.CopyFrom(key.PublicKey()), Key = ByteString.CopyFrom(key.PublicKey()),
Sign = ByteString.CopyFrom(key.SignData(data2Sign)), Sign = key.SignData(data2Sign),
}; };
return sig; return sig;
} }
internal static void Sign(this IVerifiableMessage message, ECDsa key) internal static void Sign(this IVerifiableMessage message, ECDsa key)
{ {
var meta = message.GetMetaHeader(); var meta = message.GetMetaHeader();

View file

@ -33,11 +33,14 @@ public static class Verifier
return rs; 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; return false;
byte[] sig = signature.ToByteArray();
byte[] data = message.ToByteArray();
var rs = DecodeSignature(sig); var rs = DecodeSignature(sig);
var digest = new Sha256Digest(); var digest = new Sha256Digest();
var signer = new ECDsaSigner(new HMacDsaKCalculator(digest)); var signer = new ECDsaSigner(new HMacDsaKCalculator(digest));
@ -60,21 +63,22 @@ public static class Verifier
throw new ArgumentNullException(nameof(signature)); 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<byte> data, ByteString sig)
{ {
if (key is null) if (key is null)
throw new ArgumentNullException(nameof(key)); throw new ArgumentNullException(nameof(key));
if (data is null)
throw new ArgumentNullException(nameof(data));
if (sig is null) if (sig is null)
throw new ArgumentNullException(nameof(sig)); throw new ArgumentNullException(nameof(sig));
return key.VerifyHash(data.Sha512(), sig[1..]); Span<byte> hash = stackalloc byte[64];
data.Sha512(ref hash);
return key.VerifyHash(hash, sig.Span[1..]);
} }
public static bool VerifyMessagePart(this Signature sig, IMessage data) public static bool VerifyMessagePart(this Signature sig, IMessage data)
@ -85,7 +89,7 @@ public static class Verifier
using var key = sig.Key.ToByteArray().LoadPublicKey(); using var key = sig.Key.ToByteArray().LoadPublicKey();
var data2Verify = data is null ? [] : data.ToByteArray(); 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) internal static bool VerifyMatryoskaLevel(IMessage body, IMetaHeader meta, IVerificationHeader verification)

View file

@ -1,3 +1,4 @@
using System;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading; using System.Threading;
@ -46,14 +47,14 @@ public static class Extentions
} }
} }
public static byte[] Sha512(this byte[] value) public static void Sha512(this ReadOnlySpan<byte> value, ref Span<byte> hash)
{ {
bool lockTaken = false; bool lockTaken = false;
try try
{ {
_spinlockSha512.Enter(ref lockTaken); _spinlockSha512.Enter(ref lockTaken);
return _sha512.ComputeHash(value); _sha512.TryComputeHash(value, hash, out _);
} }
finally finally
{ {

View file

@ -10,6 +10,14 @@
<EnableNETAnalyzers>true</EnableNETAnalyzers> <EnableNETAnalyzers>true</EnableNETAnalyzers>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>$(DefineConstants);NETSTANDARD2_1_OR_GREATER</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>$(DefineConstants);NETSTANDARD2_1_OR_GREATER</DefineConstants>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="BouncyCastle.Cryptography" Version="2.4.0" /> <PackageReference Include="BouncyCastle.Cryptography" Version="2.4.0" />
<PackageReference Include="Google.Protobuf" Version="3.28.3" /> <PackageReference Include="Google.Protobuf" Version="3.28.3" />

View file

@ -11,9 +11,7 @@ public static class UUIDExtension
if (id == null) if (id == null)
throw new ArgumentNullException(nameof(id)); throw new ArgumentNullException(nameof(id));
var bytes = id.ToByteArray(); var orderedBytes = GetGuidBytesDirectOrder(id.Span);
var orderedBytes = GetGuidBytesDirectOrder(bytes);
return new Guid(orderedBytes); return new Guid(orderedBytes);
} }
@ -32,7 +30,7 @@ public static class UUIDExtension
return orderedBytes; return orderedBytes;
} }
private static byte[] GetGuidBytesDirectOrder(byte[] source) private static byte[] GetGuidBytesDirectOrder(ReadOnlySpan<byte> source)
{ {
if (source.Length != 16) if (source.Length != 16)
throw new ArgumentException("Wrong uuid binary format"); throw new ArgumentException("Wrong uuid binary format");

View file

@ -1,9 +1,4 @@
using System.Security.Cryptography;
using FrostFS.Object; using FrostFS.Object;
using FrostFS.SDK.Client;
using FrostFS.SDK.Client.Mappers.GRPC;
using FrostFS.SDK.Cryptography;
using FrostFS.Session; using FrostFS.Session;
using Google.Protobuf; using Google.Protobuf;

View file

@ -43,7 +43,7 @@ public class AsyncStreamReaderMock(string key, FrostFsObjectHeader objectHeader)
Signature = new Refs.Signature Signature = new Refs.Signature
{ {
Key = ByteString.CopyFrom(Key.PublicKey()), Key = ByteString.CopyFrom(Key.PublicKey()),
Sign = ByteString.CopyFrom(Key.SignData(header.ToByteArray())), Sign = Key.SignData(header.ToByteArray())
} }
} }
}, },

View file

@ -46,19 +46,19 @@ public abstract class ServiceBase(string key)
{ {
Key = ByteString.CopyFrom(Key.PublicKey()), Key = ByteString.CopyFrom(Key.PublicKey()),
Scheme = Refs.SignatureScheme.EcdsaRfc6979Sha256, Scheme = Refs.SignatureScheme.EcdsaRfc6979Sha256,
Sign = ByteString.CopyFrom(Key.SignData(response.MetaHeader.ToByteArray())) Sign = Key.SignData(response.MetaHeader.ToByteArray())
}, },
BodySignature = new Refs.Signature BodySignature = new Refs.Signature
{ {
Key = ByteString.CopyFrom(Key.PublicKey()), Key = ByteString.CopyFrom(Key.PublicKey()),
Scheme = Refs.SignatureScheme.EcdsaRfc6979Sha256, Scheme = Refs.SignatureScheme.EcdsaRfc6979Sha256,
Sign = ByteString.CopyFrom(Key.SignData(response.GetBody().ToByteArray())) Sign = Key.SignData(response.GetBody().ToByteArray())
}, },
OriginSignature = new Refs.Signature OriginSignature = new Refs.Signature
{ {
Key = ByteString.CopyFrom(Key.PublicKey()), Key = ByteString.CopyFrom(Key.PublicKey()),
Scheme = Refs.SignatureScheme.EcdsaRfc6979Sha256, Scheme = Refs.SignatureScheme.EcdsaRfc6979Sha256,
Sign = ByteString.CopyFrom(Key.SignData([])) Sign = Key.SignData([])
} }
}; };

View file

@ -5,7 +5,6 @@ using FrostFS.Object;
using FrostFS.SDK.Client; using FrostFS.SDK.Client;
using FrostFS.SDK.Client.Mappers.GRPC; using FrostFS.SDK.Client.Mappers.GRPC;
using FrostFS.SDK.Cryptography; using FrostFS.SDK.Cryptography;
using FrostFS.Session;
using Google.Protobuf; using Google.Protobuf;
@ -41,7 +40,7 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
public GetRangeHashRequest? GetRangeHashRequest { get; set; } public GetRangeHashRequest? GetRangeHashRequest { get; set; }
public Collection<ByteString> RangeHashResponses { get; } = []; public Collection<ByteString> RangeHashResponses { get; } = [];
public override Mock<ObjectService.ObjectServiceClient> GetMock() public override Mock<ObjectService.ObjectServiceClient> GetMock()
{ {
@ -94,7 +93,7 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
headResponse.Body.Header.Signature = new Refs.Signature headResponse.Body.Header.Signature = new Refs.Signature
{ {
Key = ByteString.CopyFrom(Key.PublicKey()), 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); headResponse.VerifyHeader = GetResponseVerificationHeader(headResponse);
@ -259,7 +258,7 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
response.Body.HashList.Add(hash); response.Body.HashList.Add(hash);
} }
} }
response.VerifyHeader = GetResponseVerificationHeader(response); response.VerifyHeader = GetResponseVerificationHeader(response);
return new AsyncUnaryCall<GetRangeHashResponse>( return new AsyncUnaryCall<GetRangeHashResponse>(
@ -281,7 +280,7 @@ public class ObjectMocker(string key) : ObjectServiceBase(key)
{ {
Body = new PatchResponse.Types.Body 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 MetaHeader = ResponseMetaHeader
}; };

View file

@ -10,8 +10,6 @@ using FrostFS.SDK.Cryptography;
using Google.Protobuf; using Google.Protobuf;
using static FrostFS.Object.ECInfo.Types;
namespace FrostFS.SDK.Tests; namespace FrostFS.SDK.Tests;
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "Default Value is correct for 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.ContainerId, body.Address.ContainerId);
Assert.Equal(address.ObjectId, body.Address.ObjectId); Assert.Equal(address.ObjectId, body.Address.ObjectId);
Assert.Equal(32, body.Patch.Chunk.Length); Assert.Equal(32, body.Patch.Chunk.Length);
Assert.Equal(SHA256.HashData(patch), SHA256.HashData(body.Patch.Chunk.ToArray())); Assert.Equal(SHA256.HashData(patch), SHA256.HashData(body.Patch.Chunk.ToArray()));
} }
} }

View file

@ -248,83 +248,83 @@ public class SmokeClientTests : SmokeTestsBase
[InlineData(6 * 1024 * 1024 + 100)] [InlineData(6 * 1024 * 1024 + 100)]
public async void SimpleScenarioTest(int objectSize) 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; bool callbackInvoked = false;
var ctx = new CallContext var ctx = new CallContext
{
// Timeout = TimeSpan.FromSeconds(20),
Callback = new((CallStatistics cs) =>
{ {
// Timeout = TimeSpan.FromSeconds(20), callbackInvoked = true;
Callback = new((CallStatistics cs) => Assert.True(cs.ElapsedMicroSeconds > 0);
{
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))
}) })
{ };
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; var container = await client.GetContainerAsync(new PrmContainerGet(createdContainer, ctx));
await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(createdContainer) { Filters = [filter] })) Assert.NotNull(container);
{ Assert.True(callbackInvoked);
hasObject = true;
var objHeader = await client.GetObjectHeadAsync(new PrmObjectHeadGet(createdContainer, objectId)); var bytes = GetRandomBytes(objectSize);
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);
}
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]; var filter = new FilterByAttributePair(FrostFsMatchType.Equals, "fileName", "test");
MemoryStream ms = new(downloadedBytes);
ReadOnlyMemory<byte>? chunk = null; bool hasObject = false;
while ((chunk = await @object.ObjectReader!.ReadChunk()) != null) await foreach (var objId in client.SearchObjectsAsync(new PrmObjectSearch(createdContainer) { Filters = [filter] }))
{ {
ms.Write(chunk.Value.Span); 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()) var @object = await client.GetObjectAsync(new PrmObjectGet(createdContainer, objectId));
{
Assert.Fail("Containers exist"); var downloadedBytes = new byte[@object.Header.PayloadLength];
} MemoryStream ms = new(downloadedBytes);
ReadOnlyMemory<byte>? 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] [Fact]
@ -388,7 +388,7 @@ public class SmokeClientTests : SmokeTestsBase
ms.Write(chunk.Value.Span); 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]); Assert.Equal(downloadedBytes[i], bytes[i]);
var rangeEnd = range.Offset + range.Length; var rangeEnd = range.Offset + range.Length;
@ -494,15 +494,15 @@ public class SmokeClientTests : SmokeTestsBase
var objectId = await client.PutObjectAsync(param); 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); var hashes = await client.GetRangeHashAsync(rangeParam);
foreach (var hash in hashes) foreach (var hash in hashes)
{ {
var x = hash.Slice(0, 32).ToArray(); var x = hash[..32].ToArray();
} }
await Cleanup(client); await Cleanup(client);
await foreach (var _ in client.ListContainersAsync()) await foreach (var _ in client.ListContainersAsync())