196 lines
5.4 KiB
C#
196 lines
5.4 KiB
C#
using System;
|
|
using System.Linq;
|
|
|
|
using FrostFS.Object;
|
|
using FrostFS.Refs;
|
|
using FrostFS.SDK.Client.Mappers.GRPC;
|
|
using FrostFS.SDK.Cryptography;
|
|
|
|
using Google.Protobuf;
|
|
|
|
namespace FrostFS.SDK.Client;
|
|
|
|
public static class ObjectTools
|
|
{
|
|
public static FrostFsObjectId CalculateObjectId(
|
|
FrostFsObjectHeader header,
|
|
ReadOnlyMemory<byte> payloadHash,
|
|
FrostFsOwner owner,
|
|
FrostFsVersion version,
|
|
ClientKey key)
|
|
{
|
|
if (header is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(header));
|
|
}
|
|
|
|
if (owner is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(owner));
|
|
}
|
|
|
|
if (version is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(version));
|
|
}
|
|
|
|
if (key is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
var grpcHeader = CreateHeader(header, payloadHash, owner, version);
|
|
|
|
if (header.Split != null)
|
|
SetSplitValues(grpcHeader, header.Split, owner, version, key);
|
|
|
|
return new ObjectID { Value = grpcHeader.Sha256() }.ToModel();
|
|
}
|
|
|
|
internal static Object.Object CreateSingleObject(FrostFsObject @object, ClientContext ctx)
|
|
{
|
|
@object.Header.OwnerId ??= ctx.Owner;
|
|
@object.Header.Version ??= ctx.Version;
|
|
|
|
var grpcHeader = @object.Header.GetHeader();
|
|
|
|
grpcHeader.PayloadLength = (ulong)@object.SingleObjectPayload.Length;
|
|
|
|
if (@object.PayloadHash != null)
|
|
{
|
|
grpcHeader.PayloadHash = ChecksumFromSha256(@object.PayloadHash);
|
|
}
|
|
else
|
|
{
|
|
grpcHeader.PayloadHash = Sha256Checksum(@object.SingleObjectPayload);
|
|
}
|
|
|
|
var split = @object.Header.Split;
|
|
|
|
if (split != null)
|
|
{
|
|
SetSplitValues(grpcHeader, split, ctx.Owner, ctx.Version, ctx.Key);
|
|
}
|
|
|
|
var obj = new Object.Object
|
|
{
|
|
Header = grpcHeader,
|
|
ObjectId = new ObjectID { Value = grpcHeader.Sha256() },
|
|
Payload = UnsafeByteOperations.UnsafeWrap(@object.SingleObjectPayload)
|
|
};
|
|
|
|
obj.Signature = new Signature
|
|
{
|
|
Key = ctx.Key.PublicKeyProto,
|
|
Sign = ctx.Key.ECDsaKey.SignData(obj.ObjectId.ToByteArray()),
|
|
};
|
|
|
|
return obj;
|
|
}
|
|
|
|
internal static void SetSplitValues(
|
|
Header grpcHeader,
|
|
FrostFsSplit split,
|
|
FrostFsOwner owner,
|
|
FrostFsVersion version,
|
|
ClientKey key)
|
|
{
|
|
if (split == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (key == null)
|
|
{
|
|
throw new FrostFsInvalidObjectException(nameof(key));
|
|
}
|
|
|
|
grpcHeader.Split = new Header.Types.Split
|
|
{
|
|
SplitId = split.SplitId?.GetSplitId()
|
|
};
|
|
|
|
if (split.Children != null && split.Children.Count != 0)
|
|
{
|
|
grpcHeader.Split.Children.AddRange(split.Children.Select(id => id.ToMessage()));
|
|
}
|
|
|
|
if (split.ParentHeader is not null)
|
|
{
|
|
var grpcParentHeader = CreateHeader(split.ParentHeader, Array.Empty<byte>().Sha256(), owner, version);
|
|
|
|
grpcHeader.Split.Parent = new ObjectID { Value = grpcParentHeader.Sha256() };
|
|
grpcHeader.Split.ParentHeader = grpcParentHeader;
|
|
grpcHeader.Split.ParentSignature = new Signature
|
|
{
|
|
Key = key.PublicKeyProto,
|
|
Sign = key.ECDsaKey.SignData(grpcHeader.Split.Parent.ToByteArray()),
|
|
};
|
|
}
|
|
|
|
grpcHeader.Split.Previous = split.Previous?.ToMessage();
|
|
}
|
|
|
|
internal static Header.Types.Split CreateSplit(FrostFsSplit split, ClientKey key, FrostFsOwner owner, FrostFsVersion version)
|
|
{
|
|
if (split.ParentHeader == null)
|
|
{
|
|
return split.GetSplit();
|
|
}
|
|
split.ParentHeader.PayloadCheckSum ??= Array.Empty<byte>().Sha256();
|
|
var grpcParentHeader = CreateHeader(split.ParentHeader, split.ParentHeader.PayloadCheckSum, owner, version);
|
|
|
|
var res = split.GetSplit();
|
|
res.ParentHeader = grpcParentHeader;
|
|
res.Parent ??= new ObjectID { Value = grpcParentHeader.Sha256() };
|
|
res.ParentSignature ??= new Signature
|
|
{
|
|
Key = key.PublicKeyProto,
|
|
Sign = key.ECDsaKey.SignData(res.Parent.ToByteArray()),
|
|
};
|
|
return res;
|
|
}
|
|
|
|
internal static Header CreateHeader(
|
|
FrostFsObjectHeader header,
|
|
ReadOnlyMemory<byte> payloadChecksum,
|
|
FrostFsOwner owner,
|
|
FrostFsVersion version)
|
|
{
|
|
header.OwnerId ??= owner;
|
|
header.Version ??= version;
|
|
|
|
var grpcHeader = header.GetHeader();
|
|
|
|
grpcHeader.PayloadHash = ChecksumFromSha256(payloadChecksum);
|
|
|
|
return grpcHeader;
|
|
}
|
|
|
|
internal static Checksum Sha256Checksum(byte[] data)
|
|
{
|
|
return new Checksum
|
|
{
|
|
Type = ChecksumType.Sha256,
|
|
Sum = ByteString.CopyFrom(data.Sha256())
|
|
};
|
|
}
|
|
|
|
internal static Checksum Sha256Checksum(ReadOnlyMemory<byte> data)
|
|
{
|
|
return new Checksum
|
|
{
|
|
Type = ChecksumType.Sha256,
|
|
Sum = ByteString.CopyFrom(data.Sha256())
|
|
};
|
|
}
|
|
|
|
internal static Checksum ChecksumFromSha256(ReadOnlyMemory<byte> dataHash)
|
|
{
|
|
return new Checksum
|
|
{
|
|
Type = ChecksumType.Sha256,
|
|
Sum = UnsafeByteOperations.UnsafeWrap(dataHash)
|
|
};
|
|
}
|
|
}
|