Reformat/cleanup
All checks were successful
NuGet Package Publish / nuget (push) Successful in 1m10s
All checks were successful
NuGet Package Publish / nuget (push) Successful in 1m10s
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Globalization;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ZB.MOM.WW.CBDDC.Core;
|
||||
@@ -10,84 +12,56 @@ public enum OperationType
|
||||
Delete
|
||||
}
|
||||
|
||||
public static class OplogEntryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Computes a deterministic hash for the specified oplog entry.
|
||||
/// </summary>
|
||||
/// <param name="entry">The oplog entry to hash.</param>
|
||||
/// <returns>The lowercase hexadecimal SHA-256 hash of the entry.</returns>
|
||||
public static string ComputeHash(this OplogEntry entry)
|
||||
{
|
||||
using var sha256 = System.Security.Cryptography.SHA256.Create();
|
||||
var sb = new System.Text.StringBuilder();
|
||||
public static class OplogEntryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Computes a deterministic hash for the specified oplog entry.
|
||||
/// </summary>
|
||||
/// <param name="entry">The oplog entry to hash.</param>
|
||||
/// <returns>The lowercase hexadecimal SHA-256 hash of the entry.</returns>
|
||||
public static string ComputeHash(this OplogEntry entry)
|
||||
{
|
||||
using var sha256 = SHA256.Create();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.Append(entry.Collection);
|
||||
sb.Append('|');
|
||||
sb.Append(entry.Key);
|
||||
sb.Append('|');
|
||||
// Ensure stable string representation for Enum (integer value)
|
||||
sb.Append(((int)entry.Operation).ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
sb.Append(((int)entry.Operation).ToString(CultureInfo.InvariantCulture));
|
||||
sb.Append('|');
|
||||
// Payload excluded from hash to avoid serialization non-determinism
|
||||
// sb.Append(entry.Payload...);
|
||||
sb.Append('|');
|
||||
// Timestamp.ToString() is now Invariant
|
||||
sb.Append(entry.Timestamp.ToString());
|
||||
sb.Append(entry.Timestamp.ToString());
|
||||
sb.Append('|');
|
||||
sb.Append(entry.PreviousHash);
|
||||
|
||||
var bytes = System.Text.Encoding.UTF8.GetBytes(sb.ToString());
|
||||
var hashBytes = sha256.ComputeHash(bytes);
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString());
|
||||
byte[] hashBytes = sha256.ComputeHash(bytes);
|
||||
|
||||
// Convert to hex string
|
||||
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
|
||||
public class OplogEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the collection name associated with this entry.
|
||||
/// </summary>
|
||||
public string Collection { get; }
|
||||
/// <summary>
|
||||
/// Gets the document key associated with this entry.
|
||||
/// </summary>
|
||||
public string Key { get; }
|
||||
/// <summary>
|
||||
/// Gets the operation represented by this entry.
|
||||
/// </summary>
|
||||
public OperationType Operation { get; }
|
||||
/// <summary>
|
||||
/// Gets the serialized payload for the operation.
|
||||
/// </summary>
|
||||
public JsonElement? Payload { get; }
|
||||
/// <summary>
|
||||
/// Gets the logical timestamp for this entry.
|
||||
/// </summary>
|
||||
public HlcTimestamp Timestamp { get; }
|
||||
/// <summary>
|
||||
/// Gets the hash of this entry.
|
||||
/// </summary>
|
||||
public string Hash { get; }
|
||||
/// <summary>
|
||||
/// Gets the hash of the previous entry in the chain.
|
||||
/// </summary>
|
||||
public string PreviousHash { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OplogEntry"/> class.
|
||||
/// </summary>
|
||||
/// <param name="collection">The collection name.</param>
|
||||
/// <param name="key">The document key.</param>
|
||||
/// <param name="operation">The operation type.</param>
|
||||
/// <param name="payload">The serialized payload.</param>
|
||||
/// <param name="timestamp">The logical timestamp.</param>
|
||||
/// <param name="previousHash">The previous entry hash.</param>
|
||||
/// <param name="hash">The current entry hash. If null, it is computed.</param>
|
||||
public OplogEntry(string collection, string key, OperationType operation, JsonElement? payload, HlcTimestamp timestamp, string previousHash, string? hash = null)
|
||||
{
|
||||
public class OplogEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OplogEntry" /> class.
|
||||
/// </summary>
|
||||
/// <param name="collection">The collection name.</param>
|
||||
/// <param name="key">The document key.</param>
|
||||
/// <param name="operation">The operation type.</param>
|
||||
/// <param name="payload">The serialized payload.</param>
|
||||
/// <param name="timestamp">The logical timestamp.</param>
|
||||
/// <param name="previousHash">The previous entry hash.</param>
|
||||
/// <param name="hash">The current entry hash. If null, it is computed.</param>
|
||||
public OplogEntry(string collection, string key, OperationType operation, JsonElement? payload,
|
||||
HlcTimestamp timestamp, string previousHash, string? hash = null)
|
||||
{
|
||||
Collection = collection;
|
||||
Key = key;
|
||||
Operation = operation;
|
||||
@@ -98,10 +72,45 @@ public class OplogEntry
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies if the stored Hash matches the content.
|
||||
/// Gets the collection name associated with this entry.
|
||||
/// </summary>
|
||||
public string Collection { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the document key associated with this entry.
|
||||
/// </summary>
|
||||
public string Key { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the operation represented by this entry.
|
||||
/// </summary>
|
||||
public OperationType Operation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the serialized payload for the operation.
|
||||
/// </summary>
|
||||
public JsonElement? Payload { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logical timestamp for this entry.
|
||||
/// </summary>
|
||||
public HlcTimestamp Timestamp { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hash of this entry.
|
||||
/// </summary>
|
||||
public string Hash { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hash of the previous entry in the chain.
|
||||
/// </summary>
|
||||
public string PreviousHash { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies if the stored Hash matches the content.
|
||||
/// </summary>
|
||||
public bool IsValid()
|
||||
{
|
||||
return Hash == this.ComputeHash();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user