feature/netstandard2 #3
55 changed files with 2508 additions and 1818 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,6 +4,7 @@
|
||||||
*.dll
|
*.dll
|
||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
|
*.pdb
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
@ -31,3 +32,4 @@ antlr-*.jar
|
||||||
# binary
|
# binary
|
||||||
bin/
|
bin/
|
||||||
release/
|
release/
|
||||||
|
obj/
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ClientV2", "src\FrostFS.SDK.ClientV2\FrostFS.SDK.ClientV2.csproj", "{50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}"
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrostFS.SDK.ProtosV2", "src\FrostFS.SDK.ProtosV2\FrostFS.SDK.ProtosV2.csproj", "{A087047E-2505-4137-97CC-689A5AD58A0C}"
|
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrostFS.SDK.ClientV2", "src\FrostFS.SDK.ClientV2\FrostFS.SDK.ClientV2.csproj", "{F9CE6347-111A-4CE6-8BB2-545469838F47}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.Cryptography", "src\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj", "{3D804F4A-B0B2-47A5-B006-BE447BE64B50}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrostFS.SDK.Cryptography", "src\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj", "{599E2FF8-12C0-414D-B295-4C971A0A1A63}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ModelsV2", "src\FrostFS.SDK.ModelsV2\FrostFS.SDK.ModelsV2.csproj", "{14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrostFS.SDK.ModelsV2", "src\FrostFS.SDK.ModelsV2\FrostFS.SDK.ModelsV2.csproj", "{3F6E5EE6-2AAC-45BE-A5E2-B83D11F90CC3}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ProtosV2", "src\FrostFS.SDK.ProtosV2\FrostFS.SDK.ProtosV2.csproj", "{5012EF96-9C9E-4E77-BC78-B4111EE54107}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -14,25 +13,25 @@ Global
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{A087047E-2505-4137-97CC-689A5AD58A0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A087047E-2505-4137-97CC-689A5AD58A0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A087047E-2505-4137-97CC-689A5AD58A0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A087047E-2505-4137-97CC-689A5AD58A0C}.Release|Any CPU.Build.0 = Release|Any CPU
|
{50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{F9CE6347-111A-4CE6-8BB2-545469838F47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{F9CE6347-111A-4CE6-8BB2-545469838F47}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{F9CE6347-111A-4CE6-8BB2-545469838F47}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{F9CE6347-111A-4CE6-8BB2-545469838F47}.Release|Any CPU.Build.0 = Release|Any CPU
|
{3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{B04EBDF5-A446-49D6-B1D7-7D729D94E8E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{B04EBDF5-A446-49D6-B1D7-7D729D94E8E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{B04EBDF5-A446-49D6-B1D7-7D729D94E8E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B04EBDF5-A446-49D6-B1D7-7D729D94E8E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
{14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{599E2FF8-12C0-414D-B295-4C971A0A1A63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{5012EF96-9C9E-4E77-BC78-B4111EE54107}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{599E2FF8-12C0-414D-B295-4C971A0A1A63}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{5012EF96-9C9E-4E77-BC78-B4111EE54107}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{599E2FF8-12C0-414D-B295-4C971A0A1A63}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{5012EF96-9C9E-4E77-BC78-B4111EE54107}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{599E2FF8-12C0-414D-B295-4C971A0A1A63}.Release|Any CPU.Build.0 = Release|Any CPU
|
{5012EF96-9C9E-4E77-BC78-B4111EE54107}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{3F6E5EE6-2AAC-45BE-A5E2-B83D11F90CC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{B738F3E1-654D-41A3-B068-58ED122BB688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{3F6E5EE6-2AAC-45BE-A5E2-B83D11F90CC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B738F3E1-654D-41A3-B068-58ED122BB688}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{3F6E5EE6-2AAC-45BE-A5E2-B83D11F90CC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{B738F3E1-654D-41A3-B068-58ED122BB688}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{3F6E5EE6-2AAC-45BE-A5E2-B83D11F90CC3}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B738F3E1-654D-41A3-B068-58ED122BB688}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using FrostFS.Container;
|
using FrostFS.Container;
|
||||||
using FrostFS.Netmap;
|
using FrostFS.Netmap;
|
||||||
|
@ -14,15 +15,15 @@ namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
public partial class Client: IFrostFSClient
|
public partial class Client: IFrostFSClient
|
||||||
{
|
{
|
||||||
private GrpcChannel _channel;
|
private GrpcChannel? _channel;
|
||||||
private readonly ECDsa _key;
|
private readonly ECDsa _key;
|
||||||
public readonly OwnerId OwnerId;
|
public readonly OwnerId OwnerId;
|
||||||
public readonly Version Version = new (2, 13);
|
public readonly Version Version = new(2, 13);
|
||||||
|
|
||||||
private ContainerService.ContainerServiceClient _containerServiceClient;
|
private ContainerService.ContainerServiceClient? _containerServiceClient;
|
||||||
private NetmapService.NetmapServiceClient _netmapServiceClient;
|
private NetmapService.NetmapServiceClient? _netmapServiceClient;
|
||||||
private ObjectService.ObjectServiceClient _objectServiceClient;
|
private ObjectService.ObjectServiceClient? _objectServiceClient;
|
||||||
private SessionService.SessionServiceClient _sessionServiceClient;
|
private SessionService.SessionServiceClient? _sessionServiceClient;
|
||||||
|
|
||||||
public Client(string key, string host)
|
public Client(string key, string host)
|
||||||
{
|
{
|
||||||
|
@ -47,7 +48,7 @@ public partial class Client: IFrostFSClient
|
||||||
throw new ApplicationException(msg);
|
throw new ApplicationException(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitGrpcChannel(string host)
|
private void InitGrpcChannel(string host)
|
||||||
{
|
{
|
||||||
Uri uri;
|
Uri uri;
|
||||||
|
@ -89,7 +90,7 @@ public partial class Client: IFrostFSClient
|
||||||
{
|
{
|
||||||
_netmapServiceClient = new NetmapService.NetmapServiceClient(_channel);
|
_netmapServiceClient = new NetmapService.NetmapServiceClient(_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitObjectClient()
|
private void InitObjectClient()
|
||||||
{
|
{
|
||||||
_objectServiceClient = new ObjectService.ObjectServiceClient(_channel);
|
_objectServiceClient = new ObjectService.ObjectServiceClient(_channel);
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<LangVersion>12.0</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj" />
|
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
|
||||||
<ProjectReference Include="..\FrostFS.SDK.ModelsV2\FrostFS.SDK.ModelsV2.csproj" />
|
</ItemGroup>
|
||||||
<ProjectReference Include="..\FrostFS.SDK.ProtosV2\FrostFS.SDK.ProtosV2.csproj" />
|
|
||||||
</ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj" />
|
||||||
|
<ProjectReference Include="..\FrostFS.SDK.ModelsV2\FrostFS.SDK.ModelsV2.csproj" />
|
||||||
|
<ProjectReference Include="..\FrostFS.SDK.ProtosV2\FrostFS.SDK.ProtosV2.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Interfaces;
|
namespace FrostFS.SDK.ClientV2.Interfaces;
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using Google.Protobuf;
|
||||||
|
|
||||||
using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
||||||
using FrostFS.SDK.Cryptography;
|
using FrostFS.SDK.Cryptography;
|
||||||
using FrostFS.SDK.ModelsV2.Enums;
|
using FrostFS.SDK.ModelsV2.Enums;
|
||||||
using Google.Protobuf;
|
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
|
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
|
||||||
|
@ -26,7 +29,7 @@ public static class ContainerMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ModelsV2.Container(
|
return new ModelsV2.Container(
|
||||||
Enum.Parse<BasicAcl>(basicAclName),
|
(BasicAcl)Enum.Parse(typeof(BasicAcl), basicAclName),
|
||||||
container.PlacementPolicy.ToModel()
|
container.PlacementPolicy.ToModel()
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
using FrostFS.Netmap;
|
using FrostFS.Netmap;
|
||||||
using FrostFS.SDK.ModelsV2.Enums;
|
using FrostFS.SDK.ModelsV2.Enums;
|
||||||
using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo;
|
using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo;
|
||||||
|
@ -15,7 +17,7 @@ public static class NodeInfoMapper
|
||||||
}
|
}
|
||||||
return new NodeInfo
|
return new NodeInfo
|
||||||
{
|
{
|
||||||
State = Enum.Parse<NodeState>(nodeStateName),
|
State = (NodeState)Enum.Parse(typeof(NodeState), nodeStateName),
|
||||||
Version = nodeInfo.Version.ToModel()
|
Version = nodeInfo.Version.ToModel()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Linq;
|
||||||
using FrostFS.Netmap;
|
using FrostFS.Netmap;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
using FrostFS.Object;
|
using FrostFS.Object;
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
using MatchType = FrostFS.Object.MatchType;
|
using MatchType = FrostFS.Object.MatchType;
|
||||||
|
@ -26,15 +29,11 @@ public static class ObjectFilterMapper
|
||||||
{
|
{
|
||||||
public static SearchRequest.Types.Body.Types.Filter ToGrpcMessage(this ObjectFilter filter)
|
public static SearchRequest.Types.Body.Types.Filter ToGrpcMessage(this ObjectFilter filter)
|
||||||
{
|
{
|
||||||
var objMatchTypeName = Enum.GetName(typeof(MatchType), filter.MatchType);
|
var objMatchTypeName = Enum.GetName(typeof(MatchType), filter.MatchType)
|
||||||
if (objMatchTypeName is null)
|
?? throw new ArgumentException($"Unknown MatchType. Value: '{filter.MatchType}'.");
|
||||||
{
|
|
||||||
throw new ArgumentException($"Unknown MatchType. Value: '{filter.MatchType}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SearchRequest.Types.Body.Types.Filter
|
return new SearchRequest.Types.Body.Types.Filter
|
||||||
{
|
{
|
||||||
MatchType = Enum.Parse<MatchType>(objMatchTypeName),
|
MatchType = (MatchType)Enum.Parse(typeof(MatchType), objMatchTypeName),
|
||||||
Key = filter.Key,
|
Key = filter.Key,
|
||||||
Value = filter.Value
|
Value = filter.Value
|
||||||
};
|
};
|
||||||
|
@ -45,18 +44,15 @@ public static class ObjectHeaderMapper
|
||||||
{
|
{
|
||||||
public static Header ToGrpcMessage(this ObjectHeader header)
|
public static Header ToGrpcMessage(this ObjectHeader header)
|
||||||
{
|
{
|
||||||
var objTypeName = Enum.GetName(typeof(ObjectType), header.ObjectType);
|
var objTypeName = Enum.GetName(typeof(ObjectType), header.ObjectType)
|
||||||
if (objTypeName is null)
|
?? throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'.");
|
||||||
{
|
|
||||||
throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var head = new Header
|
var head = new Header
|
||||||
{
|
{
|
||||||
Attributes = { },
|
Attributes = { },
|
||||||
ContainerId = header.ContainerId.ToGrpcMessage(),
|
ContainerId = header.ContainerId.ToGrpcMessage(),
|
||||||
ObjectType = Enum.Parse<ObjectType>(objTypeName)
|
ObjectType = (ObjectType)Enum.Parse(typeof(ObjectType), objTypeName)
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var attribute in header.Attributes)
|
foreach (var attribute in header.Attributes)
|
||||||
{
|
{
|
||||||
head.Attributes.Add(attribute.ToGrpcMessage());
|
head.Attributes.Add(attribute.ToGrpcMessage());
|
||||||
|
@ -67,15 +63,11 @@ public static class ObjectHeaderMapper
|
||||||
|
|
||||||
public static ObjectHeader ToModel(this Header header)
|
public static ObjectHeader ToModel(this Header header)
|
||||||
{
|
{
|
||||||
var objTypeName = Enum.GetName(typeof(ModelsV2.Enums.ObjectType), header.ObjectType);
|
var objTypeName = Enum.GetName(typeof(ModelsV2.Enums.ObjectType), header.ObjectType)
|
||||||
if (objTypeName is null)
|
?? throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'.");
|
||||||
{
|
|
||||||
throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ObjectHeader(
|
return new ObjectHeader(
|
||||||
ContainerId.FromHash(header.ContainerId.Value.ToByteArray()),
|
ContainerId.FromHash(header.ContainerId.Value.ToByteArray()),
|
||||||
Enum.Parse<ModelsV2.Enums.ObjectType>(objTypeName),
|
(ModelsV2.Enums.ObjectType)Enum.Parse(typeof(ModelsV2.Enums.ObjectType), objTypeName),
|
||||||
header.Attributes.Select(attribute => attribute.ToModel()).ToArray()
|
header.Attributes.Select(attribute => attribute.ToModel()).ToArray()
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using FrostFS.SDK.ModelsV2.Enums;
|
using FrostFS.SDK.ModelsV2.Enums;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
|
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
@ -8,12 +9,9 @@ public static class StatusMapper
|
||||||
{
|
{
|
||||||
if (status is null) return new ModelsV2.Status(StatusCode.Success);
|
if (status is null) return new ModelsV2.Status(StatusCode.Success);
|
||||||
var codeName = Enum.GetName(typeof(StatusCode), status.Code);
|
var codeName = Enum.GetName(typeof(StatusCode), status.Code);
|
||||||
if (codeName is null)
|
|
||||||
{
|
return codeName is null
|
||||||
throw new ArgumentException($"Unknown StatusCode. Value: '{status.Code}'.");
|
? throw new ArgumentException($"Unknown StatusCode. Value: '{status.Code}'.")
|
||||||
}
|
: new ModelsV2.Status((StatusCode)Enum.Parse(typeof(StatusCode), codeName), status.Message);
|
||||||
|
|
||||||
return new ModelsV2.Status(Enum.Parse<StatusCode>(codeName), status.Message);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
271
src/FrostFS.SDK.ClientV2/Range.cs
Normal file
271
src/FrostFS.SDK.ClientV2/Range.cs
Normal file
|
@ -0,0 +1,271 @@
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace System
|
||||||
|
{
|
||||||
|
/// <summary>Represent a type can be used to index a collection either from the start or the end.</summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Index is used by the C# compiler to support the new index syntax
|
||||||
|
/// <code>
|
||||||
|
/// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ;
|
||||||
|
/// int lastElement = someArray[^1]; // lastElement = 5
|
||||||
|
/// </code>
|
||||||
|
/// </remarks>
|
||||||
|
internal readonly struct Index : IEquatable<Index>
|
||||||
|
{
|
||||||
|
private readonly int _value;
|
||||||
|
|
||||||
|
/// <summary>Construct an Index using a value and indicating if the index is from the start or from the end.</summary>
|
||||||
|
/// <param name="value">The index value. it has to be zero or positive number.</param>
|
||||||
|
/// <param name="fromEnd">Indicating if the index is from the start or from the end.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element.
|
||||||
|
/// </remarks>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Index(int value, bool fromEnd = false)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fromEnd)
|
||||||
|
_value = ~value;
|
||||||
|
else
|
||||||
|
_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following private constructors mainly created for perf reason to avoid the checks
|
||||||
|
private Index(int value)
|
||||||
|
{
|
||||||
|
_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Create an Index pointing at first element.</summary>
|
||||||
|
public static Index Start => new Index(0);
|
||||||
|
|
||||||
|
/// <summary>Create an Index pointing at beyond last element.</summary>
|
||||||
|
public static Index End => new Index(~0);
|
||||||
|
|
||||||
|
/// <summary>Create an Index from the start at the position indicated by the value.</summary>
|
||||||
|
/// <param name="value">The index value from the start.</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Index FromStart(int value)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Index(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Create an Index from the end at the position indicated by the value.</summary>
|
||||||
|
/// <param name="value">The index value from the end.</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Index FromEnd(int value)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Index(~value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Returns the index value.</summary>
|
||||||
|
public int Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_value < 0)
|
||||||
|
{
|
||||||
|
return ~_value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Indicates whether the index is from the start or the end.</summary>
|
||||||
|
public bool IsFromEnd => _value < 0;
|
||||||
|
|
||||||
|
/// <summary>Calculate the offset from the start using the giving collection length.</summary>
|
||||||
|
/// <param name="length">The length of the collection that the Index will be used with. length has to be a positive value</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// For performance reason, we don't validate the input length parameter and the returned offset value against negative values.
|
||||||
|
/// we don't validate either the returned offset is greater than the input length.
|
||||||
|
/// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and
|
||||||
|
/// then used to index a collection will get out of range exception which will be same affect as the validation.
|
||||||
|
/// </remarks>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int GetOffset(int length)
|
||||||
|
{
|
||||||
|
var offset = _value;
|
||||||
|
if (IsFromEnd)
|
||||||
|
{
|
||||||
|
// offset = length - (~value)
|
||||||
|
// offset = length + (~(~value) + 1)
|
||||||
|
// offset = length + value + 1
|
||||||
|
|
||||||
|
offset += length + 1;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Indicates whether the current Index object is equal to another object of the same type.</summary>
|
||||||
|
/// <param name="value">An object to compare with this object</param>
|
||||||
|
public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value;
|
||||||
|
|
||||||
|
/// <summary>Indicates whether the current Index object is equal to another Index object.</summary>
|
||||||
|
/// <param name="other">An object to compare with this object</param>
|
||||||
|
public bool Equals(Index other) => _value == other._value;
|
||||||
|
|
||||||
|
/// <summary>Returns the hash code for this instance.</summary>
|
||||||
|
public override int GetHashCode() => _value;
|
||||||
|
|
||||||
|
/// <summary>Converts integer number to an Index.</summary>
|
||||||
|
public static implicit operator Index(int value) => FromStart(value);
|
||||||
|
|
||||||
|
/// <summary>Converts the value of the current Index object to its equivalent string representation.</summary>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (IsFromEnd)
|
||||||
|
return "^" + ((uint)Value).ToString();
|
||||||
|
|
||||||
|
return ((uint)Value).ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Represent a range has start and end indexes.</summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Range is used by the C# compiler to support the range syntax.
|
||||||
|
/// <code>
|
||||||
|
/// int[] someArray = new int[5] { 1, 2, 3, 4, 5 };
|
||||||
|
/// int[] subArray1 = someArray[0..2]; // { 1, 2 }
|
||||||
|
/// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
|
||||||
|
/// </code>
|
||||||
|
/// </remarks>
|
||||||
|
internal readonly struct Range : IEquatable<Range>
|
||||||
|
{
|
||||||
|
/// <summary>Represent the inclusive start index of the Range.</summary>
|
||||||
|
public Index Start { get; }
|
||||||
|
|
||||||
|
/// <summary>Represent the exclusive end index of the Range.</summary>
|
||||||
|
public Index End { get; }
|
||||||
|
|
||||||
|
/// <summary>Construct a Range object using the start and end indexes.</summary>
|
||||||
|
/// <param name="start">Represent the inclusive start index of the range.</param>
|
||||||
|
/// <param name="end">Represent the exclusive end index of the range.</param>
|
||||||
|
public Range(Index start, Index end)
|
||||||
|
{
|
||||||
|
Start = start;
|
||||||
|
End = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Indicates whether the current Range object is equal to another object of the same type.</summary>
|
||||||
|
/// <param name="value">An object to compare with this object</param>
|
||||||
|
public override bool Equals(object? value) =>
|
||||||
|
value is Range r &&
|
||||||
|
r.Start.Equals(Start) &&
|
||||||
|
r.End.Equals(End);
|
||||||
|
|
||||||
|
/// <summary>Indicates whether the current Range object is equal to another Range object.</summary>
|
||||||
|
/// <param name="other">An object to compare with this object</param>
|
||||||
|
public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End);
|
||||||
|
|
||||||
|
/// <summary>Returns the hash code for this instance.</summary>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Start.GetHashCode() * 31 + End.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Converts the value of the current Range object to its equivalent string representation.</summary>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Start + ".." + End;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Create a Range object starting from start index to the end of the collection.</summary>
|
||||||
|
public static Range StartAt(Index start) => new Range(start, Index.End);
|
||||||
|
|
||||||
|
/// <summary>Create a Range object starting from first element in the collection to the end Index.</summary>
|
||||||
|
public static Range EndAt(Index end) => new Range(Index.Start, end);
|
||||||
|
|
||||||
|
/// <summary>Create a Range object starting from first element to the end.</summary>
|
||||||
|
public static Range All => new Range(Index.Start, Index.End);
|
||||||
|
|
||||||
|
/// <summary>Calculate the start offset and length of range object using a collection length.</summary>
|
||||||
|
/// <param name="length">The length of the collection that the range will be used with. length has to be a positive value.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// For performance reason, we don't validate the input length parameter against negative values.
|
||||||
|
/// It is expected Range will be used with collections which always have non negative length/count.
|
||||||
|
/// We validate the range is inside the length scope though.
|
||||||
|
/// </remarks>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public (int Offset, int Length) GetOffsetAndLength(int length)
|
||||||
|
{
|
||||||
|
int start;
|
||||||
|
var startIndex = Start;
|
||||||
|
if (startIndex.IsFromEnd)
|
||||||
|
start = length - startIndex.Value;
|
||||||
|
else
|
||||||
|
start = startIndex.Value;
|
||||||
|
|
||||||
|
int end;
|
||||||
|
var endIndex = End;
|
||||||
|
if (endIndex.IsFromEnd)
|
||||||
|
end = length - endIndex.Value;
|
||||||
|
else
|
||||||
|
end = endIndex.Value;
|
||||||
|
|
||||||
|
if ((uint)end > (uint)length || (uint)start > (uint)end)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(length));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (start, end - start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace System.Runtime.CompilerServices
|
||||||
|
{
|
||||||
|
internal static class RuntimeHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Slices the specified array using the specified range.
|
||||||
|
/// </summary>
|
||||||
|
public static T[] GetSubArray<T>(T[] array, Range range)
|
||||||
|
{
|
||||||
|
if (array == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(array));
|
||||||
|
}
|
||||||
|
|
||||||
|
(int offset, int length) = range.GetOffsetAndLength(array.Length);
|
||||||
|
|
||||||
|
if (default(T) != null || typeof(T[]) == array.GetType())
|
||||||
|
{
|
||||||
|
// We know the type of the array to be exactly T[].
|
||||||
|
|
||||||
|
if (length == 0)
|
||||||
|
{
|
||||||
|
return Array.Empty<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var dest = new T[length];
|
||||||
|
Array.Copy(array, offset, dest, 0, length);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The array is actually a U[] where U:T.
|
||||||
|
var dest = (T[])Array.CreateInstance(array.GetType().GetElementType(), length);
|
||||||
|
Array.Copy(array, offset, dest, 0, length);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,97 +1,106 @@
|
||||||
|
using System;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using FrostFS.Refs;
|
|
||||||
using FrostFS.SDK.Cryptography;
|
|
||||||
using FrostFS.Session;
|
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
|
||||||
using Org.BouncyCastle.Asn1.Sec;
|
using Org.BouncyCastle.Asn1.Sec;
|
||||||
using Org.BouncyCastle.Crypto.Digests;
|
using Org.BouncyCastle.Crypto.Digests;
|
||||||
using Org.BouncyCastle.Crypto.Parameters;
|
using Org.BouncyCastle.Crypto.Parameters;
|
||||||
using Org.BouncyCastle.Crypto.Signers;
|
using Org.BouncyCastle.Crypto.Signers;
|
||||||
using Org.BouncyCastle.Math;
|
using Org.BouncyCastle.Math;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2
|
using FrostFS.Refs;
|
||||||
|
using FrostFS.SDK.Cryptography;
|
||||||
|
using FrostFS.Session;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
public static class RequestSigner
|
||||||
{
|
{
|
||||||
public static class RequestSigner
|
public const int RFC6979SignatureSize = 64;
|
||||||
|
|
||||||
|
public static byte[] SignRFC6979(this ECDsa key, byte[] data)
|
||||||
{
|
{
|
||||||
public const int RFC6979SignatureSize = 64;
|
var digest = new Sha256Digest();
|
||||||
|
var secp256R1 = SecNamedCurves.GetByName("secp256r1");
|
||||||
|
var ecParameters = new ECDomainParameters(secp256R1.Curve, secp256R1.G, secp256R1.N);
|
||||||
|
var privateKey = new ECPrivateKeyParameters(new BigInteger(1, key.PrivateKey()), ecParameters);
|
||||||
|
var signer = new ECDsaSigner(new HMacDsaKCalculator(digest));
|
||||||
|
var hash = new byte[digest.GetDigestSize()];
|
||||||
|
|
||||||
|
digest.BlockUpdate(data, 0, data.Length);
|
||||||
|
digest.DoFinal(hash, 0);
|
||||||
|
signer.Init(true, privateKey);
|
||||||
|
|
||||||
|
var rs = signer.GenerateSignature(hash);
|
||||||
|
var signature = new byte[RFC6979SignatureSize];
|
||||||
|
var rbytes = rs[0].ToByteArrayUnsigned();
|
||||||
|
var sbytes = rs[1].ToByteArrayUnsigned();
|
||||||
|
var index = RFC6979SignatureSize / 2 - rbytes.Length;
|
||||||
|
|
||||||
|
rbytes.CopyTo(signature, index);
|
||||||
|
index = RFC6979SignatureSize - sbytes.Length;
|
||||||
|
sbytes.CopyTo(signature, index);
|
||||||
|
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
public static byte[] SignRFC6979(this ECDsa key, byte[] data)
|
public static SignatureRFC6979 SignRFC6979(this ECDsa key, IMessage message)
|
||||||
|
{
|
||||||
|
return new SignatureRFC6979
|
||||||
{
|
{
|
||||||
var digest = new Sha256Digest();
|
Key = ByteString.CopyFrom(key.PublicKey()),
|
||||||
var secp256R1 = SecNamedCurves.GetByName("secp256r1");
|
Sign = ByteString.CopyFrom(key.SignRFC6979(message.ToByteArray())),
|
||||||
var ecParameters = new ECDomainParameters(secp256R1.Curve, secp256R1.G, secp256R1.N);
|
};
|
||||||
var privateKey = new ECPrivateKeyParameters(new BigInteger(1, key.PrivateKey()), ecParameters);
|
}
|
||||||
var signer = new ECDsaSigner(new HMacDsaKCalculator(digest));
|
|
||||||
var hash = new byte[digest.GetDigestSize()];
|
public static SignatureRFC6979 SignRFC6979(this ECDsa key, ByteString data)
|
||||||
digest.BlockUpdate(data, 0, data.Length);
|
{
|
||||||
digest.DoFinal(hash, 0);
|
return new SignatureRFC6979
|
||||||
signer.Init(true, privateKey);
|
{
|
||||||
var rs = signer.GenerateSignature(hash);
|
Key = ByteString.CopyFrom(key.PublicKey()),
|
||||||
var signature = new byte[RFC6979SignatureSize];
|
Sign = ByteString.CopyFrom(key.SignRFC6979(data.ToByteArray())),
|
||||||
var rbytes = rs[0].ToByteArrayUnsigned();
|
};
|
||||||
var sbytes = rs[1].ToByteArrayUnsigned();
|
}
|
||||||
var index = RFC6979SignatureSize / 2 - rbytes.Length;
|
|
||||||
rbytes.CopyTo(signature, index);
|
|
||||||
index = RFC6979SignatureSize - sbytes.Length;
|
|
||||||
sbytes.CopyTo(signature, index);
|
|
||||||
return signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SignatureRFC6979 SignRFC6979(this ECDsa key, IMessage message)
|
public static byte[] SignData(this ECDsa key, byte[] data)
|
||||||
{
|
{
|
||||||
return new SignatureRFC6979
|
var hash = new byte[65];
|
||||||
{
|
hash[0] = 0x04;
|
||||||
Key = ByteString.CopyFrom(key.PublicKey()),
|
key
|
||||||
Sign = ByteString.CopyFrom(key.SignRFC6979(message.ToByteArray())),
|
.SignHash(SHA512.Create().ComputeHash(data))
|
||||||
};
|
.CopyTo(hash, 1);
|
||||||
}
|
return hash;
|
||||||
|
}
|
||||||
public static SignatureRFC6979 SignRFC6979(this ECDsa key, ByteString data)
|
|
||||||
{
|
|
||||||
return new SignatureRFC6979
|
|
||||||
{
|
|
||||||
Key = ByteString.CopyFrom(key.PublicKey()),
|
|
||||||
Sign = ByteString.CopyFrom(key.SignRFC6979(data.ToByteArray())),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] SignData(this ECDsa key, byte[] data)
|
public static Signature SignMessagePart(this ECDsa key, IMessage? data)
|
||||||
|
{
|
||||||
|
var data2Sign = data is null ? Array.Empty<byte>() : data.ToByteArray();
|
||||||
|
var sig = new Signature
|
||||||
{
|
{
|
||||||
var hash = new byte[65];
|
Key = ByteString.CopyFrom(key.PublicKey()),
|
||||||
hash[0] = 0x04;
|
Sign = ByteString.CopyFrom(key.SignData(data2Sign)),
|
||||||
key
|
};
|
||||||
.SignHash(SHA512.Create().ComputeHash(data))
|
return sig;
|
||||||
.CopyTo(hash, 1);
|
}
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Signature SignMessagePart(this ECDsa key, IMessage? data)
|
public static void Sign(this IVerificableMessage message, ECDsa key)
|
||||||
|
{
|
||||||
|
var meta = message.GetMetaHeader();
|
||||||
|
IVerificationHeader verify = message switch
|
||||||
{
|
{
|
||||||
var data2Sign = data is null ? Array.Empty<byte>() : data.ToByteArray();
|
IRequest => new RequestVerificationHeader(),
|
||||||
var sig = new Signature
|
IResponse => new ResponseVerificationHeader(),
|
||||||
{
|
_ => throw new InvalidOperationException("Unsopported message type")
|
||||||
Key = ByteString.CopyFrom(key.PublicKey()),
|
};
|
||||||
Sign = ByteString.CopyFrom(key.SignData(data2Sign)),
|
|
||||||
};
|
var verifyOrigin = message.GetVerificationHeader();
|
||||||
return sig;
|
if (verifyOrigin is null)
|
||||||
}
|
verify.BodySignature = key.SignMessagePart(message.GetBody());
|
||||||
|
|
||||||
public static void Sign(this IVerificableMessage message, ECDsa key)
|
verify.MetaSignature = key.SignMessagePart(meta);
|
||||||
{
|
verify.OriginSignature = key.SignMessagePart(verifyOrigin);
|
||||||
var meta = message.GetMetaHeader();
|
verify.SetOrigin(verifyOrigin);
|
||||||
IVerificationHeader verify = message switch
|
message.SetVerificationHeader(verify);
|
||||||
{
|
|
||||||
IRequest => new RequestVerificationHeader(),
|
|
||||||
IResponse => new ResponseVerificationHeader(),
|
|
||||||
_ => throw new InvalidOperationException("Unsopported message type")
|
|
||||||
};
|
|
||||||
var verifyOrigin = message.GetVerificationHeader();
|
|
||||||
if (verifyOrigin is null)
|
|
||||||
verify.BodySignature = key.SignMessagePart(message.GetBody());
|
|
||||||
verify.MetaSignature = key.SignMessagePart(meta);
|
|
||||||
verify.OriginSignature = key.SignMessagePart(verifyOrigin);
|
|
||||||
verify.SetOrigin(verifyOrigin);
|
|
||||||
message.SetVerificationHeader(verify);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using FrostFS.Container;
|
using FrostFS.Container;
|
||||||
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
using FrostFS.Netmap;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using FrostFS.Netmap;
|
||||||
using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap;
|
||||||
|
|
||||||
using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo;
|
using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
@ -10,11 +13,13 @@ public partial class Client
|
||||||
{
|
{
|
||||||
var request = new LocalNodeInfoRequest
|
var request = new LocalNodeInfoRequest
|
||||||
{
|
{
|
||||||
Body = new LocalNodeInfoRequest.Types.Body { },
|
Body = new LocalNodeInfoRequest.Types.Body { }
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader();
|
request.AddMetaHeader();
|
||||||
request.Sign(_key);
|
request.Sign(_key);
|
||||||
var response = await _netmapServiceClient.LocalNodeInfoAsync(request);
|
var response = await _netmapServiceClient.LocalNodeInfoAsync(request);
|
||||||
|
|
||||||
return response.Body.ToModel();
|
return response.Body.ToModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,10 +27,12 @@ public partial class Client
|
||||||
{
|
{
|
||||||
var request = new NetworkInfoRequest
|
var request = new NetworkInfoRequest
|
||||||
{
|
{
|
||||||
Body = new NetworkInfoRequest.Types.Body { },
|
Body = new NetworkInfoRequest.Types.Body { }
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader();
|
request.AddMetaHeader();
|
||||||
request.Sign(_key);
|
request.Sign(_key);
|
||||||
|
|
||||||
return await _netmapServiceClient.NetworkInfoAsync(request);
|
return await _netmapServiceClient.NetworkInfoAsync(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Google.Protobuf;
|
||||||
|
|
||||||
using FrostFS.Object;
|
using FrostFS.Object;
|
||||||
using FrostFS.Refs;
|
using FrostFS.Refs;
|
||||||
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
using FrostFS.SDK.Cryptography;
|
using FrostFS.SDK.Cryptography;
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
using FrostFS.Session;
|
using FrostFS.Session;
|
||||||
using Google.Protobuf;
|
|
||||||
using Grpc.Core;
|
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
@ -15,19 +20,21 @@ public partial class Client
|
||||||
{
|
{
|
||||||
var request = new HeadRequest
|
var request = new HeadRequest
|
||||||
{
|
{
|
||||||
Body = new HeadRequest.Types.Body
|
Body = new HeadRequest.Types.Body
|
||||||
{
|
{
|
||||||
Address = new Address
|
Address = new Address
|
||||||
{
|
{
|
||||||
ContainerId = cid.ToGrpcMessage(),
|
ContainerId = cid.ToGrpcMessage(),
|
||||||
ObjectId = oid.ToGrpcMessage()
|
ObjectId = oid.ToGrpcMessage()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader();
|
request.AddMetaHeader();
|
||||||
request.Sign(_key);
|
request.Sign(_key);
|
||||||
var response = await _objectServiceClient.HeadAsync(request);
|
var response = await _objectServiceClient.HeadAsync(request);
|
||||||
Verifier.CheckResponse(response);
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
return response.Body.Header.Header.ToModel();
|
return response.Body.Header.Header.ToModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,9 +50,10 @@ public partial class Client
|
||||||
{
|
{
|
||||||
ContainerId = cid.ToGrpcMessage(),
|
ContainerId = cid.ToGrpcMessage(),
|
||||||
ObjectId = oid.ToGrpcMessage()
|
ObjectId = oid.ToGrpcMessage()
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader();
|
request.AddMetaHeader();
|
||||||
request.AddObjectSessionToken(
|
request.AddObjectSessionToken(
|
||||||
sessionToken,
|
sessionToken,
|
||||||
|
@ -54,43 +62,13 @@ public partial class Client
|
||||||
ObjectSessionContext.Types.Verb.Get,
|
ObjectSessionContext.Types.Verb.Get,
|
||||||
_key
|
_key
|
||||||
);
|
);
|
||||||
|
|
||||||
request.Sign(_key);
|
request.Sign(_key);
|
||||||
|
|
||||||
var obj = await GetObject(request);
|
var obj = await GetObject(request);
|
||||||
|
|
||||||
return obj.ToModel();
|
return obj.ToModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Object.Object> GetObject(GetRequest request)
|
|
||||||
{
|
|
||||||
using var stream = GetObjectInit(request);
|
|
||||||
var obj = await stream.ReadHeader();
|
|
||||||
var payload = new byte[obj.Header.PayloadLength];
|
|
||||||
var offset = 0;
|
|
||||||
var chunk = await stream.ReadChunk();
|
|
||||||
while (chunk is not null)
|
|
||||||
{
|
|
||||||
chunk.CopyTo(payload, offset);
|
|
||||||
offset += chunk.Length;
|
|
||||||
chunk = await stream.ReadChunk();
|
|
||||||
}
|
|
||||||
|
|
||||||
obj.Payload = ByteString.CopyFrom(payload);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObjectReader GetObjectInit(GetRequest initRequest)
|
|
||||||
{
|
|
||||||
if (initRequest is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(initRequest));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ObjectReader
|
|
||||||
{
|
|
||||||
Call = _objectServiceClient.Get(initRequest)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ObjectId> PutObjectAsync(ObjectHeader header, Stream payload)
|
public async Task<ObjectId> PutObjectAsync(ObjectHeader header, Stream payload)
|
||||||
{
|
{
|
||||||
return await PutObject(header, payload);
|
return await PutObject(header, payload);
|
||||||
|
@ -100,74 +78,12 @@ public partial class Client
|
||||||
{
|
{
|
||||||
return await PutObject(header, new MemoryStream(payload));
|
return await PutObject(header, new MemoryStream(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<ObjectId> PutObject(ObjectHeader header, Stream payload)
|
|
||||||
{
|
|
||||||
var sessionToken = await CreateSessionAsync(uint.MaxValue);
|
|
||||||
var hdr = header.ToGrpcMessage();
|
|
||||||
hdr.OwnerId = OwnerId.ToGrpcMessage();
|
|
||||||
hdr.Version = Version.ToGrpcMessage();
|
|
||||||
var oid = new ObjectID
|
|
||||||
{
|
|
||||||
Value = hdr.Sha256()
|
|
||||||
};
|
|
||||||
var request = new PutRequest
|
|
||||||
{
|
|
||||||
Body = new PutRequest.Types.Body
|
|
||||||
{
|
|
||||||
Init = new PutRequest.Types.Body.Types.Init
|
|
||||||
{
|
|
||||||
Header = hdr
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
request.AddMetaHeader();
|
|
||||||
request.AddObjectSessionToken(
|
|
||||||
sessionToken,
|
|
||||||
hdr.ContainerId,
|
|
||||||
oid,
|
|
||||||
ObjectSessionContext.Types.Verb.Put,
|
|
||||||
_key
|
|
||||||
);
|
|
||||||
request.Sign(_key);
|
|
||||||
|
|
||||||
using var stream = await PutObjectInit(request);
|
|
||||||
var buffer = new byte[Constants.ObjectChunkSize];
|
|
||||||
var bufferLength = await payload.ReadAsync(buffer.AsMemory(0, Constants.ObjectChunkSize));
|
|
||||||
while (bufferLength > 0)
|
|
||||||
{
|
|
||||||
request.Body = new PutRequest.Types.Body
|
|
||||||
{
|
|
||||||
Chunk = ByteString.CopyFrom(buffer[..bufferLength]),
|
|
||||||
};
|
|
||||||
request.VerifyHeader = null;
|
|
||||||
request.Sign(_key);
|
|
||||||
await stream.Write(request);
|
|
||||||
bufferLength = await payload.ReadAsync(buffer.AsMemory(0, Constants.ObjectChunkSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = await stream.Close();
|
|
||||||
Verifier.CheckResponse(response);
|
|
||||||
return ObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<ObjectStreamer> PutObjectInit(PutRequest initRequest)
|
|
||||||
{
|
|
||||||
if (initRequest is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(initRequest));
|
|
||||||
}
|
|
||||||
|
|
||||||
var call = _objectServiceClient.Put();
|
|
||||||
await call.RequestStream.WriteAsync(initRequest);
|
|
||||||
return new ObjectStreamer { Call = call };
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteObjectAsync(ContainerId cid, ObjectId oid)
|
public async Task DeleteObjectAsync(ContainerId cid, ObjectId oid)
|
||||||
{
|
{
|
||||||
var request = new DeleteRequest
|
var request = new DeleteRequest
|
||||||
{
|
{
|
||||||
Body = new DeleteRequest.Types.Body
|
Body = new DeleteRequest.Types.Body
|
||||||
{
|
{
|
||||||
Address = new Address
|
Address = new Address
|
||||||
{
|
{
|
||||||
|
@ -176,6 +92,7 @@ public partial class Client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader();
|
request.AddMetaHeader();
|
||||||
request.Sign(_key);
|
request.Sign(_key);
|
||||||
var response = await _objectServiceClient.DeleteAsync(request);
|
var response = await _objectServiceClient.DeleteAsync(request);
|
||||||
|
@ -193,24 +110,125 @@ public partial class Client
|
||||||
Version = 1
|
Version = 1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var filter in filters)
|
foreach (var filter in filters)
|
||||||
{
|
{
|
||||||
request.Body.Filters.Add(filter.ToGrpcMessage());
|
request.Body.Filters.Add(filter.ToGrpcMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
|
||||||
request.AddMetaHeader();
|
request.AddMetaHeader();
|
||||||
request.Sign(_key);
|
request.Sign(_key);
|
||||||
var objectsIds = SearchObjects(request);
|
var objectsIds = SearchObjects(request);
|
||||||
|
|
||||||
await foreach (var oid in objectsIds)
|
await foreach (var oid in objectsIds)
|
||||||
{
|
{
|
||||||
yield return ObjectId.FromHash(oid.Value.ToByteArray());
|
yield return ObjectId.FromHash(oid.Value.ToByteArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<Object.Object> GetObject(GetRequest request)
|
||||||
|
{
|
||||||
|
using var stream = GetObjectInit(request);
|
||||||
|
var obj = await stream.ReadHeader();
|
||||||
|
var payload = new byte[obj.Header.PayloadLength];
|
||||||
|
var offset = 0;
|
||||||
|
var chunk = await stream.ReadChunk();
|
||||||
|
|
||||||
|
while (chunk is not null)
|
||||||
|
{
|
||||||
|
chunk.CopyTo(payload, offset);
|
||||||
|
offset += chunk.Length;
|
||||||
|
chunk = await stream.ReadChunk();
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.Payload = ByteString.CopyFrom(payload);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObjectReader GetObjectInit(GetRequest initRequest)
|
||||||
|
{
|
||||||
|
if (initRequest is null)
|
||||||
|
throw new ArgumentNullException(nameof(initRequest));
|
||||||
|
|
||||||
|
return new ObjectReader
|
||||||
|
{
|
||||||
|
Call = _objectServiceClient.Get(initRequest)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ObjectId> PutObject(ObjectHeader header, Stream payload)
|
||||||
|
{
|
||||||
|
var sessionToken = await CreateSessionAsync(uint.MaxValue);
|
||||||
|
var hdr = header.ToGrpcMessage();
|
||||||
|
hdr.OwnerId = OwnerId.ToGrpcMessage();
|
||||||
|
hdr.Version = Version.ToGrpcMessage();
|
||||||
|
|
||||||
|
var oid = new ObjectID
|
||||||
|
{
|
||||||
|
Value = hdr.Sha256()
|
||||||
|
};
|
||||||
|
|
||||||
|
var request = new PutRequest
|
||||||
|
{
|
||||||
|
Body = new PutRequest.Types.Body
|
||||||
|
{
|
||||||
|
Init = new PutRequest.Types.Body.Types.Init
|
||||||
|
{
|
||||||
|
Header = hdr
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddMetaHeader();
|
||||||
|
request.AddObjectSessionToken(
|
||||||
|
sessionToken,
|
||||||
|
hdr.ContainerId,
|
||||||
|
oid,
|
||||||
|
ObjectSessionContext.Types.Verb.Put,
|
||||||
|
_key
|
||||||
|
);
|
||||||
|
|
||||||
|
request.Sign(_key);
|
||||||
|
|
||||||
|
using var stream = await PutObjectInit(request);
|
||||||
|
var buffer = new byte[Constants.ObjectChunkSize];
|
||||||
|
var bufferLength = await payload.ReadAsync(buffer, 0, Constants.ObjectChunkSize);
|
||||||
|
|
||||||
|
while (bufferLength > 0)
|
||||||
|
{
|
||||||
|
request.Body = new PutRequest.Types.Body
|
||||||
|
{
|
||||||
|
Chunk = ByteString.CopyFrom(buffer[..bufferLength]),
|
||||||
|
};
|
||||||
|
request.VerifyHeader = null;
|
||||||
|
request.Sign(_key);
|
||||||
|
await stream.Write(request);
|
||||||
|
bufferLength = await payload.ReadAsync(buffer, 0, Constants.ObjectChunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = await stream.Close();
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
|
return ObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ObjectStreamer> PutObjectInit(PutRequest initRequest)
|
||||||
|
{
|
||||||
|
if (initRequest is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(initRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
var call = _objectServiceClient.Put();
|
||||||
|
await call.RequestStream.WriteAsync(initRequest);
|
||||||
|
|
||||||
|
return new ObjectStreamer(call);
|
||||||
|
}
|
||||||
|
|
||||||
private async IAsyncEnumerable<ObjectID> SearchObjects(SearchRequest request)
|
private async IAsyncEnumerable<ObjectID> SearchObjects(SearchRequest request)
|
||||||
{
|
{
|
||||||
using var stream = SearchObjectsInit(request);
|
using var stream = GetSearchReader(request);
|
||||||
var ids = await stream.Read();
|
var ids = await stream.Read();
|
||||||
while (ids is not null)
|
while (ids is not null)
|
||||||
{
|
{
|
||||||
|
@ -218,110 +236,18 @@ public partial class Client
|
||||||
{
|
{
|
||||||
yield return oid;
|
yield return oid;
|
||||||
}
|
}
|
||||||
|
|
||||||
ids = await stream.Read();
|
ids = await stream.Read();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchReader SearchObjectsInit(SearchRequest initRequest)
|
private SearchReader GetSearchReader(SearchRequest initRequest)
|
||||||
{
|
{
|
||||||
if (initRequest is null)
|
if (initRequest is null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(initRequest));
|
throw new ArgumentNullException(nameof(initRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SearchReader
|
return new SearchReader(_objectServiceClient.Search(initRequest));
|
||||||
{
|
|
||||||
Call = _objectServiceClient.Search(initRequest)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ObjectReader : IDisposable
|
|
||||||
{
|
|
||||||
public AsyncServerStreamingCall<GetResponse> Call { get; init; }
|
|
||||||
|
|
||||||
public async Task<Object.Object> ReadHeader()
|
|
||||||
{
|
|
||||||
if (!await Call.ResponseStream.MoveNext())
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("unexpect end of stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = Call.ResponseStream.Current;
|
|
||||||
Verifier.CheckResponse(response);
|
|
||||||
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Init)
|
|
||||||
throw new InvalidOperationException("unexpect message type");
|
|
||||||
return new Object.Object
|
|
||||||
{
|
|
||||||
ObjectId = response.Body.Init.ObjectId,
|
|
||||||
Header = response.Body.Init.Header,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<byte[]?> ReadChunk()
|
|
||||||
{
|
|
||||||
if (!await Call.ResponseStream.MoveNext())
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = Call.ResponseStream.Current;
|
|
||||||
Verifier.CheckResponse(response);
|
|
||||||
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk)
|
|
||||||
throw new InvalidOperationException("unexpect message type");
|
|
||||||
return response.Body.Chunk.ToByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Call.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class ObjectStreamer : IDisposable
|
|
||||||
{
|
|
||||||
public AsyncClientStreamingCall<PutRequest, PutResponse> Call { get; init; }
|
|
||||||
|
|
||||||
public async Task Write(PutRequest request)
|
|
||||||
{
|
|
||||||
if (request is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
await Call.RequestStream.WriteAsync(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<PutResponse> Close()
|
|
||||||
{
|
|
||||||
await Call.RequestStream.CompleteAsync();
|
|
||||||
return await Call.ResponseAsync;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Call.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class SearchReader : IDisposable
|
|
||||||
{
|
|
||||||
public AsyncServerStreamingCall<SearchResponse> Call { get; init; }
|
|
||||||
|
|
||||||
public async Task<List<ObjectID>?> Read()
|
|
||||||
{
|
|
||||||
if (!await Call.ResponseStream.MoveNext())
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = Call.ResponseStream.Current;
|
|
||||||
Verifier.CheckResponse(response);
|
|
||||||
return response.Body?.IdList.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Call.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
50
src/FrostFS.SDK.ClientV2/Services/ObjectReader.cs
Normal file
50
src/FrostFS.SDK.ClientV2/Services/ObjectReader.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Grpc.Core;
|
||||||
|
|
||||||
|
using FrostFS.Object;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
internal class ObjectReader : IDisposable
|
||||||
|
{
|
||||||
|
public AsyncServerStreamingCall<GetResponse> Call { get; set; }
|
||||||
|
|
||||||
|
public async Task<Object.Object> ReadHeader()
|
||||||
|
{
|
||||||
|
if (!await Call.ResponseStream.MoveNext())
|
||||||
|
throw new InvalidOperationException("unexpect end of stream");
|
||||||
|
|
||||||
|
var response = Call.ResponseStream.Current;
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
|
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Init)
|
||||||
|
throw new InvalidOperationException("unexpect message type");
|
||||||
|
|
||||||
|
return new Object.Object
|
||||||
|
{
|
||||||
|
ObjectId = response.Body.Init.ObjectId,
|
||||||
|
Header = response.Body.Init.Header,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<byte[]?> ReadChunk()
|
||||||
|
{
|
||||||
|
if (!await Call.ResponseStream.MoveNext())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var response = Call.ResponseStream.Current;
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
|
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk)
|
||||||
|
throw new InvalidOperationException("unexpect message type");
|
||||||
|
|
||||||
|
return response.Body.Chunk.ToByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Call.Dispose();
|
||||||
|
}
|
||||||
|
}
|
35
src/FrostFS.SDK.ClientV2/Services/ObjectStreamer.cs
Normal file
35
src/FrostFS.SDK.ClientV2/Services/ObjectStreamer.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Grpc.Core;
|
||||||
|
|
||||||
|
using FrostFS.Object;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
internal class ObjectStreamer(AsyncClientStreamingCall<PutRequest, PutResponse> call) : IDisposable
|
||||||
|
{
|
||||||
|
public AsyncClientStreamingCall<PutRequest, PutResponse> Call { get; private set; } = call;
|
||||||
|
|
||||||
|
public async Task Write(PutRequest request)
|
||||||
|
{
|
||||||
|
if (request is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
await Call.RequestStream.WriteAsync(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PutResponse> Close()
|
||||||
|
{
|
||||||
|
await Call.RequestStream.CompleteAsync();
|
||||||
|
|
||||||
|
return await Call.ResponseAsync;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Call.Dispose();
|
||||||
|
}
|
||||||
|
}
|
34
src/FrostFS.SDK.ClientV2/Services/SearchReader.cs
Normal file
34
src/FrostFS.SDK.ClientV2/Services/SearchReader.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Grpc.Core;
|
||||||
|
|
||||||
|
using FrostFS.Object;
|
||||||
|
using FrostFS.Refs;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
internal class SearchReader(AsyncServerStreamingCall<SearchResponse> call) : IDisposable
|
||||||
|
{
|
||||||
|
public AsyncServerStreamingCall<SearchResponse> Call { get; private set; } = call;
|
||||||
|
|
||||||
|
public async Task<List<ObjectID>?> Read()
|
||||||
|
{
|
||||||
|
if (!await Call.ResponseStream.MoveNext())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = Call.ResponseStream.Current;
|
||||||
|
Verifier.CheckResponse(response);
|
||||||
|
|
||||||
|
return response.Body?.IdList.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Call.Dispose();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
using FrostFS.Session;
|
using FrostFS.Session;
|
||||||
|
|
||||||
|
@ -15,14 +17,17 @@ public partial class Client
|
||||||
Expiration = expiration,
|
Expiration = expiration,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader();
|
request.AddMetaHeader();
|
||||||
request.Sign(_key);
|
request.Sign(_key);
|
||||||
|
|
||||||
return await CreateSession(request);
|
return await CreateSession(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<SessionToken> CreateSession(CreateRequest request)
|
private async Task<SessionToken> CreateSession(CreateRequest request)
|
||||||
{
|
{
|
||||||
var resp = await _sessionServiceClient.CreateAsync(request);
|
var resp = await _sessionServiceClient.CreateAsync(request);
|
||||||
|
|
||||||
return new SessionToken
|
return new SessionToken
|
||||||
{
|
{
|
||||||
Body = new SessionToken.Types.Body
|
Body = new SessionToken.Types.Body
|
||||||
|
|
|
@ -1,89 +1,106 @@
|
||||||
|
using System;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using FrostFS.Refs;
|
|
||||||
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
|
||||||
using FrostFS.SDK.Cryptography;
|
|
||||||
using FrostFS.Session;
|
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
|
||||||
using Org.BouncyCastle.Asn1.Sec;
|
using Org.BouncyCastle.Asn1.Sec;
|
||||||
using Org.BouncyCastle.Crypto.Digests;
|
using Org.BouncyCastle.Crypto.Digests;
|
||||||
using Org.BouncyCastle.Crypto.Parameters;
|
using Org.BouncyCastle.Crypto.Parameters;
|
||||||
using Org.BouncyCastle.Crypto.Signers;
|
using Org.BouncyCastle.Crypto.Signers;
|
||||||
using Org.BouncyCastle.Math;
|
using Org.BouncyCastle.Math;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2
|
using FrostFS.Refs;
|
||||||
|
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
|
using FrostFS.SDK.Cryptography;
|
||||||
|
using FrostFS.Session;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
|
public static class Verifier
|
||||||
{
|
{
|
||||||
public static class Verifier
|
public const int RFC6979SignatureSize = 64;
|
||||||
|
|
||||||
|
private static BigInteger[] DecodeSignature(byte[] sig)
|
||||||
{
|
{
|
||||||
public const int RFC6979SignatureSize = 64;
|
if (sig.Length != RFC6979SignatureSize)
|
||||||
|
throw new FormatException($"Wrong signature size, expect={RFC6979SignatureSize}, actual={sig.Length}");
|
||||||
|
|
||||||
private static BigInteger[] DecodeSignature(byte[] sig)
|
var rs = new BigInteger[2];
|
||||||
{
|
rs[0] = new BigInteger(1, sig[..32]);
|
||||||
if (sig.Length != RFC6979SignatureSize)
|
rs[1] = new BigInteger(1, sig[32..]);
|
||||||
throw new FormatException($"Wrong signature size, expect={RFC6979SignatureSize}, actual={sig.Length}");
|
|
||||||
var rs = new BigInteger[2];
|
|
||||||
rs[0] = new BigInteger(1, sig[..32]);
|
|
||||||
rs[1] = new BigInteger(1, sig[32..]);
|
|
||||||
return rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool VerifyRFC6979(this byte[] publicKey, byte[] data, byte[] sig)
|
return rs;
|
||||||
{
|
}
|
||||||
if (publicKey is null || data is null || sig is null) return false;
|
|
||||||
var rs = DecodeSignature(sig);
|
|
||||||
var digest = new Sha256Digest();
|
|
||||||
var signer = new ECDsaSigner(new HMacDsaKCalculator(digest));
|
|
||||||
var secp256R1 = SecNamedCurves.GetByName("secp256r1");
|
|
||||||
var ecParameters = new ECDomainParameters(secp256R1.Curve, secp256R1.G, secp256R1.N);
|
|
||||||
var bcPublicKey = new ECPublicKeyParameters(secp256R1.Curve.DecodePoint(publicKey), ecParameters);
|
|
||||||
var hash = new byte[digest.GetDigestSize()];
|
|
||||||
digest.BlockUpdate(data, 0, data.Length);
|
|
||||||
digest.DoFinal(hash, 0);
|
|
||||||
signer.Init(false, bcPublicKey);
|
|
||||||
return signer.VerifySignature(hash, rs[0], rs[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool VerifyRFC6979(this SignatureRFC6979 signature, IMessage message)
|
public static bool VerifyRFC6979(this byte[] publicKey, byte[] data, byte[] sig)
|
||||||
{
|
{
|
||||||
return signature.Key.ToByteArray().VerifyRFC6979(message.ToByteArray(), signature.Sign.ToByteArray());
|
if (publicKey is null || data is null || sig is null)
|
||||||
}
|
return false;
|
||||||
|
|
||||||
public static bool VerifyData(this ECDsa key, byte[] data, byte[] sig)
|
var rs = DecodeSignature(sig);
|
||||||
{
|
var digest = new Sha256Digest();
|
||||||
return key.VerifyHash(SHA512.Create().ComputeHash(data), sig[1..]);
|
var signer = new ECDsaSigner(new HMacDsaKCalculator(digest));
|
||||||
}
|
var secp256R1 = SecNamedCurves.GetByName("secp256r1");
|
||||||
|
var ecParameters = new ECDomainParameters(secp256R1.Curve, secp256R1.G, secp256R1.N);
|
||||||
|
var bcPublicKey = new ECPublicKeyParameters(secp256R1.Curve.DecodePoint(publicKey), ecParameters);
|
||||||
|
var hash = new byte[digest.GetDigestSize()];
|
||||||
|
|
||||||
|
digest.BlockUpdate(data, 0, data.Length);
|
||||||
|
digest.DoFinal(hash, 0);
|
||||||
|
signer.Init(false, bcPublicKey);
|
||||||
|
|
||||||
public static bool VerifyMessagePart(this Signature sig, IMessage data)
|
return signer.VerifySignature(hash, rs[0], rs[1]);
|
||||||
{
|
}
|
||||||
if (sig is null || sig.Key is null || sig.Sign is null) return false;
|
|
||||||
using var key = sig.Key.ToByteArray().LoadPublicKey();
|
|
||||||
var data2Verify = data is null ? Array.Empty<byte>() : data.ToByteArray();
|
|
||||||
return key.VerifyData(data2Verify, sig.Sign.ToByteArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool VerifyMatryoskaLevel(IMessage body, IMetaHeader meta, IVerificationHeader verification)
|
public static bool VerifyRFC6979(this SignatureRFC6979 signature, IMessage message)
|
||||||
{
|
{
|
||||||
if (!verification.MetaSignature.VerifyMessagePart(meta)) return false;
|
return signature.Key.ToByteArray().VerifyRFC6979(message.ToByteArray(), signature.Sign.ToByteArray());
|
||||||
var origin = verification.GetOrigin();
|
}
|
||||||
if (!verification.OriginSignature.VerifyMessagePart(origin)) return false;
|
|
||||||
if (origin is null)
|
|
||||||
return verification.BodySignature.VerifyMessagePart(body);
|
|
||||||
return verification.BodySignature is null && VerifyMatryoskaLevel(body, meta.GetOrigin(), origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Verify(this IVerificableMessage message)
|
public static bool VerifyData(this ECDsa key, byte[] data, byte[] sig)
|
||||||
{
|
{
|
||||||
return VerifyMatryoskaLevel(message.GetBody(), message.GetMetaHeader(), message.GetVerificationHeader());
|
return key.VerifyHash(SHA512.Create().ComputeHash(data), sig[1..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CheckResponse(IResponse resp)
|
public static bool VerifyMessagePart(this Signature sig, IMessage data)
|
||||||
{
|
{
|
||||||
if (!resp.Verify())
|
if (sig is null || sig.Key is null || sig.Sign is null)
|
||||||
throw new FormatException($"invalid response, type={resp.GetType()}");
|
return false;
|
||||||
var status = resp.MetaHeader.Status.ToModel();
|
|
||||||
if (!status.IsSuccess())
|
using var key = sig.Key.ToByteArray().LoadPublicKey();
|
||||||
{
|
var data2Verify = data is null ? Array.Empty<byte>() : data.ToByteArray();
|
||||||
throw new ApplicationException(status.ToString());
|
|
||||||
}
|
return key.VerifyData(data2Verify, sig.Sign.ToByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool VerifyMatryoskaLevel(IMessage body, IMetaHeader meta, IVerificationHeader verification)
|
||||||
|
{
|
||||||
|
if (!verification.MetaSignature.VerifyMessagePart(meta))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var origin = verification.GetOrigin();
|
||||||
|
|
||||||
|
if (!verification.OriginSignature.VerifyMessagePart(origin))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (origin is null)
|
||||||
|
return verification.BodySignature.VerifyMessagePart(body);
|
||||||
|
|
||||||
|
return verification.BodySignature is null && VerifyMatryoskaLevel(body, meta.GetOrigin(), origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Verify(this IVerificableMessage message)
|
||||||
|
{
|
||||||
|
return VerifyMatryoskaLevel(message.GetBody(), message.GetMetaHeader(), message.GetVerificationHeader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CheckResponse(IResponse resp)
|
||||||
|
{
|
||||||
|
if (!resp.Verify())
|
||||||
|
throw new FormatException($"invalid response, type={resp.GetType()}");
|
||||||
|
|
||||||
|
var status = resp.MetaHeader.Status.ToModel();
|
||||||
|
if (!status.IsSuccess())
|
||||||
|
throw new ApplicationException(status.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,23 +1,24 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace FrostFS.SDK.Cryptography
|
namespace FrostFS.SDK.Cryptography;
|
||||||
|
|
||||||
|
internal static class ArrayHelper
|
||||||
{
|
{
|
||||||
internal static class ArrayHelper
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static byte[] Concat(params byte[][] buffers)
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
var length = buffers.Sum(buffer => buffer.Length);
|
||||||
public static byte[] Concat(params byte[][] buffers)
|
|
||||||
|
var dst = new byte[length];
|
||||||
|
var p = 0;
|
||||||
|
foreach (var src in buffers)
|
||||||
{
|
{
|
||||||
var length = buffers.Sum(buffer => buffer.Length);
|
Buffer.BlockCopy(src, 0, dst, p, src.Length);
|
||||||
|
p += src.Length;
|
||||||
var dst = new byte[length];
|
|
||||||
var p = 0;
|
|
||||||
foreach (var src in buffers)
|
|
||||||
{
|
|
||||||
Buffer.BlockCopy(src, 0, dst, p, src.Length);
|
|
||||||
p += src.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return dst;
|
||||||
}
|
}
|
||||||
}
|
}
|
20
src/FrostFS.SDK.Cryptography/AssemblyInfo.cs
Normal file
20
src/FrostFS.SDK.Cryptography/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// In SDK-style projects such as this one, several assembly attributes that were historically
|
||||||
|
// defined in this file are now automatically added during build and populated with
|
||||||
|
// values defined in project properties. For details of which attributes are included
|
||||||
|
// and how to customise this process see: https://aka.ms/assembly-info-properties
|
||||||
|
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible to COM
|
||||||
|
// components. If you need to access a type in this assembly from COM, set the ComVisible
|
||||||
|
// attribute to true on that type.
|
||||||
|
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM.
|
||||||
|
|
||||||
|
[assembly: Guid("08a8487e-39ce-41fb-9c24-13f73ff2bde0")]
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleToAttribute("FrostFS.SDK.Cryptography.Test")]
|
|
@ -1,77 +1,97 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace FrostFS.SDK.Cryptography
|
using Org.BouncyCastle.Security.Certificates;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.Cryptography;
|
||||||
|
|
||||||
|
public static class Base58
|
||||||
{
|
{
|
||||||
public static class Base58
|
public const string Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
public static byte[] Base58CheckDecode(this string input)
|
||||||
{
|
{
|
||||||
public const string Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
if (input is null)
|
||||||
|
throw new ArgumentNullException(nameof(input));
|
||||||
|
|
||||||
|
byte[] buffer = Decode(input);
|
||||||
|
|
||||||
public static byte[] Base58CheckDecode(this string input)
|
if (buffer.Length < 4)
|
||||||
|
throw new FormatException();
|
||||||
|
|
||||||
|
byte[] checksum = buffer[0..(buffer.Length - 4)].Sha256().Sha256();
|
||||||
|
|
||||||
|
if (!buffer.AsSpan(buffer.Length - 4).SequenceEqual(checksum[..4].AsSpan()))
|
||||||
|
throw new FormatException();
|
||||||
|
|
||||||
|
var ret = buffer[..^4];
|
||||||
|
Array.Clear(buffer, 0, buffer.Length);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Base58CheckEncode(this ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
byte[] checksum = data.ToArray().Sha256().Sha256();
|
||||||
|
Span<byte> buffer = stackalloc byte[data.Length + 4];
|
||||||
|
data.CopyTo(buffer);
|
||||||
|
checksum[..4].AsSpan().CopyTo(buffer[data.Length..]);
|
||||||
|
var ret = Encode(buffer);
|
||||||
|
buffer.Clear();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] Decode(string input)
|
||||||
|
{
|
||||||
|
// Decode Base58 string to BigInteger
|
||||||
|
var bi = BigInteger.Zero;
|
||||||
|
for (int i = 0; i < input.Length; i++)
|
||||||
{
|
{
|
||||||
if (input is null) throw new ArgumentNullException(nameof(input));
|
int digit = Alphabet.IndexOf(input[i]);
|
||||||
byte[] buffer = Decode(input);
|
if (digit < 0)
|
||||||
if (buffer.Length < 4) throw new FormatException();
|
throw new FormatException($"Invalid Base58 character '{input[i]}' at position {i}");
|
||||||
byte[] checksum = buffer[0..(buffer.Length - 4)].Sha256().Sha256();
|
|
||||||
if (!buffer.AsSpan(^4).SequenceEqual(checksum.AsSpan(..4)))
|
bi = bi * Alphabet.Length + digit;
|
||||||
throw new FormatException();
|
|
||||||
var ret = buffer[..^4];
|
|
||||||
Array.Clear(buffer, 0, buffer.Length);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Base58CheckEncode(this ReadOnlySpan<byte> data)
|
int leadingZeroCount = input.TakeWhile(c => c == Alphabet[0]).Count();
|
||||||
|
var leadingZeros = new byte[leadingZeroCount];
|
||||||
|
|
||||||
|
if (bi.IsZero)
|
||||||
|
return leadingZeros;
|
||||||
|
|
||||||
|
var bytesBigEndian = bi.ToByteArray().Reverse();
|
||||||
|
|
||||||
|
var firstNonZeroIndex = 0;
|
||||||
|
|
||||||
|
while(bytesBigEndian.ElementAt(firstNonZeroIndex) == 0x0)
|
||||||
|
firstNonZeroIndex++;
|
||||||
|
|
||||||
|
var bytesWithoutLeadingZeros = bytesBigEndian.Skip(firstNonZeroIndex).ToArray();
|
||||||
|
|
||||||
|
return ArrayHelper.Concat(leadingZeros, bytesWithoutLeadingZeros);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Encode(ReadOnlySpan<byte> input)
|
||||||
|
{
|
||||||
|
var data = input.ToArray().Reverse().Concat(new byte[] { 0 }).ToArray();
|
||||||
|
BigInteger value = new(data);
|
||||||
|
|
||||||
|
// Encode BigInteger to Base58 string
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
while (value > 0)
|
||||||
{
|
{
|
||||||
byte[] checksum = data.ToArray().Sha256().Sha256();
|
value = BigInteger.DivRem(value, Alphabet.Length, out var remainder);
|
||||||
Span<byte> buffer = stackalloc byte[data.Length + 4];
|
sb.Insert(0, Alphabet[(int)remainder]);
|
||||||
data.CopyTo(buffer);
|
|
||||||
checksum.AsSpan(..4).CopyTo(buffer[data.Length..]);
|
|
||||||
var ret = Encode(buffer);
|
|
||||||
buffer.Clear();
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] Decode(string input)
|
// Append `1` for each leading 0 byte
|
||||||
|
for (int i = 0; i < input.Length && input[i] == 0; i++)
|
||||||
{
|
{
|
||||||
// Decode Base58 string to BigInteger
|
sb.Insert(0, Alphabet[0]);
|
||||||
var bi = BigInteger.Zero;
|
|
||||||
for (int i = 0; i < input.Length; i++)
|
|
||||||
{
|
|
||||||
int digit = Alphabet.IndexOf(input[i]);
|
|
||||||
if (digit < 0)
|
|
||||||
throw new FormatException($"Invalid Base58 character '{input[i]}' at position {i}");
|
|
||||||
bi = bi * Alphabet.Length + digit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode BigInteger to byte[]
|
|
||||||
// Leading zero bytes get encoded as leading `1` characters
|
|
||||||
int leadingZeroCount = input.TakeWhile(c => c == Alphabet[0]).Count();
|
|
||||||
var leadingZeros = new byte[leadingZeroCount];
|
|
||||||
if (bi.IsZero) return leadingZeros;
|
|
||||||
var bytesWithoutLeadingZeros = bi.ToByteArray(isUnsigned: true, isBigEndian: true);
|
|
||||||
return ArrayHelper.Concat(leadingZeros, bytesWithoutLeadingZeros);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Encode(ReadOnlySpan<byte> input)
|
|
||||||
{
|
|
||||||
// Decode byte[] to BigInteger
|
|
||||||
BigInteger value = new(input, isUnsigned: true, isBigEndian: true);
|
|
||||||
|
|
||||||
// Encode BigInteger to Base58 string
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
|
|
||||||
while (value > 0)
|
|
||||||
{
|
|
||||||
value = BigInteger.DivRem(value, Alphabet.Length, out var remainder);
|
|
||||||
sb.Insert(0, Alphabet[(int)remainder]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append `1` for each leading 0 byte
|
|
||||||
for (int i = 0; i < input.Length && input[i] == 0; i++)
|
|
||||||
{
|
|
||||||
sb.Insert(0, Alphabet[0]);
|
|
||||||
}
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
}
|
||||||
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<LangVersion>12.0</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Google.Protobuf" Version="3.27.0" />
|
||||||
|
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
|
||||||
|
<PackageReference Include="System.Memory" Version="4.5.5" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BouncyCastle.NetCore" Version="2.2.1" />
|
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.26.1" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using System.Buffers.Binary;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using FrostFS.SDK.Cryptography.Tz;
|
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
using Org.BouncyCastle.Crypto.Digests;
|
using Org.BouncyCastle.Crypto.Digests;
|
||||||
|
using System;
|
||||||
|
using System.Buffers.Binary;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace FrostFS.SDK.Cryptography;
|
namespace FrostFS.SDK.Cryptography;
|
||||||
|
|
||||||
|
@ -31,10 +31,8 @@ public static class Helper
|
||||||
|
|
||||||
internal static byte[] Sha256(this ReadOnlySpan<byte> value)
|
internal static byte[] Sha256(this ReadOnlySpan<byte> value)
|
||||||
{
|
{
|
||||||
var buffer = new byte[32];
|
|
||||||
using var sha256 = SHA256.Create();
|
using var sha256 = SHA256.Create();
|
||||||
sha256.TryComputeHash(value, buffer, out _);
|
return sha256.ComputeHash(value.ToArray());
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ByteString Sha256(this IMessage data)
|
public static ByteString Sha256(this IMessage data)
|
||||||
|
@ -47,18 +45,7 @@ public static class Helper
|
||||||
return ByteString.CopyFrom(data.ToByteArray().Sha256());
|
return ByteString.CopyFrom(data.ToByteArray().Sha256());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ByteString TzHash(this IMessage data)
|
|
||||||
{
|
|
||||||
return ByteString.CopyFrom(new TzHash().ComputeHash(data.ToByteArray()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ByteString TzHash(this ByteString data)
|
|
||||||
{
|
|
||||||
return ByteString.CopyFrom(new TzHash().ComputeHash(data.ToByteArray()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static ulong Murmur64(this byte[] value, uint seed)
|
public static ulong Murmur64(this byte[] value, uint seed)
|
||||||
{
|
{
|
||||||
using var murmur = new Murmur3_128(seed);
|
using var murmur = new Murmur3_128(seed);
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
using System.Buffers.Binary;
|
using System;
|
||||||
|
using System.Buffers.Binary;
|
||||||
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using Org.BouncyCastle.Asn1.Sec;
|
using Org.BouncyCastle.Asn1.Sec;
|
||||||
|
|
||||||
namespace FrostFS.SDK.Cryptography;
|
namespace FrostFS.SDK.Cryptography;
|
||||||
|
@ -22,8 +25,10 @@ public static class KeyExtension
|
||||||
$"{nameof(Compress)} argument isn't uncompressed public key. " +
|
$"{nameof(Compress)} argument isn't uncompressed public key. " +
|
||||||
$"expected length={UncompressedPublicKeyLength}, actual={publicKey.Length}"
|
$"expected length={UncompressedPublicKeyLength}, actual={publicKey.Length}"
|
||||||
);
|
);
|
||||||
|
|
||||||
var secp256R1 = SecNamedCurves.GetByName("secp256r1");
|
var secp256R1 = SecNamedCurves.GetByName("secp256r1");
|
||||||
var point = secp256R1.Curve.DecodePoint(publicKey);
|
var point = secp256R1.Curve.DecodePoint(publicKey);
|
||||||
|
|
||||||
return point.GetEncoded(true);
|
return point.GetEncoded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,8 +39,10 @@ public static class KeyExtension
|
||||||
$"{nameof(Decompress)} argument isn't compressed public key. " +
|
$"{nameof(Decompress)} argument isn't compressed public key. " +
|
||||||
$"expected length={CompressedPublicKeyLength}, actual={publicKey.Length}"
|
$"expected length={CompressedPublicKeyLength}, actual={publicKey.Length}"
|
||||||
);
|
);
|
||||||
|
|
||||||
var secp256R1 = SecNamedCurves.GetByName("secp256r1");
|
var secp256R1 = SecNamedCurves.GetByName("secp256r1");
|
||||||
var point = secp256R1.Curve.DecodePoint(publicKey);
|
var point = secp256R1.Curve.DecodePoint(publicKey);
|
||||||
|
|
||||||
return point.GetEncoded(false);
|
return point.GetEncoded(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,10 +53,12 @@ public static class KeyExtension
|
||||||
$"{nameof(CreateSignatureRedeemScript)} argument isn't compressed public key. " +
|
$"{nameof(CreateSignatureRedeemScript)} argument isn't compressed public key. " +
|
||||||
$"expected length={CompressedPublicKeyLength}, actual={publicKey.Length}"
|
$"expected length={CompressedPublicKeyLength}, actual={publicKey.Length}"
|
||||||
);
|
);
|
||||||
|
|
||||||
var script = new byte[] { 0x0c, CompressedPublicKeyLength }; //PUSHDATA1 33
|
var script = new byte[] { 0x0c, CompressedPublicKeyLength }; //PUSHDATA1 33
|
||||||
script = ArrayHelper.Concat(script, publicKey);
|
script = ArrayHelper.Concat(script, publicKey);
|
||||||
script = ArrayHelper.Concat(script, new byte[] { 0x41 }); //SYSCALL
|
script = ArrayHelper.Concat(script, new byte[] { 0x41 }); //SYSCALL
|
||||||
script = ArrayHelper.Concat(script, BitConverter.GetBytes(CheckSigDescriptor)); //Neo_Crypto_CheckSig
|
script = ArrayHelper.Concat(script, BitConverter.GetBytes(CheckSigDescriptor)); //Neo_Crypto_CheckSig
|
||||||
|
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,15 +73,20 @@ public static class KeyExtension
|
||||||
Span<byte> data = stackalloc byte[21];
|
Span<byte> data = stackalloc byte[21];
|
||||||
data[0] = version;
|
data[0] = version;
|
||||||
scriptHash.CopyTo(data[1..]);
|
scriptHash.CopyTo(data[1..]);
|
||||||
|
|
||||||
return Base58.Base58CheckEncode(data);
|
return Base58.Base58CheckEncode(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] GetPrivateKeyFromWIF(string wif)
|
private static byte[] GetPrivateKeyFromWIF(string wif)
|
||||||
{
|
{
|
||||||
if (wif == null) throw new ArgumentNullException();
|
if (wif == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
var data = wif.Base58CheckDecode();
|
var data = wif.Base58CheckDecode();
|
||||||
|
|
||||||
if (data.Length != 34 || data[0] != 0x80 || data[33] != 0x01)
|
if (data.Length != 34 || data[0] != 0x80 || data[33] != 0x01)
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
|
|
||||||
var privateKey = new byte[32];
|
var privateKey = new byte[32];
|
||||||
Buffer.BlockCopy(data, 1, privateKey, 0, privateKey.Length);
|
Buffer.BlockCopy(data, 1, privateKey, 0, privateKey.Length);
|
||||||
Array.Clear(data, 0, data.Length);
|
Array.Clear(data, 0, data.Length);
|
||||||
|
@ -92,6 +106,7 @@ public static class KeyExtension
|
||||||
$" isn't encoded compressed public key. " +
|
$" isn't encoded compressed public key. " +
|
||||||
$"expected length={CompressedPublicKeyLength}, actual={publicKey.Length}"
|
$"expected length={CompressedPublicKeyLength}, actual={publicKey.Length}"
|
||||||
);
|
);
|
||||||
|
|
||||||
return publicKey.GetScriptHash().ToAddress(NeoAddressVersion);
|
return publicKey.GetScriptHash().ToAddress(NeoAddressVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,12 +145,14 @@ public static class KeyExtension
|
||||||
Y = publicKey[32..]
|
Y = publicKey[32..]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ECDsa LoadWif(this string wif)
|
public static ECDsa LoadWif(this string wif)
|
||||||
{
|
{
|
||||||
var privateKey = GetPrivateKeyFromWIF(wif);
|
var privateKey = GetPrivateKeyFromWIF(wif);
|
||||||
|
|
||||||
return LoadPrivateKey(privateKey);
|
return LoadPrivateKey(privateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,6 +168,7 @@ public static class KeyExtension
|
||||||
Y = publicKeyFull[32..]
|
Y = publicKeyFull[32..]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,121 +1,125 @@
|
||||||
|
using System;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace FrostFS.SDK.Cryptography
|
namespace FrostFS.SDK.Cryptography;
|
||||||
|
|
||||||
|
internal class Murmur3_128 : HashAlgorithm
|
||||||
{
|
{
|
||||||
internal class Murmur3_128 : HashAlgorithm
|
private const ulong c1 = 0x87c37b91114253d5;
|
||||||
|
private const ulong c2 = 0x4cf5ad432745937f;
|
||||||
|
private const uint m = 5;
|
||||||
|
private const uint n1 = 0x52dce729;
|
||||||
|
private const uint n2 = 0x38495ab5;
|
||||||
|
|
||||||
|
private ulong h1;
|
||||||
|
private ulong h2;
|
||||||
|
private readonly uint seed;
|
||||||
|
private int length;
|
||||||
|
|
||||||
|
public Murmur3_128(uint seed)
|
||||||
{
|
{
|
||||||
private const ulong c1 = 0x87c37b91114253d5;
|
this.seed = seed;
|
||||||
private const ulong c2 = 0x4cf5ad432745937f;
|
Initialize();
|
||||||
private const uint m = 5;
|
}
|
||||||
private const uint n1 = 0x52dce729;
|
|
||||||
private const uint n2 = 0x38495ab5;
|
|
||||||
|
|
||||||
private ulong h1;
|
protected override void HashCore(byte[] array, int ibStart, int cbSize)
|
||||||
private ulong h2;
|
{
|
||||||
private readonly uint seed;
|
length += cbSize;
|
||||||
private int length;
|
int remainder = cbSize & 15;
|
||||||
|
int alignedLength = ibStart + (cbSize - remainder);
|
||||||
public Murmur3_128(uint seed)
|
|
||||||
|
for (int i = ibStart; i < alignedLength; i += 16)
|
||||||
{
|
{
|
||||||
this.seed = seed;
|
ulong k1 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i));
|
||||||
Initialize();
|
ulong k2 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i + 8));
|
||||||
}
|
|
||||||
|
|
||||||
protected override void HashCore(byte[] array, int ibStart, int cbSize)
|
k1 *= c1;
|
||||||
{
|
k1 = (k1 << 31) | (k1 >> 33);
|
||||||
length += cbSize;
|
k1 *= c2;
|
||||||
int remainder = cbSize & 15;
|
h1 ^= k1;
|
||||||
int alignedLength = ibStart + (cbSize - remainder);
|
h1 = (h1 << 27) | (h1 >> 37);
|
||||||
for (int i = ibStart; i < alignedLength; i += 16)
|
|
||||||
{
|
|
||||||
ulong k1 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i));
|
|
||||||
ulong k2 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i + 8));
|
|
||||||
|
|
||||||
k1 *= c1;
|
|
||||||
k1 = (k1 << 31) | (k1 >> 33);
|
|
||||||
k1 *= c2;
|
|
||||||
h1 ^= k1;
|
|
||||||
h1 = (h1 << 27) | (h1 >> 37);
|
|
||||||
h1 += h2;
|
|
||||||
h1 = h1 * m + n1;
|
|
||||||
|
|
||||||
k2 *= c2;
|
|
||||||
k2 = (k2 << 33) | (k2 >> 31);
|
|
||||||
k2 *= c1;
|
|
||||||
h2 ^= k2;
|
|
||||||
h2 = (h2 << 31) | (h2 >> 33);
|
|
||||||
h2 += h1;
|
|
||||||
h2 = h2 * m + n2;
|
|
||||||
}
|
|
||||||
if (remainder > 0)
|
|
||||||
{
|
|
||||||
ulong k1 = 0, k2 = 0;
|
|
||||||
switch (remainder)
|
|
||||||
{
|
|
||||||
case 15: k2 ^= (ulong)array[alignedLength + 14] << 48; goto case 14;
|
|
||||||
case 14: k2 ^= (ulong)array[alignedLength + 13] << 40; goto case 13;
|
|
||||||
case 13: k2 ^= (ulong)array[alignedLength + 12] << 32; goto case 12;
|
|
||||||
case 12: k2 ^= (ulong)array[alignedLength + 11] << 24; goto case 11;
|
|
||||||
case 11: k2 ^= (ulong)array[alignedLength + 10] << 16; goto case 10;
|
|
||||||
case 10: k2 ^= (ulong)array[alignedLength + 9] << 8; goto case 9;
|
|
||||||
case 9:
|
|
||||||
{
|
|
||||||
k2 ^= (ulong)array[alignedLength + 8];
|
|
||||||
k2 *= c2;
|
|
||||||
k2 = (k2 << 33) | (k2 >> 31);
|
|
||||||
k2 *= c1;
|
|
||||||
h2 ^= k2;
|
|
||||||
goto case 8;
|
|
||||||
}
|
|
||||||
case 8: k1 ^= (ulong)array[alignedLength + 7] << 56; goto case 7;
|
|
||||||
case 7: k1 ^= (ulong)array[alignedLength + 6] << 48; goto case 6;
|
|
||||||
case 6: k1 ^= (ulong)array[alignedLength + 5] << 40; goto case 5;
|
|
||||||
case 5: k1 ^= (ulong)array[alignedLength + 4] << 32; goto case 4;
|
|
||||||
case 4: k1 ^= (ulong)array[alignedLength + 3] << 24; goto case 3;
|
|
||||||
case 3: k1 ^= (ulong)array[alignedLength + 2] << 16; goto case 2;
|
|
||||||
case 2: k1 ^= (ulong)array[alignedLength + 1] << 8; goto case 1;
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
k1 ^= (ulong)array[alignedLength];
|
|
||||||
k1 *= c1;
|
|
||||||
k1 = (k1 << 31) | (k1 >> 33);
|
|
||||||
k1 *= c2;
|
|
||||||
h1 ^= k1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override byte[] HashFinal()
|
|
||||||
{
|
|
||||||
h1 ^= (ulong)length;
|
|
||||||
h2 ^= (ulong)length;
|
|
||||||
h1 += h2;
|
h1 += h2;
|
||||||
h2 += h1;
|
h1 = h1 * m + n1;
|
||||||
h1 = Fimix64(h1);
|
|
||||||
h2 = Fimix64(h2);
|
|
||||||
h1 += h2;
|
|
||||||
h2 += h1;
|
|
||||||
return BitConverter.GetBytes(h1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Initialize()
|
k2 *= c2;
|
||||||
{
|
k2 = (k2 << 33) | (k2 >> 31);
|
||||||
length = 0;
|
k2 *= c1;
|
||||||
h1 = seed;
|
h2 ^= k2;
|
||||||
h2 = seed;
|
h2 = (h2 << 31) | (h2 >> 33);
|
||||||
|
h2 += h1;
|
||||||
|
h2 = h2 * m + n2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ulong Fimix64(ulong k)
|
if (remainder > 0)
|
||||||
{
|
{
|
||||||
k ^= k >> 33;
|
ulong k1 = 0, k2 = 0;
|
||||||
k *= 0xff51afd7ed558ccd;
|
switch (remainder)
|
||||||
k ^= k >> 33;
|
{
|
||||||
k *= 0xc4ceb9fe1a85ec53;
|
case 15: k2 ^= (ulong)array[alignedLength + 14] << 48; goto case 14;
|
||||||
k ^= k >> 33;
|
case 14: k2 ^= (ulong)array[alignedLength + 13] << 40; goto case 13;
|
||||||
return k;
|
case 13: k2 ^= (ulong)array[alignedLength + 12] << 32; goto case 12;
|
||||||
|
case 12: k2 ^= (ulong)array[alignedLength + 11] << 24; goto case 11;
|
||||||
|
case 11: k2 ^= (ulong)array[alignedLength + 10] << 16; goto case 10;
|
||||||
|
case 10: k2 ^= (ulong)array[alignedLength + 9] << 8; goto case 9;
|
||||||
|
case 9:
|
||||||
|
{
|
||||||
|
k2 ^= (ulong)array[alignedLength + 8];
|
||||||
|
k2 *= c2;
|
||||||
|
k2 = (k2 << 33) | (k2 >> 31);
|
||||||
|
k2 *= c1;
|
||||||
|
h2 ^= k2;
|
||||||
|
goto case 8;
|
||||||
|
}
|
||||||
|
case 8: k1 ^= (ulong)array[alignedLength + 7] << 56; goto case 7;
|
||||||
|
case 7: k1 ^= (ulong)array[alignedLength + 6] << 48; goto case 6;
|
||||||
|
case 6: k1 ^= (ulong)array[alignedLength + 5] << 40; goto case 5;
|
||||||
|
case 5: k1 ^= (ulong)array[alignedLength + 4] << 32; goto case 4;
|
||||||
|
case 4: k1 ^= (ulong)array[alignedLength + 3] << 24; goto case 3;
|
||||||
|
case 3: k1 ^= (ulong)array[alignedLength + 2] << 16; goto case 2;
|
||||||
|
case 2: k1 ^= (ulong)array[alignedLength + 1] << 8; goto case 1;
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
k1 ^= (ulong)array[alignedLength];
|
||||||
|
k1 *= c1;
|
||||||
|
k1 = (k1 << 31) | (k1 >> 33);
|
||||||
|
k1 *= c2;
|
||||||
|
h1 ^= k1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override byte[] HashFinal()
|
||||||
|
{
|
||||||
|
h1 ^= (ulong)length;
|
||||||
|
h2 ^= (ulong)length;
|
||||||
|
h1 += h2;
|
||||||
|
h2 += h1;
|
||||||
|
h1 = Fimix64(h1);
|
||||||
|
h2 = Fimix64(h2);
|
||||||
|
h1 += h2;
|
||||||
|
h2 += h1;
|
||||||
|
|
||||||
|
return BitConverter.GetBytes(h1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
length = 0;
|
||||||
|
h1 = seed;
|
||||||
|
h2 = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong Fimix64(ulong k)
|
||||||
|
{
|
||||||
|
k ^= k >> 33;
|
||||||
|
k *= 0xff51afd7ed558ccd;
|
||||||
|
k ^= k >> 33;
|
||||||
|
k *= 0xc4ceb9fe1a85ec53;
|
||||||
|
k ^= k >> 33;
|
||||||
|
|
||||||
|
return k;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
271
src/FrostFS.SDK.Cryptography/Range.cs
Normal file
271
src/FrostFS.SDK.Cryptography/Range.cs
Normal file
|
@ -0,0 +1,271 @@
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace System
|
||||||
|
{
|
||||||
|
/// <summary>Represent a type can be used to index a collection either from the start or the end.</summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Index is used by the C# compiler to support the new index syntax
|
||||||
|
/// <code>
|
||||||
|
/// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ;
|
||||||
|
/// int lastElement = someArray[^1]; // lastElement = 5
|
||||||
|
/// </code>
|
||||||
|
/// </remarks>
|
||||||
|
internal readonly struct Index : IEquatable<Index>
|
||||||
|
{
|
||||||
|
private readonly int _value;
|
||||||
|
|
||||||
|
/// <summary>Construct an Index using a value and indicating if the index is from the start or from the end.</summary>
|
||||||
|
/// <param name="value">The index value. it has to be zero or positive number.</param>
|
||||||
|
/// <param name="fromEnd">Indicating if the index is from the start or from the end.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element.
|
||||||
|
/// </remarks>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Index(int value, bool fromEnd = false)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fromEnd)
|
||||||
|
_value = ~value;
|
||||||
|
else
|
||||||
|
_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following private constructors mainly created for perf reason to avoid the checks
|
||||||
|
private Index(int value)
|
||||||
|
{
|
||||||
|
_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Create an Index pointing at first element.</summary>
|
||||||
|
public static Index Start => new Index(0);
|
||||||
|
|
||||||
|
/// <summary>Create an Index pointing at beyond last element.</summary>
|
||||||
|
public static Index End => new Index(~0);
|
||||||
|
|
||||||
|
/// <summary>Create an Index from the start at the position indicated by the value.</summary>
|
||||||
|
/// <param name="value">The index value from the start.</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Index FromStart(int value)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Index(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Create an Index from the end at the position indicated by the value.</summary>
|
||||||
|
/// <param name="value">The index value from the end.</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Index FromEnd(int value)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Index(~value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Returns the index value.</summary>
|
||||||
|
public int Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_value < 0)
|
||||||
|
{
|
||||||
|
return ~_value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Indicates whether the index is from the start or the end.</summary>
|
||||||
|
public bool IsFromEnd => _value < 0;
|
||||||
|
|
||||||
|
/// <summary>Calculate the offset from the start using the giving collection length.</summary>
|
||||||
|
/// <param name="length">The length of the collection that the Index will be used with. length has to be a positive value</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// For performance reason, we don't validate the input length parameter and the returned offset value against negative values.
|
||||||
|
/// we don't validate either the returned offset is greater than the input length.
|
||||||
|
/// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and
|
||||||
|
/// then used to index a collection will get out of range exception which will be same affect as the validation.
|
||||||
|
/// </remarks>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int GetOffset(int length)
|
||||||
|
{
|
||||||
|
var offset = _value;
|
||||||
|
if (IsFromEnd)
|
||||||
|
{
|
||||||
|
// offset = length - (~value)
|
||||||
|
// offset = length + (~(~value) + 1)
|
||||||
|
// offset = length + value + 1
|
||||||
|
|
||||||
|
offset += length + 1;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Indicates whether the current Index object is equal to another object of the same type.</summary>
|
||||||
|
/// <param name="value">An object to compare with this object</param>
|
||||||
|
public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value;
|
||||||
|
|
||||||
|
/// <summary>Indicates whether the current Index object is equal to another Index object.</summary>
|
||||||
|
/// <param name="other">An object to compare with this object</param>
|
||||||
|
public bool Equals(Index other) => _value == other._value;
|
||||||
|
|
||||||
|
/// <summary>Returns the hash code for this instance.</summary>
|
||||||
|
public override int GetHashCode() => _value;
|
||||||
|
|
||||||
|
/// <summary>Converts integer number to an Index.</summary>
|
||||||
|
public static implicit operator Index(int value) => FromStart(value);
|
||||||
|
|
||||||
|
/// <summary>Converts the value of the current Index object to its equivalent string representation.</summary>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (IsFromEnd)
|
||||||
|
return "^" + ((uint)Value).ToString();
|
||||||
|
|
||||||
|
return ((uint)Value).ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Represent a range has start and end indexes.</summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Range is used by the C# compiler to support the range syntax.
|
||||||
|
/// <code>
|
||||||
|
/// int[] someArray = new int[5] { 1, 2, 3, 4, 5 };
|
||||||
|
/// int[] subArray1 = someArray[0..2]; // { 1, 2 }
|
||||||
|
/// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
|
||||||
|
/// </code>
|
||||||
|
/// </remarks>
|
||||||
|
internal readonly struct Range : IEquatable<Range>
|
||||||
|
{
|
||||||
|
/// <summary>Represent the inclusive start index of the Range.</summary>
|
||||||
|
public Index Start { get; }
|
||||||
|
|
||||||
|
/// <summary>Represent the exclusive end index of the Range.</summary>
|
||||||
|
public Index End { get; }
|
||||||
|
|
||||||
|
/// <summary>Construct a Range object using the start and end indexes.</summary>
|
||||||
|
/// <param name="start">Represent the inclusive start index of the range.</param>
|
||||||
|
/// <param name="end">Represent the exclusive end index of the range.</param>
|
||||||
|
public Range(Index start, Index end)
|
||||||
|
{
|
||||||
|
Start = start;
|
||||||
|
End = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Indicates whether the current Range object is equal to another object of the same type.</summary>
|
||||||
|
/// <param name="value">An object to compare with this object</param>
|
||||||
|
public override bool Equals(object? value) =>
|
||||||
|
value is Range r &&
|
||||||
|
r.Start.Equals(Start) &&
|
||||||
|
r.End.Equals(End);
|
||||||
|
|
||||||
|
/// <summary>Indicates whether the current Range object is equal to another Range object.</summary>
|
||||||
|
/// <param name="other">An object to compare with this object</param>
|
||||||
|
public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End);
|
||||||
|
|
||||||
|
/// <summary>Returns the hash code for this instance.</summary>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Start.GetHashCode() * 31 + End.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Converts the value of the current Range object to its equivalent string representation.</summary>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Start + ".." + End;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Create a Range object starting from start index to the end of the collection.</summary>
|
||||||
|
public static Range StartAt(Index start) => new Range(start, Index.End);
|
||||||
|
|
||||||
|
/// <summary>Create a Range object starting from first element in the collection to the end Index.</summary>
|
||||||
|
public static Range EndAt(Index end) => new Range(Index.Start, end);
|
||||||
|
|
||||||
|
/// <summary>Create a Range object starting from first element to the end.</summary>
|
||||||
|
public static Range All => new Range(Index.Start, Index.End);
|
||||||
|
|
||||||
|
/// <summary>Calculate the start offset and length of range object using a collection length.</summary>
|
||||||
|
/// <param name="length">The length of the collection that the range will be used with. length has to be a positive value.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// For performance reason, we don't validate the input length parameter against negative values.
|
||||||
|
/// It is expected Range will be used with collections which always have non negative length/count.
|
||||||
|
/// We validate the range is inside the length scope though.
|
||||||
|
/// </remarks>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public (int Offset, int Length) GetOffsetAndLength(int length)
|
||||||
|
{
|
||||||
|
int start;
|
||||||
|
var startIndex = Start;
|
||||||
|
if (startIndex.IsFromEnd)
|
||||||
|
start = length - startIndex.Value;
|
||||||
|
else
|
||||||
|
start = startIndex.Value;
|
||||||
|
|
||||||
|
int end;
|
||||||
|
var endIndex = End;
|
||||||
|
if (endIndex.IsFromEnd)
|
||||||
|
end = length - endIndex.Value;
|
||||||
|
else
|
||||||
|
end = endIndex.Value;
|
||||||
|
|
||||||
|
if ((uint)end > (uint)length || (uint)start > (uint)end)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(length));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (start, end - start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace System.Runtime.CompilerServices
|
||||||
|
{
|
||||||
|
internal static class RuntimeHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Slices the specified array using the specified range.
|
||||||
|
/// </summary>
|
||||||
|
public static T[] GetSubArray<T>(T[] array, Range range)
|
||||||
|
{
|
||||||
|
if (array == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(array));
|
||||||
|
}
|
||||||
|
|
||||||
|
(int offset, int length) = range.GetOffsetAndLength(array.Length);
|
||||||
|
|
||||||
|
if (default(T) != null || typeof(T[]) == array.GetType())
|
||||||
|
{
|
||||||
|
// We know the type of the array to be exactly T[].
|
||||||
|
|
||||||
|
if (length == 0)
|
||||||
|
{
|
||||||
|
return Array.Empty<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var dest = new T[length];
|
||||||
|
Array.Copy(array, offset, dest, 0, length);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The array is actually a U[] where U:T.
|
||||||
|
var dest = (T[])Array.CreateInstance(array.GetType().GetElementType(), length);
|
||||||
|
Array.Copy(array, offset, dest, 0, length);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,253 +1,253 @@
|
||||||
using System.Security.Cryptography;
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace FrostFS.SDK.Cryptography.Tz
|
namespace FrostFS.SDK.Cryptography.Tz;
|
||||||
|
|
||||||
|
// GF127 represents element of GF(2^127)
|
||||||
|
public class GF127 : IEquatable<GF127>
|
||||||
{
|
{
|
||||||
// GF127 represents element of GF(2^127)
|
public const int ByteSize = 16;
|
||||||
public class GF127 : IEquatable<GF127>
|
public const ulong MSB64 = (ulong)1 << 63; // 2^63
|
||||||
|
public static readonly GF127 Zero = new(0, 0);
|
||||||
|
public static readonly GF127 One = new(1, 0);
|
||||||
|
public static readonly GF127 X127X631 = new(MSB64 + 1, MSB64); // x^127+x^63+1
|
||||||
|
|
||||||
|
private readonly ulong[] _data;
|
||||||
|
|
||||||
|
public ulong this[int index]
|
||||||
{
|
{
|
||||||
public const int ByteSize = 16;
|
get { return _data[index]; }
|
||||||
public const ulong MSB64 = (ulong)1 << 63; // 2^63
|
set { _data[index] = value; }
|
||||||
public static readonly GF127 Zero = new(0, 0);
|
}
|
||||||
public static readonly GF127 One = new(1, 0);
|
|
||||||
public static readonly GF127 X127X631 = new(MSB64 + 1, MSB64); // x^127+x^63+1
|
|
||||||
|
|
||||||
private readonly ulong[] _data;
|
public GF127(ulong[] value)
|
||||||
|
{
|
||||||
|
if (value is null || value.Length != 2)
|
||||||
|
throw new ArgumentException(nameof(value) + "is invalid");
|
||||||
|
_data = value;
|
||||||
|
}
|
||||||
|
|
||||||
public ulong this[int index]
|
// Constructs new element of GF(2^127) as u1*x^64 + u0.
|
||||||
{
|
// It is assumed that u1 has zero MSB.
|
||||||
get { return _data[index]; }
|
public GF127(ulong u0, ulong u1) : this(new ulong[] { u0, u1 })
|
||||||
set { _data[index] = value; }
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public GF127(ulong[] value)
|
public GF127() : this(0, 0)
|
||||||
{
|
{
|
||||||
if (value is null || value.Length != 2)
|
}
|
||||||
throw new ArgumentException(nameof(value) + "is invalid");
|
|
||||||
_data = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructs new element of GF(2^127) as u1*x^64 + u0.
|
public override bool Equals(object obj)
|
||||||
// It is assumed that u1 has zero MSB.
|
{
|
||||||
public GF127(ulong u0, ulong u1) : this(new ulong[] { u0, u1 })
|
if (obj is null)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public GF127() : this(0, 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (obj is null)
|
|
||||||
return false;
|
|
||||||
if (ReferenceEquals(this, obj))
|
|
||||||
return true;
|
|
||||||
if (obj is GF127 b)
|
|
||||||
return Equals(b);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
if (ReferenceEquals(this, obj))
|
||||||
|
return true;
|
||||||
|
if (obj is GF127 b)
|
||||||
|
return Equals(b);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return this[0].GetHashCode() + this[1].GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(GF127 other)
|
||||||
|
{
|
||||||
|
if (other is null)
|
||||||
|
return false;
|
||||||
|
if (ReferenceEquals(this, other))
|
||||||
|
return true;
|
||||||
|
return this[0] == other[0] && this[1] == other[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the index of MSB
|
||||||
|
private int IndexOfMSB()
|
||||||
|
{
|
||||||
|
int i = Helper.GetLeadingZeros(this[1]);
|
||||||
|
if (i == 64)
|
||||||
|
i += Helper.GetLeadingZeros(this[0]);
|
||||||
|
return 127 - i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set index n to 1
|
||||||
|
public static GF127 SetN(int n)
|
||||||
|
{
|
||||||
|
if (n < 64)
|
||||||
|
return new GF127((ulong)1 << n, 0);
|
||||||
|
return new GF127(0, (ulong)1 << (n - 64));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add
|
||||||
|
public static GF127 operator +(GF127 a, GF127 b)
|
||||||
|
{
|
||||||
|
return new GF127(a[0] ^ b[0], a[1] ^ b[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bitwise-and
|
||||||
|
public static GF127 operator &(GF127 a, GF127 b)
|
||||||
|
{
|
||||||
|
return new GF127(a[0] & b[0], a[1] & b[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiply
|
||||||
|
public static GF127 operator *(GF127 a, GF127 b) // 2^63 * 2, 10
|
||||||
|
{
|
||||||
|
GF127 r = new();
|
||||||
|
GF127 c = a;
|
||||||
|
|
||||||
|
if (b[1] == 0)
|
||||||
{
|
{
|
||||||
return this[0].GetHashCode() + this[1].GetHashCode();
|
for (int i = 0; i < b[0].GetNonZeroLength(); i++)
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(GF127 other)
|
|
||||||
{
|
|
||||||
if (other is null)
|
|
||||||
return false;
|
|
||||||
if (ReferenceEquals(this, other))
|
|
||||||
return true;
|
|
||||||
return this[0] == other[0] && this[1] == other[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the index of MSB
|
|
||||||
private int IndexOfMSB()
|
|
||||||
{
|
|
||||||
int i = Helper.GetLeadingZeros(this[1]);
|
|
||||||
if (i == 64)
|
|
||||||
i += Helper.GetLeadingZeros(this[0]);
|
|
||||||
return 127 - i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set index n to 1
|
|
||||||
public static GF127 SetN(int n)
|
|
||||||
{
|
|
||||||
if (n < 64)
|
|
||||||
return new GF127((ulong)1 << n, 0);
|
|
||||||
return new GF127(0, (ulong)1 << (n - 64));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add
|
|
||||||
public static GF127 operator +(GF127 a, GF127 b)
|
|
||||||
{
|
|
||||||
return new GF127(a[0] ^ b[0], a[1] ^ b[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bitwise-and
|
|
||||||
public static GF127 operator &(GF127 a, GF127 b)
|
|
||||||
{
|
|
||||||
return new GF127(a[0] & b[0], a[1] & b[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multiply
|
|
||||||
public static GF127 operator *(GF127 a, GF127 b) // 2^63 * 2, 10
|
|
||||||
{
|
|
||||||
GF127 r = new();
|
|
||||||
GF127 c = a;
|
|
||||||
|
|
||||||
if (b[1] == 0)
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < b[0].GetNonZeroLength(); i++)
|
if ((b[0] & ((ulong)1 << i)) != 0)
|
||||||
{
|
r += c;
|
||||||
if ((b[0] & ((ulong)1 << i)) != 0)
|
c = Mul10(c); // c = c * 2
|
||||||
r += c;
|
|
||||||
c = Mul10(c); // c = c * 2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 64; i++)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 64; i++)
|
if ((b[0] & ((ulong)1 << i)) != 0)
|
||||||
{
|
r += c;
|
||||||
if ((b[0] & ((ulong)1 << i)) != 0)
|
c = Mul10(c); // c = c * 2
|
||||||
r += c;
|
|
||||||
c = Mul10(c); // c = c * 2
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < b[1].GetNonZeroLength(); i++)
|
|
||||||
{
|
|
||||||
if ((b[1] & ((ulong)1 << i)) != 0)
|
|
||||||
r += c;
|
|
||||||
c = Mul10(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
for (int i = 0; i < b[1].GetNonZeroLength(); i++)
|
||||||
|
{
|
||||||
|
if ((b[1] & ((ulong)1 << i)) != 0)
|
||||||
|
r += c;
|
||||||
|
c = Mul10(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse, returns a^-1
|
return r;
|
||||||
// Extended Euclidean Algorithm
|
}
|
||||||
// https://link.springer.com/content/pdf/10.1007/3-540-44499-8_1.pdf
|
|
||||||
public static GF127 Inv(GF127 a)
|
// Inverse, returns a^-1
|
||||||
|
// Extended Euclidean Algorithm
|
||||||
|
// https://link.springer.com/content/pdf/10.1007/3-540-44499-8_1.pdf
|
||||||
|
public static GF127 Inv(GF127 a)
|
||||||
|
{
|
||||||
|
GF127 v = X127X631,
|
||||||
|
u = a,
|
||||||
|
c = new(1, 0),
|
||||||
|
d = new(0, 0),
|
||||||
|
t,
|
||||||
|
x;
|
||||||
|
|
||||||
|
int du = u.IndexOfMSB();
|
||||||
|
int dv = v.IndexOfMSB();
|
||||||
|
// degree of polynomial is a position of most significant bit
|
||||||
|
while (du != 0)
|
||||||
{
|
{
|
||||||
GF127 v = X127X631,
|
if (du < dv)
|
||||||
u = a,
|
|
||||||
c = new(1, 0),
|
|
||||||
d = new(0, 0),
|
|
||||||
t,
|
|
||||||
x;
|
|
||||||
|
|
||||||
int du = u.IndexOfMSB();
|
|
||||||
int dv = v.IndexOfMSB();
|
|
||||||
// degree of polynomial is a position of most significant bit
|
|
||||||
while (du != 0)
|
|
||||||
{
|
{
|
||||||
if (du < dv)
|
(v, u) = (u, v);
|
||||||
{
|
(dv, du) = (du, dv);
|
||||||
(v, u) = (u, v);
|
(d, c) = (c, d);
|
||||||
(dv, du) = (du, dv);
|
|
||||||
(d, c) = (c, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
x = SetN(du - dv);
|
|
||||||
t = x * v;
|
|
||||||
u += t;
|
|
||||||
// because * performs reduction on t, manually reduce u at first step
|
|
||||||
if (u.IndexOfMSB() == 127)
|
|
||||||
u += X127X631;
|
|
||||||
|
|
||||||
t = x * d;
|
|
||||||
c += t;
|
|
||||||
|
|
||||||
du = u.IndexOfMSB();
|
|
||||||
dv = v.IndexOfMSB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
x = SetN(du - dv);
|
||||||
|
t = x * v;
|
||||||
|
u += t;
|
||||||
|
// because * performs reduction on t, manually reduce u at first step
|
||||||
|
if (u.IndexOfMSB() == 127)
|
||||||
|
u += X127X631;
|
||||||
|
|
||||||
|
t = x * d;
|
||||||
|
c += t;
|
||||||
|
|
||||||
|
du = u.IndexOfMSB();
|
||||||
|
dv = v.IndexOfMSB();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mul10 returns a*x
|
return c;
|
||||||
public static GF127 Mul10(GF127 a)
|
}
|
||||||
{
|
|
||||||
GF127 b = new();
|
|
||||||
var c = (a[0] & MSB64) >> 63;
|
|
||||||
b[0] = a[0] << 1;
|
|
||||||
b[1] = (a[1] << 1) ^ c;
|
|
||||||
if ((b[1] & MSB64) != 0)
|
|
||||||
{
|
|
||||||
b[0] ^= X127X631[0];
|
|
||||||
b[1] ^= X127X631[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return b;
|
// Mul10 returns a*x
|
||||||
}
|
public static GF127 Mul10(GF127 a)
|
||||||
|
{
|
||||||
// Mul11 returns a*(x+1)
|
GF127 b = new();
|
||||||
public static GF127 Mul11(GF127 a)
|
var c = (a[0] & MSB64) >> 63;
|
||||||
|
b[0] = a[0] << 1;
|
||||||
|
b[1] = (a[1] << 1) ^ c;
|
||||||
|
if ((b[1] & MSB64) != 0)
|
||||||
{
|
{
|
||||||
GF127 b = new();
|
|
||||||
var c = (a[0] & MSB64) >> 63;
|
|
||||||
b[0] = a[0] ^ (a[0] << 1);
|
|
||||||
b[1] = a[1] ^ (a[1] << 1) ^ c;
|
|
||||||
if ((b[1] & MSB64) == 0) return b;
|
|
||||||
b[0] ^= X127X631[0];
|
b[0] ^= X127X631[0];
|
||||||
b[1] ^= X127X631[1];
|
b[1] ^= X127X631[1];
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Random returns random element from GF(2^127).
|
return b;
|
||||||
// Is used mostly for testing.
|
}
|
||||||
public static GF127 Random()
|
|
||||||
|
// Mul11 returns a*(x+1)
|
||||||
|
public static GF127 Mul11(GF127 a)
|
||||||
|
{
|
||||||
|
GF127 b = new();
|
||||||
|
var c = (a[0] & MSB64) >> 63;
|
||||||
|
b[0] = a[0] ^ (a[0] << 1);
|
||||||
|
b[1] = a[1] ^ (a[1] << 1) ^ c;
|
||||||
|
if ((b[1] & MSB64) == 0) return b;
|
||||||
|
b[0] ^= X127X631[0];
|
||||||
|
b[1] ^= X127X631[1];
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Random returns random element from GF(2^127).
|
||||||
|
// Is used mostly for testing.
|
||||||
|
public static GF127 Random()
|
||||||
|
{
|
||||||
|
using RandomNumberGenerator rng = RandomNumberGenerator.Create();
|
||||||
|
return new GF127(rng.NextUlong(), rng.NextUlong() >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromByteArray does the deserialization stuff
|
||||||
|
public GF127 FromByteArray(byte[] data)
|
||||||
|
{
|
||||||
|
if (data.Length != ByteSize)
|
||||||
|
throw new ArgumentException(
|
||||||
|
nameof(data) + $" wrong data lenght, {nameof(GF127)} expect={ByteSize}, actual={data.Length}"
|
||||||
|
);
|
||||||
|
var t0 = new byte[8];
|
||||||
|
var t1 = new byte[8];
|
||||||
|
Array.Copy(data, 0, t1, 0, 8);
|
||||||
|
Array.Copy(data, 8, t0, 0, 8);
|
||||||
|
if (BitConverter.IsLittleEndian)
|
||||||
{
|
{
|
||||||
using RandomNumberGenerator rng = RandomNumberGenerator.Create();
|
Array.Reverse(t0);
|
||||||
return new GF127(rng.NextUlong(), rng.NextUlong() >> 1);
|
Array.Reverse(t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromByteArray does the deserialization stuff
|
_data[0] = BitConverter.ToUInt64(t0, 0);
|
||||||
public GF127 FromByteArray(byte[] data)
|
_data[1] = BitConverter.ToUInt64(t1, 0);
|
||||||
|
if ((_data[1] & MSB64) != 0)
|
||||||
|
throw new ArgumentException(nameof(data) + " invalid data");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToArray() represents element of GF(2^127) as byte array of length 16.
|
||||||
|
public byte[] ToByteArray()
|
||||||
|
{
|
||||||
|
var buff = new byte[16];
|
||||||
|
var b0 = BitConverter.GetBytes(_data[0]);
|
||||||
|
var b1 = BitConverter.GetBytes(_data[1]);
|
||||||
|
if (BitConverter.IsLittleEndian)
|
||||||
{
|
{
|
||||||
if (data.Length != ByteSize)
|
Array.Reverse(b0);
|
||||||
throw new ArgumentException(
|
Array.Reverse(b1);
|
||||||
nameof(data) + $" wrong data lenght, {nameof(GF127)} expect={ByteSize}, actual={data.Length}"
|
|
||||||
);
|
|
||||||
var t0 = new byte[8];
|
|
||||||
var t1 = new byte[8];
|
|
||||||
Array.Copy(data, 0, t1, 0, 8);
|
|
||||||
Array.Copy(data, 8, t0, 0, 8);
|
|
||||||
if (BitConverter.IsLittleEndian)
|
|
||||||
{
|
|
||||||
Array.Reverse(t0);
|
|
||||||
Array.Reverse(t1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_data[0] = BitConverter.ToUInt64(t0);
|
|
||||||
_data[1] = BitConverter.ToUInt64(t1);
|
|
||||||
if ((_data[1] & MSB64) != 0)
|
|
||||||
throw new ArgumentException(nameof(data) + " invalid data");
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToArray() represents element of GF(2^127) as byte array of length 16.
|
Array.Copy(b1, 0, buff, 0, 8);
|
||||||
public byte[] ToByteArray()
|
Array.Copy(b0, 0, buff, 8, 8);
|
||||||
{
|
return buff;
|
||||||
var buff = new byte[16];
|
}
|
||||||
var b0 = BitConverter.GetBytes(_data[0]);
|
|
||||||
var b1 = BitConverter.GetBytes(_data[1]);
|
|
||||||
if (BitConverter.IsLittleEndian)
|
|
||||||
{
|
|
||||||
Array.Reverse(b0);
|
|
||||||
Array.Reverse(b1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Array.Copy(b1, 0, buff, 0, 8);
|
// ToString() returns hex-encoded representation, starting with MSB.
|
||||||
Array.Copy(b0, 0, buff, 8, 8);
|
public override string ToString()
|
||||||
return buff;
|
{
|
||||||
}
|
return BitConverter.ToString(ToByteArray()).Replace("-", "");
|
||||||
|
|
||||||
// ToString() returns hex-encoded representation, starting with MSB.
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Convert.ToHexString(ToByteArray());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,30 +1,30 @@
|
||||||
using System.Security.Cryptography;
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace FrostFS.SDK.Cryptography.Tz
|
namespace FrostFS.SDK.Cryptography.Tz;
|
||||||
|
|
||||||
|
public static class Helper
|
||||||
{
|
{
|
||||||
public static class Helper
|
public static ulong NextUlong(this RandomNumberGenerator rng)
|
||||||
{
|
{
|
||||||
public static ulong NextUlong(this RandomNumberGenerator rng)
|
var buff = new byte[8];
|
||||||
{
|
rng.GetBytes(buff);
|
||||||
var buff = new byte[8];
|
return BitConverter.ToUInt64(buff, 0);
|
||||||
rng.GetBytes(buff);
|
}
|
||||||
return BitConverter.ToUInt64(buff, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetLeadingZeros(ulong value)
|
public static int GetLeadingZeros(ulong value)
|
||||||
|
{
|
||||||
|
var i = 64;
|
||||||
|
while (value != 0)
|
||||||
{
|
{
|
||||||
var i = 64;
|
value >>= 1;
|
||||||
while (value != 0)
|
i--;
|
||||||
{
|
|
||||||
value >>= 1;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
public static int GetNonZeroLength(this ulong value)
|
public static int GetNonZeroLength(this ulong value)
|
||||||
{
|
{
|
||||||
return 64 - GetLeadingZeros(value);
|
return 64 - GetLeadingZeros(value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,177 +1,179 @@
|
||||||
namespace FrostFS.SDK.Cryptography.Tz
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace FrostFS.SDK.Cryptography.Tz;
|
||||||
|
|
||||||
|
public class SL2 : IEquatable<SL2>
|
||||||
{
|
{
|
||||||
public class SL2 : IEquatable<SL2>
|
// 2x2 matrix
|
||||||
|
private readonly GF127[][] data;
|
||||||
|
|
||||||
|
public static readonly SL2 ID = new(
|
||||||
|
new GF127(1, 0), new GF127(0, 0), new GF127(0, 0), new GF127(1, 0));
|
||||||
|
|
||||||
|
public static readonly SL2 A = new(
|
||||||
|
new GF127(2, 0), new GF127(1, 0), new GF127(1, 0), new GF127(0, 0));
|
||||||
|
|
||||||
|
public static readonly SL2 B = new(
|
||||||
|
new GF127(2, 0), new GF127(3, 0), new GF127(1, 0), new GF127(1, 0));
|
||||||
|
|
||||||
|
// Indexer
|
||||||
|
public GF127[] this[int i]
|
||||||
{
|
{
|
||||||
// 2x2 matrix
|
get { return data[i]; }
|
||||||
private readonly GF127[][] data;
|
set { data[i] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
public static readonly SL2 ID = new(new GF127(1, 0), new GF127(0, 0),
|
public SL2(GF127[][] value)
|
||||||
new GF127(0, 0), new GF127(1, 0));
|
{
|
||||||
public static readonly SL2 A = new(new GF127(2, 0), new GF127(1, 0),
|
if (value is null || value.Length != 2 || !value.All(p => p.Length == 2))
|
||||||
new GF127(1, 0), new GF127(0, 0));
|
throw new ArgumentException(nameof(value) + $" invalid {nameof(GF127)} matrics");
|
||||||
public static readonly SL2 B = new(new GF127(2, 0), new GF127(3, 0),
|
data = value;
|
||||||
new GF127(1, 0), new GF127(1, 0));
|
}
|
||||||
|
|
||||||
// Indexer
|
public SL2(GF127 g00, GF127 g01, GF127 g10, GF127 g11)
|
||||||
public GF127[] this[int i]
|
: this([[g00, g01], [g10, g11]])
|
||||||
{
|
{
|
||||||
get { return data[i]; }
|
}
|
||||||
set { data[i] = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public SL2(GF127[][] value)
|
public SL2() : this(GF127.One, GF127.Zero, GF127.Zero, GF127.One)
|
||||||
{
|
{
|
||||||
if (value is null || value.Length != 2 || !value.All(p => p.Length == 2))
|
}
|
||||||
throw new ArgumentException(nameof(value) + $" invalid {nameof(GF127)} matrics");
|
|
||||||
data = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SL2(GF127 g00, GF127 g01, GF127 g10, GF127 g11)
|
public override bool Equals(object obj)
|
||||||
: this(new GF127[][] { new[] { g00, g01 }, new[] { g10, g11 } })
|
{
|
||||||
{
|
if (obj is null)
|
||||||
}
|
|
||||||
|
|
||||||
public SL2() : this(GF127.One, GF127.Zero, GF127.Zero, GF127.One)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (obj is null)
|
|
||||||
return false;
|
|
||||||
if (ReferenceEquals(this, obj))
|
|
||||||
return true;
|
|
||||||
if (obj is SL2 b)
|
|
||||||
return Equals(b);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
if (ReferenceEquals(this, obj))
|
||||||
|
return true;
|
||||||
|
if (obj is SL2 b)
|
||||||
|
return Equals(b);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return this[0][0].GetHashCode() +
|
return this[0][0].GetHashCode() +
|
||||||
this[0][1].GetHashCode() +
|
this[0][1].GetHashCode() +
|
||||||
this[1][0].GetHashCode() +
|
this[1][0].GetHashCode() +
|
||||||
this[1][1].GetHashCode();
|
this[1][1].GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(SL2 other)
|
public bool Equals(SL2 other)
|
||||||
{
|
{
|
||||||
if (other is null)
|
if (other is null)
|
||||||
return false;
|
return false;
|
||||||
if (ReferenceEquals(this, other))
|
if (ReferenceEquals(this, other))
|
||||||
return true;
|
return true;
|
||||||
return this[0][0].Equals(other[0][0]) &&
|
return this[0][0].Equals(other[0][0]) &&
|
||||||
this[0][1].Equals(other[0][1]) &&
|
this[0][1].Equals(other[0][1]) &&
|
||||||
this[1][0].Equals(other[1][0]) &&
|
this[1][0].Equals(other[1][0]) &&
|
||||||
this[1][1].Equals(other[1][1]);
|
this[1][1].Equals(other[1][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2X2 matrix multiplication
|
||||||
|
public static SL2 operator *(SL2 a, SL2 b)
|
||||||
|
{
|
||||||
|
return new SL2(
|
||||||
|
a[0][0] * b[0][0] + a[0][1] * b[1][0],
|
||||||
|
a[0][0] * b[0][1] + a[0][1] * b[1][1],
|
||||||
|
a[1][0] * b[0][0] + a[1][1] * b[1][0],
|
||||||
|
a[1][0] * b[0][1] + a[1][1] * b[1][1]);
|
||||||
|
}
|
||||||
|
|
||||||
// 2X2 matrix multiplication
|
// Multiplication using strassen algorithm
|
||||||
public static SL2 operator *(SL2 a, SL2 b)
|
public static SL2 MulStrassen(SL2 a, SL2 b)
|
||||||
{
|
{
|
||||||
return new SL2(a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1],
|
GF127[] t =
|
||||||
a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]);
|
[
|
||||||
}
|
(a[0][0] + a[1][1]) * (b[0][0] + b[1][1]), // t[0] == (a11 + a22) * (b11 + b22)
|
||||||
|
(a[1][0] + a[1][1]) * b[0][0], // t[1] == (a21 + a22) * b11
|
||||||
|
(b[0][1] + b[1][1]) * a[0][0], // t[2] == (b12 + b22) * a11
|
||||||
|
(b[1][0] + b[0][0]) * a[1][1], // t[3] == (b21 + b11) * a22
|
||||||
|
(a[0][0] + a[0][1]) * b[1][1], // t[4] == (a11 + a12) * b22
|
||||||
|
(a[1][0] + a[0][0]) * (b[0][0] + b[0][1]), // t[5] == (a21 + a11) * (b11 + b12)
|
||||||
|
(a[0][1] + a[1][1]) * (b[1][0] + b[1][1]), // t[6] == (a12 + a22) * (b21 + b22)
|
||||||
|
];
|
||||||
|
|
||||||
// Multiplication using strassen algorithm
|
SL2 r = new();
|
||||||
public static SL2 MulStrassen(SL2 a, SL2 b)
|
r[0][1] = t[2] + t[4]; // r12 == a11*b12 + a11*b22 + a11*b22 + a12*b22 == a11*b12 + a12*b22
|
||||||
{
|
r[1][0] = t[1] + t[3]; // r21 == a21*b11 + a22*b11 + a22*b21 + a22*b11 == a21*b11 + a22*b21
|
||||||
GF127[] t = new GF127[7];
|
// r11 == (a11*b11 + a22*b11` + a11*b22` + a22*b22`) + (a22*b21` + a22*b11`) + (a11*b22` + a12*b22`) +
|
||||||
t[0] = (a[0][0] + a[1][1]) * (b[0][0] + b[1][1]); // t[0] == (a11 + a22) * (b11 + b22)
|
// (a12*b21 + a22*b21` + a12*b22` + a22*b22`) == a11*b11 + a12*b21
|
||||||
|
r[0][0] = t[0] + t[3] + t[4] + t[6];
|
||||||
|
// r22 == (a11*b11` + a22*b11` + a11*b22` + a22*b22) + (a21*b11` + a22*b11`) + (a11*b12` + a11*b22`) +
|
||||||
|
// (a21*b11` + a11*b11` + a21*b12 + a11*b12`) == a21*b12 + a22*b22
|
||||||
|
r[1][1] = t[0] + t[1] + t[2] + t[5];
|
||||||
|
|
||||||
t[1] = (a[1][0] + a[1][1]) * b[0][0]; // t[1] == (a21 + a22) * b11
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
t[2] = (b[0][1] + b[1][1]) * a[0][0]; // t[2] == (b12 + b22) * a11
|
// Inv() returns inverse of a in SL2(GF(2^127))
|
||||||
|
public static SL2 Inv(SL2 a)
|
||||||
|
{
|
||||||
|
GF127[] t = new GF127[2];
|
||||||
|
t[0] = a[0][0] * a[1][1] + a[0][1] * a[1][0];
|
||||||
|
t[1] = GF127.Inv(t[0]);
|
||||||
|
|
||||||
t[3] = (b[1][0] + b[0][0]) * a[1][1]; // t[3] == (b21 + b11) * a22
|
SL2 r = new();
|
||||||
|
r[1][1] = t[1] * a[0][0];
|
||||||
|
r[0][1] = t[1] * a[0][1];
|
||||||
|
r[1][0] = t[1] * a[1][0];
|
||||||
|
r[0][0] = t[1] * a[1][1];
|
||||||
|
|
||||||
t[4] = (a[0][0] + a[0][1]) * b[1][1]; // t[4] == (a11 + a12) * b22
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
t[5] = (a[1][0] + a[0][0]) * (b[0][0] + b[0][1]); // t[5] == (a21 + a11) * (b11 + b12)
|
// MulA() returns this*A, A = {{x, 1}, {1, 0}}
|
||||||
|
public SL2 MulA()
|
||||||
|
{
|
||||||
|
var r = new SL2();
|
||||||
|
r[0][0] = GF127.Mul10(this[0][0]) + this[0][1]; // r11 == t11*x + t12
|
||||||
|
r[0][1] = this[0][0]; // r12 == t11
|
||||||
|
|
||||||
t[6] = (a[0][1] + a[1][1]) * (b[1][0] + b[1][1]); // t[6] == (a12 + a22) * (b21 + b22)
|
r[1][0] = GF127.Mul10(this[1][0]) + this[1][1]; // r21 == t21*x + t22
|
||||||
|
r[1][1] = this[1][0]; // r22 == t21
|
||||||
|
|
||||||
SL2 r = new();
|
return r;
|
||||||
r[0][1] = t[2] + t[4]; // r12 == a11*b12 + a11*b22 + a11*b22 + a12*b22 == a11*b12 + a12*b22
|
}
|
||||||
r[1][0] = t[1] + t[3]; // r21 == a21*b11 + a22*b11 + a22*b21 + a22*b11 == a21*b11 + a22*b21
|
|
||||||
// r11 == (a11*b11 + a22*b11` + a11*b22` + a22*b22`) + (a22*b21` + a22*b11`) + (a11*b22` + a12*b22`) +
|
|
||||||
// (a12*b21 + a22*b21` + a12*b22` + a22*b22`) == a11*b11 + a12*b21
|
|
||||||
r[0][0] = t[0] + t[3] + t[4] + t[6];
|
|
||||||
// r22 == (a11*b11` + a22*b11` + a11*b22` + a22*b22) + (a21*b11` + a22*b11`) + (a11*b12` + a11*b22`) +
|
|
||||||
// (a21*b11` + a11*b11` + a21*b12 + a11*b12`) == a21*b12 + a22*b22
|
|
||||||
r[1][1] = t[0] + t[1] + t[2] + t[5];
|
|
||||||
|
|
||||||
return r;
|
// MulB() returns this*B, B = {{x, x+1}, {1, 1}}
|
||||||
}
|
public SL2 MulB()
|
||||||
|
{
|
||||||
|
var r = new SL2();
|
||||||
|
r[0][0] = GF127.Mul10(this[0][0]) + this[0][1]; // r11 == t11*x + t12
|
||||||
|
r[0][1] = GF127.Mul10(this[0][0]) + this[0][0] + this[0][1]; // r12 == t11*x + t11 + t12
|
||||||
|
|
||||||
// Inv() returns inverse of a in SL2(GF(2^127))
|
r[1][0] = GF127.Mul10(this[1][0]) + this[1][1]; // r21 == t21*x + t22
|
||||||
public static SL2 Inv(SL2 a)
|
r[1][1] = GF127.Mul10(this[1][0]) + this[1][0] + this[1][1]; // r22 == t21*x + t21 + t22
|
||||||
{
|
|
||||||
GF127[] t = new GF127[2];
|
|
||||||
t[0] = a[0][0] * a[1][1] + a[0][1] * a[1][0]; //
|
|
||||||
t[1] = GF127.Inv(t[0]);
|
|
||||||
|
|
||||||
SL2 r = new();
|
return r;
|
||||||
r[1][1] = t[1] * a[0][0];
|
}
|
||||||
r[0][1] = t[1] * a[0][1];
|
|
||||||
r[1][0] = t[1] * a[1][0];
|
|
||||||
r[0][0] = t[1] * a[1][1];
|
|
||||||
|
|
||||||
return r;
|
public SL2 FromByteArray(byte[] data)
|
||||||
}
|
{
|
||||||
|
if (data.Length != 64)
|
||||||
|
throw new ArgumentException(nameof(SL2) + $" invalid data, exect={64}, ecatual={data.Length}");
|
||||||
|
this[0][0] = new GF127().FromByteArray(data[0..16]);
|
||||||
|
this[0][1] = new GF127().FromByteArray(data[16..32]);
|
||||||
|
this[1][0] = new GF127().FromByteArray(data[32..48]);
|
||||||
|
this[1][1] = new GF127().FromByteArray(data[48..64]);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// MulA() returns this*A, A = {{x, 1}, {1, 0}}
|
public byte[] ToByteArray()
|
||||||
public SL2 MulA()
|
{
|
||||||
{
|
var buff = new byte[64];
|
||||||
var r = new SL2();
|
Array.Copy(this[0][0].ToByteArray(), 0, buff, 0, 16);
|
||||||
r[0][0] = GF127.Mul10(this[0][0]) + this[0][1]; // r11 == t11*x + t12
|
Array.Copy(this[0][1].ToByteArray(), 0, buff, 16, 16);
|
||||||
r[0][1] = this[0][0]; // r12 == t11
|
Array.Copy(this[1][0].ToByteArray(), 0, buff, 32, 16);
|
||||||
|
Array.Copy(this[1][1].ToByteArray(), 0, buff, 48, 16);
|
||||||
|
return buff;
|
||||||
|
}
|
||||||
|
|
||||||
r[1][0] = GF127.Mul10(this[1][0]) + this[1][1]; // r21 == t21*x + t22
|
public override string ToString()
|
||||||
r[1][1] = this[1][0]; // r22 == t21
|
{
|
||||||
|
return this[0][0].ToString() + this[0][1].ToString() +
|
||||||
return r;
|
this[1][0].ToString() + this[1][1].ToString();
|
||||||
}
|
|
||||||
|
|
||||||
// MulB() returns this*B, B = {{x, x+1}, {1, 1}}
|
|
||||||
public SL2 MulB()
|
|
||||||
{
|
|
||||||
var r = new SL2();
|
|
||||||
r[0][0] = GF127.Mul10(this[0][0]) + this[0][1]; // r11 == t11*x + t12
|
|
||||||
r[0][1] = GF127.Mul10(this[0][0]) + this[0][0] + this[0][1]; // r12 == t11*x + t11 + t12
|
|
||||||
|
|
||||||
r[1][0] = GF127.Mul10(this[1][0]) + this[1][1]; // r21 == t21*x + t22
|
|
||||||
r[1][1] = GF127.Mul10(this[1][0]) + this[1][0] + this[1][1]; // r22 == t21*x + t21 + t22
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SL2 FromByteArray(byte[] data)
|
|
||||||
{
|
|
||||||
if (data.Length != 64)
|
|
||||||
throw new ArgumentException(nameof(SL2) + $" invalid data, exect={64}, ecatual={data.Length}");
|
|
||||||
this[0][0] = new GF127().FromByteArray(data[0..16]);
|
|
||||||
this[0][1] = new GF127().FromByteArray(data[16..32]);
|
|
||||||
this[1][0] = new GF127().FromByteArray(data[32..48]);
|
|
||||||
this[1][1] = new GF127().FromByteArray(data[48..64]);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] ToByteArray()
|
|
||||||
{
|
|
||||||
var buff = new byte[64];
|
|
||||||
Array.Copy(this[0][0].ToByteArray(), 0, buff, 0, 16);
|
|
||||||
Array.Copy(this[0][1].ToByteArray(), 0, buff, 16, 16);
|
|
||||||
Array.Copy(this[1][0].ToByteArray(), 0, buff, 32, 16);
|
|
||||||
Array.Copy(this[1][1].ToByteArray(), 0, buff, 48, 16);
|
|
||||||
return buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return this[0][0].ToString() + this[0][1].ToString() +
|
|
||||||
this[1][0].ToString() + this[1][1].ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,139 +1,140 @@
|
||||||
using System.Security;
|
//using System;
|
||||||
using System.Security.Cryptography;
|
//using System.Collections.Generic;
|
||||||
|
//using System.Security;
|
||||||
|
//using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace FrostFS.SDK.Cryptography.Tz
|
//namespace FrostFS.SDK.Cryptography.Tz;
|
||||||
{
|
|
||||||
public class TzHash : HashAlgorithm
|
|
||||||
{
|
|
||||||
private const int TzHashLength = 64;
|
|
||||||
private GF127[] x;
|
|
||||||
public override int HashSize => TzHashLength;
|
|
||||||
|
|
||||||
public TzHash()
|
//public class TzHash : HashAlgorithm
|
||||||
{
|
//{
|
||||||
Initialize();
|
// private const int TzHashLength = 64;
|
||||||
}
|
// private GF127[] x;
|
||||||
|
// public override int HashSize => TzHashLength;
|
||||||
|
|
||||||
public override void Initialize()
|
// public TzHash()
|
||||||
{
|
// {
|
||||||
x = new GF127[4];
|
// Initialize();
|
||||||
Reset();
|
// }
|
||||||
HashValue = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
x[0] = new GF127(1, 0);
|
|
||||||
x[1] = new GF127(0, 0);
|
|
||||||
x[2] = new GF127(0, 0);
|
|
||||||
x[3] = new GF127(1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] ToByteArray()
|
// public override void Initialize()
|
||||||
{
|
// {
|
||||||
var buff = new byte[HashSize];
|
// x = new GF127[4];
|
||||||
for (int i = 0; i < 4; i++)
|
// Reset();
|
||||||
{
|
// HashValue = null;
|
||||||
Array.Copy(x[i].ToByteArray(), 0, buff, i * 16, 16);
|
// }
|
||||||
}
|
|
||||||
return buff;
|
// public void Reset()
|
||||||
}
|
// {
|
||||||
|
// x[0] = new GF127(1, 0);
|
||||||
|
// x[1] = new GF127(0, 0);
|
||||||
|
// x[2] = new GF127(0, 0);
|
||||||
|
// x[3] = new GF127(1, 0);
|
||||||
|
// }
|
||||||
|
|
||||||
[SecurityCritical]
|
// public byte[] ToByteArray()
|
||||||
protected override void HashCore(byte[] array, int ibStart, int cbSize)
|
// {
|
||||||
{
|
// var buff = new byte[HashSize];
|
||||||
_ = HashData(array[ibStart..(ibStart + cbSize)]);
|
// for (int i = 0; i < 4; i++)
|
||||||
}
|
// {
|
||||||
|
// Array.Copy(x[i].ToByteArray(), 0, buff, i * 16, 16);
|
||||||
|
// }
|
||||||
|
// return buff;
|
||||||
|
// }
|
||||||
|
|
||||||
[SecurityCritical]
|
// [SecurityCritical]
|
||||||
protected override byte[] HashFinal()
|
// protected override void HashCore(byte[] array, int ibStart, int cbSize)
|
||||||
{
|
// {
|
||||||
return HashValue = ToByteArray();
|
// _ = HashData(array[ibStart..(ibStart + cbSize)]);
|
||||||
}
|
// }
|
||||||
|
|
||||||
[SecurityCritical]
|
// [SecurityCritical]
|
||||||
private int HashData(byte[] data)
|
// protected override byte[] HashFinal()
|
||||||
{
|
// {
|
||||||
var n = data.Length;
|
// return HashValue = ToByteArray();
|
||||||
for (int i = 0; i < n; i++)
|
// }
|
||||||
{
|
|
||||||
for (int j = 7; j >= 0; j--)
|
|
||||||
{
|
|
||||||
MulBitRight(ref x[0], ref x[1], ref x[2], ref x[3], (data[i] & (1 << j)) != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MulBitRight() multiply A (if the bit is 0) or B (if the bit is 1) on the right side
|
// [SecurityCritical]
|
||||||
private void MulBitRight(ref GF127 c00, ref GF127 c01, ref GF127 c10, ref GF127 c11, bool bit)
|
// private int HashData(byte[] data)
|
||||||
{
|
// {
|
||||||
// plan 1
|
// var n = data.Length;
|
||||||
GF127 t;
|
// for (int i = 0; i < n; i++)
|
||||||
if (bit)
|
// {
|
||||||
{ // MulB
|
// for (int j = 7; j >= 0; j--)
|
||||||
t = c00;
|
// {
|
||||||
c00 = GF127.Mul10(c00) + c01; // c00 = c00 * x + c01
|
// MulBitRight(ref x[0], ref x[1], ref x[2], ref x[3], (data[i] & (1 << j)) != 0);
|
||||||
c01 = GF127.Mul11(t) + c01; // c01 = c00 * (x+1) + c01
|
// }
|
||||||
|
// }
|
||||||
|
// return n;
|
||||||
|
// }
|
||||||
|
|
||||||
t = c10;
|
// // MulBitRight() multiply A (if the bit is 0) or B (if the bit is 1) on the right side
|
||||||
c10 = GF127.Mul10(c10) + c11; // c10 = c10 * x + c11
|
// private void MulBitRight(ref GF127 c00, ref GF127 c01, ref GF127 c10, ref GF127 c11, bool bit)
|
||||||
c11 = GF127.Mul11(t) + c11; // c11 = c10 * (x+1) + c11
|
// {
|
||||||
}
|
// // plan 1
|
||||||
else
|
// GF127 t;
|
||||||
{ // MulA
|
// if (bit)
|
||||||
t = c00;
|
// { // MulB
|
||||||
c00 = GF127.Mul10(c00) + c01; // c00 = c00 * x + c01
|
// t = c00;
|
||||||
c01 = t; // c01 = c00
|
// c00 = GF127.Mul10(c00) + c01; // c00 = c00 * x + c01
|
||||||
|
// c01 = GF127.Mul11(t) + c01; // c01 = c00 * (x+1) + c01
|
||||||
|
|
||||||
t = c10;
|
// t = c10;
|
||||||
c10 = GF127.Mul10(c10) + c11; // c10 = c10 * x + c11
|
// c10 = GF127.Mul10(c10) + c11; // c10 = c10 * x + c11
|
||||||
c11 = t; // c11 = c10;
|
// c11 = GF127.Mul11(t) + c11; // c11 = c10 * (x+1) + c11
|
||||||
}
|
// }
|
||||||
|
// else
|
||||||
|
// { // MulA
|
||||||
|
// t = c00;
|
||||||
|
// c00 = GF127.Mul10(c00) + c01; // c00 = c00 * x + c01
|
||||||
|
// c01 = t; // c01 = c00
|
||||||
|
|
||||||
//// plan 2
|
// t = c10;
|
||||||
//var r = new SL2(c00, c01, c10, c11);
|
// c10 = GF127.Mul10(c10) + c11; // c10 = c10 * x + c11
|
||||||
//if (bit)
|
// c11 = t; // c11 = c10;
|
||||||
// r.MulB();
|
// }
|
||||||
//else
|
|
||||||
// r.MulA();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Concat() performs combining of hashes based on homomorphic characteristic.
|
// //// plan 2
|
||||||
public static byte[] Concat(List<byte[]> hs)
|
// //var r = new SL2(c00, c01, c10, c11);
|
||||||
{
|
// //if (bit)
|
||||||
var r = SL2.ID;
|
// // r.MulB();
|
||||||
foreach (var h in hs)
|
// //else
|
||||||
{
|
// // r.MulA();
|
||||||
r *= new SL2().FromByteArray(h);
|
// }
|
||||||
}
|
|
||||||
return r.ToByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate() checks if hashes in hs combined are equal to h.
|
// // Concat() performs combining of hashes based on homomorphic characteristic.
|
||||||
public static bool Validate(byte[] h, List<byte[]> hs)
|
// public static byte[] Concat(List<byte[]> hs)
|
||||||
{
|
// {
|
||||||
var expected = new SL2().FromByteArray(h);
|
// var r = SL2.ID;
|
||||||
var actual = new SL2().FromByteArray(Concat(hs));
|
// foreach (var h in hs)
|
||||||
return expected.Equals(actual);
|
// {
|
||||||
}
|
// r *= new SL2().FromByteArray(h);
|
||||||
|
// }
|
||||||
|
// return r.ToByteArray();
|
||||||
|
// }
|
||||||
|
|
||||||
// SubtractR() returns hash a, such that Concat(a, b) == c
|
// // Validate() checks if hashes in hs combined are equal to h.
|
||||||
public static byte[] SubstractR(byte[] b, byte[] c)
|
// public static bool Validate(byte[] h, List<byte[]> hs)
|
||||||
{
|
// {
|
||||||
var t1 = new SL2().FromByteArray(b);
|
// var expected = new SL2().FromByteArray(h);
|
||||||
var t2 = new SL2().FromByteArray(c);
|
// var actual = new SL2().FromByteArray(Concat(hs));
|
||||||
var r = t2 * SL2.Inv(t1);
|
// return expected.Equals(actual);
|
||||||
return r.ToByteArray();
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
// SubtractL() returns hash b, such that Concat(a, b) == c
|
// // SubtractR() returns hash a, such that Concat(a, b) == c
|
||||||
public static byte[] SubstractL(byte[] a, byte[] c)
|
// public static byte[] SubstractR(byte[] b, byte[] c)
|
||||||
{
|
// {
|
||||||
var t1 = new SL2().FromByteArray(a);
|
// var t1 = new SL2().FromByteArray(b);
|
||||||
var t2 = new SL2().FromByteArray(c);
|
// var t2 = new SL2().FromByteArray(c);
|
||||||
var r = SL2.Inv(t1) * t2;
|
// var r = t2 * SL2.Inv(t1);
|
||||||
return r.ToByteArray();
|
// return r.ToByteArray();
|
||||||
}
|
// }
|
||||||
}
|
|
||||||
}
|
// // SubtractL() returns hash b, such that Concat(a, b) == c
|
||||||
|
// public static byte[] SubstractL(byte[] a, byte[] c)
|
||||||
|
// {
|
||||||
|
// var t1 = new SL2().FromByteArray(a);
|
||||||
|
// var t2 = new SL2().FromByteArray(c);
|
||||||
|
// var r = SL2.Inv(t1) * t2;
|
||||||
|
// return r.ToByteArray();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
|
@ -1,17 +1,24 @@
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace FrostFS.SDK.Cryptography
|
namespace FrostFS.SDK.Cryptography;
|
||||||
|
|
||||||
|
public static class UUIDExtension
|
||||||
{
|
{
|
||||||
public static class UUIDExtension
|
public static Guid ToUuid(this ByteString id)
|
||||||
{
|
{
|
||||||
public static Guid ToUuid(this ByteString id)
|
return Guid.Parse(BitConverter.ToString(id.ToByteArray()).Replace("-", ""));
|
||||||
{
|
}
|
||||||
return Guid.Parse(Convert.ToHexString(id.ToByteArray()));
|
|
||||||
}
|
public static byte[] ToBytes(this Guid id)
|
||||||
|
{
|
||||||
|
var str = id.ToString("N");
|
||||||
|
var len = str.Length;
|
||||||
|
var bytes = new byte[len/2];
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i += 2)
|
||||||
|
bytes[i/2] = Convert.ToByte(str.Substring(i, 2), 16);
|
||||||
|
|
||||||
public static byte[] ToBytes(this Guid id)
|
return bytes;
|
||||||
{
|
|
||||||
return Convert.FromHexString(id.ToString("N"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
using FrostFS.SDK.ModelsV2.Enums;
|
using FrostFS.SDK.ModelsV2.Enums;
|
||||||
using FrostFS.SDK.ModelsV2.Netmap;
|
using FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using FrostFS.SDK.Cryptography;
|
using System;
|
||||||
|
|
||||||
|
using FrostFS.SDK.Cryptography;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ModelsV2;
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
|
@ -10,16 +12,15 @@ public class ContainerId
|
||||||
{
|
{
|
||||||
Value = id;
|
Value = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ContainerId FromHash(byte[] hash)
|
public static ContainerId FromHash(byte[] hash)
|
||||||
{
|
{
|
||||||
if (hash.Length != Constants.Sha256HashLength)
|
if (hash.Length != Constants.Sha256HashLength)
|
||||||
{
|
|
||||||
throw new FormatException("ContainerID must be a sha256 hash.");
|
throw new FormatException("ContainerID must be a sha256 hash.");
|
||||||
}
|
|
||||||
return new ContainerId(Base58.Encode(hash));
|
return new ContainerId(Base58.Encode(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ToHash()
|
public byte[] ToHash()
|
||||||
{
|
{
|
||||||
return Base58.Decode(Value);
|
return Base58.Decode(Value);
|
||||||
|
|
|
@ -6,13 +6,13 @@ public enum BasicAcl
|
||||||
{
|
{
|
||||||
[Description("Basic ACL for private container")]
|
[Description("Basic ACL for private container")]
|
||||||
Private = 0x1C8C8CCC,
|
Private = 0x1C8C8CCC,
|
||||||
|
|
||||||
[Description("Basic ACL for public RO container")]
|
[Description("Basic ACL for public RO container")]
|
||||||
PublicRO = 0x1FBF8CFF,
|
PublicRO = 0x1FBF8CFF,
|
||||||
|
|
||||||
[Description("Basic ACL for public RW container")]
|
[Description("Basic ACL for public RW container")]
|
||||||
PublicRW = 0x1FBFBFFF,
|
PublicRW = 0x1FBFBFFF,
|
||||||
|
|
||||||
[Description("Basic ACL for public append container")]
|
[Description("Basic ACL for public append container")]
|
||||||
PublicAppend = 0x1FBF9FFF,
|
PublicAppend = 0x1FBF9FFF,
|
||||||
}
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<LangVersion>12.0</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj" />
|
<ProjectReference Include="..\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -2,8 +2,8 @@ namespace FrostFS.SDK.ModelsV2.Netmap;
|
||||||
|
|
||||||
public class PlacementPolicy
|
public class PlacementPolicy
|
||||||
{
|
{
|
||||||
public Replica[] Replicas { get; init; }
|
public Replica[] Replicas { get; private set; }
|
||||||
public bool Unique { get; init; }
|
public bool Unique { get; private set; }
|
||||||
|
|
||||||
public PlacementPolicy(bool unique, params Replica[] replicas)
|
public PlacementPolicy(bool unique, params Replica[] replicas)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,7 @@ public class Replica
|
||||||
public Replica(int count, string? selector = null)
|
public Replica(int count, string? selector = null)
|
||||||
{
|
{
|
||||||
selector ??= string.Empty;
|
selector ??= string.Empty;
|
||||||
|
|
||||||
Count = count;
|
Count = count;
|
||||||
Selector = selector;
|
Selector = selector;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,17 +32,17 @@ public class ObjectFilter
|
||||||
{
|
{
|
||||||
return new ObjectFilter(matchType, HeaderPrefix + "objectID", objectId.Value);
|
return new ObjectFilter(matchType, HeaderPrefix + "objectID", objectId.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ObjectFilter OwnerFilter(ObjectMatchType matchType, OwnerId ownerId)
|
public static ObjectFilter OwnerFilter(ObjectMatchType matchType, OwnerId ownerId)
|
||||||
{
|
{
|
||||||
return new ObjectFilter(matchType, HeaderPrefix + "ownerID", ownerId.Value);
|
return new ObjectFilter(matchType, HeaderPrefix + "ownerID", ownerId.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ObjectFilter RootFilter()
|
public static ObjectFilter RootFilter()
|
||||||
{
|
{
|
||||||
return new ObjectFilter(ObjectMatchType.Unspecified, HeaderPrefix + "ROOT", "");
|
return new ObjectFilter(ObjectMatchType.Unspecified, HeaderPrefix + "ROOT", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ObjectFilter VersionFilter(ObjectMatchType matchType, Version version)
|
public static ObjectFilter VersionFilter(ObjectMatchType matchType, Version version)
|
||||||
{
|
{
|
||||||
return new ObjectFilter(matchType, HeaderPrefix + "version", version.ToString());
|
return new ObjectFilter(matchType, HeaderPrefix + "version", version.ToString());
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using FrostFS.SDK.Cryptography;
|
using System;
|
||||||
|
|
||||||
|
using FrostFS.SDK.Cryptography;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ModelsV2;
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
|
@ -10,7 +12,7 @@ public class ObjectId
|
||||||
{
|
{
|
||||||
Value = id;
|
Value = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ObjectId FromHash(byte[] hash)
|
public static ObjectId FromHash(byte[] hash)
|
||||||
{
|
{
|
||||||
if (hash.Length != Constants.Sha256HashLength)
|
if (hash.Length != Constants.Sha256HashLength)
|
||||||
|
@ -19,7 +21,7 @@ public class ObjectId
|
||||||
}
|
}
|
||||||
return new ObjectId(Base58.Encode(hash));
|
return new ObjectId(Base58.Encode(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ToHash()
|
public byte[] ToHash()
|
||||||
{
|
{
|
||||||
return Base58.Decode(Value);
|
return Base58.Decode(Value);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
using FrostFS.SDK.Cryptography;
|
using FrostFS.SDK.Cryptography;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ModelsV2;
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
@ -16,7 +17,7 @@ public class OwnerId
|
||||||
{
|
{
|
||||||
return new OwnerId(key.PublicKey().PublicKeyToAddress());
|
return new OwnerId(key.PublicKey().PublicKeyToAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ToHash()
|
public byte[] ToHash()
|
||||||
{
|
{
|
||||||
return Base58.Decode(Value);
|
return Base58.Decode(Value);
|
||||||
|
|
|
@ -17,7 +17,7 @@ public class Status
|
||||||
{
|
{
|
||||||
return Code == StatusCode.Success;
|
return Code == StatusCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"Response status: {Code}. Message: {Message}.";
|
return $"Response status: {Code}. Message: {Message}.";
|
||||||
|
|
|
@ -1,33 +1,32 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<LangVersion>12.0</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.26.1" />
|
<PackageReference Include="Google.Protobuf" Version="3.26.1" />
|
||||||
<PackageReference Include="Grpc.Core" Version="2.46.6" />
|
<PackageReference Include="Grpc.Net.Client" Version="2.62.0" />
|
||||||
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.62.0" />
|
<PackageReference Include="Grpc.Tools" Version="2.64.0">
|
||||||
<PackageReference Include="Grpc.Tools" Version="2.63.0">
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
</PackageReference>
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Protobuf Include="accounting\*.proto" GrpcServices="Client" />
|
|
||||||
<Protobuf Include="acl\*.proto" GrpcServices="Client" />
|
|
||||||
<Protobuf Include="apemanager\*.proto" GrpcServices="Client" />
|
|
||||||
<Protobuf Include="container\*.proto" GrpcServices="Client" />
|
|
||||||
<Protobuf Include="lock\*.proto" GrpcServices="Client" />
|
|
||||||
<Protobuf Include="netmap\*.proto" GrpcServices="Client" />
|
|
||||||
<Protobuf Include="object\*.proto" GrpcServices="Client" />
|
|
||||||
<Protobuf Include="refs\*.proto" GrpcServices="Client" />
|
|
||||||
<Protobuf Include="session\*.proto" GrpcServices="Client" />
|
|
||||||
<Protobuf Include="status\*.proto" GrpcServices="Client" />
|
|
||||||
<Protobuf Include="tombstone\*.proto" GrpcServices="Client" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Protobuf Include="accounting\*.proto" GrpcServices="Client" />
|
||||||
|
<Protobuf Include="acl\*.proto" GrpcServices="Client" />
|
||||||
|
<Protobuf Include="apemanager\*.proto" GrpcServices="Client" />
|
||||||
|
<Protobuf Include="container\*.proto" GrpcServices="Client" />
|
||||||
|
<Protobuf Include="lock\*.proto" GrpcServices="Client" />
|
||||||
|
<Protobuf Include="netmap\*.proto" GrpcServices="Client" />
|
||||||
|
<Protobuf Include="object\*.proto" GrpcServices="Client" />
|
||||||
|
<Protobuf Include="refs\*.proto" GrpcServices="Client" />
|
||||||
|
<Protobuf Include="session\*.proto" GrpcServices="Client" />
|
||||||
|
<Protobuf Include="status\*.proto" GrpcServices="Client" />
|
||||||
|
<Protobuf Include="tombstone\*.proto" GrpcServices="Client" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
|
||||||
namespace FrostFS.Session
|
namespace FrostFS.Session;
|
||||||
|
|
||||||
|
public interface IMetaHeader : IMessage
|
||||||
{
|
{
|
||||||
public interface IMetaHeader : IMessage
|
IMetaHeader GetOrigin();
|
||||||
{
|
|
||||||
IMetaHeader GetOrigin();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
namespace FrostFS.Session
|
namespace FrostFS.Session;
|
||||||
|
|
||||||
|
public interface IRequest : IVerificableMessage
|
||||||
{
|
{
|
||||||
public interface IRequest : IVerificableMessage
|
RequestMetaHeader MetaHeader { get; set; }
|
||||||
{
|
RequestVerificationHeader VerifyHeader { get; set; }
|
||||||
RequestMetaHeader MetaHeader { get; set; }
|
|
||||||
RequestVerificationHeader VerifyHeader { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
namespace FrostFS.Session
|
namespace FrostFS.Session;
|
||||||
|
|
||||||
|
public interface IResponse : IVerificableMessage
|
||||||
{
|
{
|
||||||
public interface IResponse : IVerificableMessage
|
ResponseMetaHeader MetaHeader { get; set; }
|
||||||
{
|
ResponseVerificationHeader VerifyHeader { get; set; }
|
||||||
ResponseMetaHeader MetaHeader { get; set; }
|
|
||||||
ResponseVerificationHeader VerifyHeader { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
|
||||||
namespace FrostFS.Session
|
namespace FrostFS.Session;
|
||||||
|
|
||||||
|
public interface IVerificableMessage : IMessage
|
||||||
{
|
{
|
||||||
public interface IVerificableMessage : IMessage
|
IMetaHeader GetMetaHeader();
|
||||||
{
|
void SetMetaHeader(IMetaHeader metaHeader);
|
||||||
IMetaHeader GetMetaHeader();
|
IVerificationHeader GetVerificationHeader();
|
||||||
void SetMetaHeader(IMetaHeader metaHeader);
|
void SetVerificationHeader(IVerificationHeader verificationHeader);
|
||||||
IVerificationHeader GetVerificationHeader();
|
IMessage GetBody();
|
||||||
void SetVerificationHeader(IVerificationHeader verificationHeader);
|
|
||||||
IMessage GetBody();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
using FrostFS.Refs;
|
using FrostFS.Refs;
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
|
||||||
namespace FrostFS.Session
|
namespace FrostFS.Session;
|
||||||
|
|
||||||
|
public interface IVerificationHeader : IMessage
|
||||||
{
|
{
|
||||||
public interface IVerificationHeader : IMessage
|
Signature BodySignature { get; set; }
|
||||||
{
|
Signature MetaSignature { get; set; }
|
||||||
Signature BodySignature { get; set; }
|
Signature OriginSignature { get; set; }
|
||||||
Signature MetaSignature { get; set; }
|
IVerificationHeader GetOrigin();
|
||||||
Signature OriginSignature { get; set; }
|
void SetOrigin(IVerificationHeader verificationHeader);
|
||||||
IVerificationHeader GetOrigin();
|
|
||||||
void SetOrigin(IVerificationHeader verificationHeader);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,397 +1,397 @@
|
||||||
using FrostFS.Session;
|
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
|
||||||
namespace FrostFS.Container
|
using FrostFS.Session;
|
||||||
|
|
||||||
|
namespace FrostFS.Container;
|
||||||
|
|
||||||
|
public partial class AnnounceUsedSpaceRequest : IRequest
|
||||||
{
|
{
|
||||||
public partial class AnnounceUsedSpaceRequest : IRequest
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return MetaHeader;
|
||||||
{
|
|
||||||
return MetaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
|
||||||
{
|
|
||||||
return VerifyHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
|
||||||
return Body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class AnnounceUsedSpaceResponse : IResponse
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return VerifyHeader;
|
||||||
{
|
|
||||||
return MetaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
|
||||||
{
|
|
||||||
return VerifyHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
|
||||||
return Body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class GetRequest : IRequest
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
{
|
|
||||||
return MetaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
|
||||||
{
|
|
||||||
return VerifyHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
|
||||||
return Body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class GetResponse : IResponse
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
{
|
|
||||||
return MetaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
|
||||||
{
|
|
||||||
return VerifyHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
|
||||||
return Body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class PutRequest : IRequest
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return Body;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
}
|
||||||
}
|
|
||||||
|
public partial class AnnounceUsedSpaceResponse : IResponse
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
{
|
||||||
{
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
return VerifyHeader;
|
{
|
||||||
}
|
return MetaHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
{
|
||||||
}
|
return VerifyHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
{
|
||||||
}
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
return Body;
|
{
|
||||||
}
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class PutResponse : IResponse
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return Body;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
}
|
||||||
}
|
|
||||||
|
public partial class GetRequest : IRequest
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
{
|
||||||
{
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
return VerifyHeader;
|
{
|
||||||
}
|
return MetaHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
{
|
||||||
}
|
return VerifyHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
{
|
||||||
}
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
return Body;
|
{
|
||||||
}
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class DeleteRequest : IRequest
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return Body;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
}
|
||||||
}
|
|
||||||
|
public partial class GetResponse : IResponse
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
{
|
||||||
{
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
return VerifyHeader;
|
{
|
||||||
}
|
return MetaHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
{
|
||||||
}
|
return VerifyHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
{
|
||||||
}
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
return Body;
|
{
|
||||||
}
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class DeleteResponse : IResponse
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return Body;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
}
|
||||||
}
|
|
||||||
|
public partial class PutRequest : IRequest
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
{
|
||||||
{
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
return VerifyHeader;
|
{
|
||||||
}
|
return MetaHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
{
|
||||||
}
|
return VerifyHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
{
|
||||||
}
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
return Body;
|
{
|
||||||
}
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class ListRequest : IRequest
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return Body;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
}
|
||||||
}
|
|
||||||
|
public partial class PutResponse : IResponse
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
{
|
||||||
{
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
return VerifyHeader;
|
{
|
||||||
}
|
return MetaHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
{
|
||||||
}
|
return VerifyHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
{
|
||||||
}
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
return Body;
|
{
|
||||||
}
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class ListResponse : IResponse
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return Body;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
}
|
||||||
}
|
|
||||||
|
public partial class DeleteRequest : IRequest
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
{
|
||||||
{
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
return VerifyHeader;
|
{
|
||||||
}
|
return MetaHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
{
|
||||||
}
|
return VerifyHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
{
|
||||||
}
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
return Body;
|
{
|
||||||
}
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class SetExtendedACLRequest : IRequest
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return Body;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
}
|
||||||
}
|
|
||||||
|
public partial class DeleteResponse : IResponse
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
{
|
||||||
{
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
return VerifyHeader;
|
{
|
||||||
}
|
return MetaHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
{
|
||||||
}
|
return VerifyHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
{
|
||||||
}
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
return Body;
|
{
|
||||||
}
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class SetExtendedACLResponse : IResponse
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return Body;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
}
|
||||||
}
|
|
||||||
|
public partial class ListRequest : IRequest
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
{
|
||||||
{
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
return VerifyHeader;
|
{
|
||||||
}
|
return MetaHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
{
|
||||||
}
|
return VerifyHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
{
|
||||||
}
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
return Body;
|
{
|
||||||
}
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class GetExtendedACLRequest : IRequest
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return Body;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
}
|
||||||
}
|
|
||||||
|
public partial class ListResponse : IResponse
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
{
|
||||||
{
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
return VerifyHeader;
|
{
|
||||||
}
|
return MetaHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
{
|
||||||
}
|
return VerifyHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
{
|
||||||
}
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
return Body;
|
{
|
||||||
}
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class GetExtendedACLResponse : IResponse
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return Body;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
}
|
||||||
}
|
|
||||||
|
public partial class SetExtendedACLRequest : IRequest
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
{
|
||||||
{
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
return VerifyHeader;
|
{
|
||||||
}
|
return MetaHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
{
|
||||||
}
|
return VerifyHeader;
|
||||||
|
}
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
{
|
||||||
}
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
return Body;
|
{
|
||||||
}
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMessage GetBody()
|
||||||
|
{
|
||||||
|
return Body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class SetExtendedACLResponse : IResponse
|
||||||
|
{
|
||||||
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
|
{
|
||||||
|
return MetaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
|
{
|
||||||
|
return VerifyHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
|
{
|
||||||
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
|
{
|
||||||
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMessage GetBody()
|
||||||
|
{
|
||||||
|
return Body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class GetExtendedACLRequest : IRequest
|
||||||
|
{
|
||||||
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
|
{
|
||||||
|
return MetaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
|
{
|
||||||
|
return VerifyHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
|
{
|
||||||
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
|
{
|
||||||
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMessage GetBody()
|
||||||
|
{
|
||||||
|
return Body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class GetExtendedACLResponse : IResponse
|
||||||
|
{
|
||||||
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
|
{
|
||||||
|
return MetaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
|
{
|
||||||
|
return VerifyHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
|
{
|
||||||
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
|
{
|
||||||
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMessage GetBody()
|
||||||
|
{
|
||||||
|
return Body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,117 +1,116 @@
|
||||||
using FrostFS.Session;
|
using FrostFS.Session;
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
|
||||||
namespace FrostFS.Netmap
|
namespace FrostFS.Netmap;
|
||||||
|
|
||||||
|
public partial class LocalNodeInfoRequest : IRequest
|
||||||
{
|
{
|
||||||
public partial class LocalNodeInfoRequest : IRequest
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return MetaHeader;
|
||||||
{
|
|
||||||
return MetaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
|
||||||
{
|
|
||||||
return VerifyHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
|
||||||
return Body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class LocalNodeInfoResponse : IResponse
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return VerifyHeader;
|
||||||
{
|
|
||||||
return MetaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
|
||||||
{
|
|
||||||
return VerifyHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
|
||||||
return Body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class NetworkInfoRequest : IRequest
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
{
|
|
||||||
return MetaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
|
||||||
{
|
|
||||||
return VerifyHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
|
||||||
return Body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class NetworkInfoResponse : IResponse
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
return Body;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
public partial class LocalNodeInfoResponse : IResponse
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
{
|
||||||
}
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
|
{
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
return MetaHeader;
|
||||||
{
|
}
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
|
||||||
}
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
|
{
|
||||||
public IMessage GetBody()
|
return VerifyHeader;
|
||||||
{
|
}
|
||||||
return Body;
|
|
||||||
}
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
|
{
|
||||||
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
|
{
|
||||||
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMessage GetBody()
|
||||||
|
{
|
||||||
|
return Body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class NetworkInfoRequest : IRequest
|
||||||
|
{
|
||||||
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
|
{
|
||||||
|
return MetaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
|
{
|
||||||
|
return VerifyHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
|
{
|
||||||
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
|
{
|
||||||
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMessage GetBody()
|
||||||
|
{
|
||||||
|
return Body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class NetworkInfoResponse : IResponse
|
||||||
|
{
|
||||||
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
|
{
|
||||||
|
return MetaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
|
{
|
||||||
|
return VerifyHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
|
{
|
||||||
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
|
{
|
||||||
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMessage GetBody()
|
||||||
|
{
|
||||||
|
return Body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +1,59 @@
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
|
||||||
namespace FrostFS.Session
|
namespace FrostFS.Session;
|
||||||
|
|
||||||
|
public partial class CreateResponse : IResponse
|
||||||
{
|
{
|
||||||
public partial class CreateResponse : IResponse
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return MetaHeader;
|
||||||
{
|
|
||||||
return MetaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
|
||||||
{
|
|
||||||
return VerifyHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
|
||||||
{
|
|
||||||
MetaHeader = (ResponseMetaHeader)metaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
|
||||||
{
|
|
||||||
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
|
||||||
return Body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class CreateRequest : IRequest
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
{
|
{
|
||||||
IMetaHeader IVerificableMessage.GetMetaHeader()
|
return VerifyHeader;
|
||||||
{
|
}
|
||||||
return MetaHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
{
|
{
|
||||||
return VerifyHeader;
|
MetaHeader = (ResponseMetaHeader)metaHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
MetaHeader = (RequestMetaHeader)metaHeader;
|
VerifyHeader = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
public IMessage GetBody()
|
||||||
{
|
{
|
||||||
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
return Body;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public IMessage GetBody()
|
|
||||||
{
|
public partial class CreateRequest : IRequest
|
||||||
return Body;
|
{
|
||||||
}
|
IMetaHeader IVerificableMessage.GetMetaHeader()
|
||||||
|
{
|
||||||
|
return MetaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
IVerificationHeader IVerificableMessage.GetVerificationHeader()
|
||||||
|
{
|
||||||
|
return VerifyHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader)
|
||||||
|
{
|
||||||
|
MetaHeader = (RequestMetaHeader)metaHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader)
|
||||||
|
{
|
||||||
|
VerifyHeader = (RequestVerificationHeader)verificationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMessage GetBody()
|
||||||
|
{
|
||||||
|
return Body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
namespace FrostFS.Session
|
namespace FrostFS.Session;
|
||||||
{
|
|
||||||
public partial class RequestMetaHeader : IMetaHeader
|
|
||||||
{
|
|
||||||
public IMetaHeader GetOrigin()
|
|
||||||
{
|
|
||||||
return Origin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial class ResponseMetaHeader : IMetaHeader
|
public partial class RequestMetaHeader : IMetaHeader
|
||||||
|
{
|
||||||
|
public IMetaHeader GetOrigin()
|
||||||
{
|
{
|
||||||
public IMetaHeader GetOrigin()
|
return Origin;
|
||||||
{
|
}
|
||||||
return Origin;
|
}
|
||||||
}
|
|
||||||
|
public partial class ResponseMetaHeader : IMetaHeader
|
||||||
|
{
|
||||||
|
public IMetaHeader GetOrigin()
|
||||||
|
{
|
||||||
|
return Origin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,27 @@
|
||||||
namespace FrostFS.Session
|
namespace FrostFS.Session;
|
||||||
{
|
|
||||||
public partial class RequestVerificationHeader : IVerificationHeader
|
|
||||||
{
|
|
||||||
IVerificationHeader IVerificationHeader.GetOrigin()
|
|
||||||
{
|
|
||||||
return Origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IVerificationHeader.SetOrigin(IVerificationHeader verificationHeader)
|
public partial class RequestVerificationHeader : IVerificationHeader
|
||||||
{
|
{
|
||||||
Origin = (RequestVerificationHeader)verificationHeader;
|
IVerificationHeader IVerificationHeader.GetOrigin()
|
||||||
}
|
{
|
||||||
|
return Origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class ResponseVerificationHeader : IVerificationHeader
|
void IVerificationHeader.SetOrigin(IVerificationHeader verificationHeader)
|
||||||
{
|
{
|
||||||
IVerificationHeader IVerificationHeader.GetOrigin()
|
Origin = (RequestVerificationHeader)verificationHeader;
|
||||||
{
|
}
|
||||||
return Origin;
|
}
|
||||||
}
|
|
||||||
|
public partial class ResponseVerificationHeader : IVerificationHeader
|
||||||
void IVerificationHeader.SetOrigin(IVerificationHeader verificationHeader)
|
{
|
||||||
{
|
IVerificationHeader IVerificationHeader.GetOrigin()
|
||||||
Origin = (ResponseVerificationHeader)verificationHeader;
|
{
|
||||||
}
|
return Origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IVerificationHeader.SetOrigin(IVerificationHeader verificationHeader)
|
||||||
|
{
|
||||||
|
Origin = (ResponseVerificationHeader)verificationHeader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
namespace FrostFS.Session
|
namespace FrostFS.Session;
|
||||||
|
|
||||||
|
public partial class XHeader
|
||||||
{
|
{
|
||||||
public partial class XHeader
|
public const string ReservedXHeaderPrefix = "__NEOFS__";
|
||||||
{
|
public const string XHeaderNetmapEpoch = ReservedXHeaderPrefix + "NETMAP_EPOCH";
|
||||||
public const string ReservedXHeaderPrefix = "__NEOFS__";
|
public const string XHeaderNetmapLookupDepth = ReservedXHeaderPrefix + "NETMAP_LOOKUP_DEPTH";
|
||||||
public const string XHeaderNetmapEpoch = ReservedXHeaderPrefix + "NETMAP_EPOCH";
|
|
||||||
public const string XHeaderNetmapLookupDepth = ReservedXHeaderPrefix + "NETMAP_LOOKUP_DEPTH";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue