diff --git a/src/ProjectOrigin.Vault/EventHandlers/VaultSendRegistryTransactionConsumer.cs b/src/ProjectOrigin.Vault/EventHandlers/VaultSendRegistryTransactionConsumer.cs index 7499eb91..d394b358 100644 --- a/src/ProjectOrigin.Vault/EventHandlers/VaultSendRegistryTransactionConsumer.cs +++ b/src/ProjectOrigin.Vault/EventHandlers/VaultSendRegistryTransactionConsumer.cs @@ -1,21 +1,26 @@ +using Google.Protobuf; using Grpc.Net.Client; using MassTransit; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using ProjectOrigin.Electricity.V1; +using ProjectOrigin.HierarchicalDeterministicKeys.Interfaces; +using ProjectOrigin.PedersenCommitment; using ProjectOrigin.Registry.V1; +using ProjectOrigin.Vault.Database; using ProjectOrigin.Vault.Extensions; using ProjectOrigin.Vault.Models; using ProjectOrigin.Vault.Options; using System; +using System.Linq; +using System.Security.Cryptography; using System.Text.Json; using System.Threading.Tasks; -using ProjectOrigin.Vault.Database; namespace ProjectOrigin.Vault.EventHandlers; public record TransferFullSliceRegistryTransactionArguments { - public required Transaction Transaction { get; init; } public required string RegistryName { get; set; } public required Guid CertificateId { get; set; } public required Guid SliceId { get; set; } @@ -27,7 +32,6 @@ public record TransferFullSliceRegistryTransactionArguments public record TransferPartialSliceRegistryTransactionArguments { - public required Transaction Transaction { get; init; } public required string RegistryName { get; set; } public required Guid CertificateId { get; set; } public required Guid TransferredSliceId { get; set; } @@ -35,6 +39,7 @@ public record TransferPartialSliceRegistryTransactionArguments public required Guid SourceSliceId { get; set; } public required WalletAttribute[] WalletAttributes { get; set; } public required Guid ExternalEndpointId { get; set; } + public required uint Quantity { get; set; } public RequestStatusArgs? RequestStatusArgs { get; set; } } @@ -60,7 +65,16 @@ public async Task Consume(ConsumeContext s.ci.Message) != sourceSlice.Quantity) + throw new InvalidOperationException(); + + var certificateId = sourceSlice.GetFederatedStreamId(); + + var sourceSliceCommitment = new PedersenCommitment.SecretCommitmentInfo((uint)sourceSlice.Quantity, sourceSlice.RandomR); + var sumOfNewSlices = newSlices.Select(newSlice => newSlice.ci).Aggregate((left, right) => left + right); + var equalityProof = SecretCommitmentInfo.CreateEqualityProof(sourceSliceCommitment, sumOfNewSlices, certificateId.StreamId.Value); + + var slicedEvent = new SlicedEvent + { + CertificateId = certificateId, + SumProof = ByteString.CopyFrom(equalityProof), + SourceSliceHash = ByteString.CopyFrom(SHA256.HashData(sourceSliceCommitment.Commitment.C)) + }; + + foreach (var newSlice in newSlices) + { + var poSlice = new SlicedEvent.Types.Slice + { + NewOwner = new PublicKey + { + Type = KeyType.Secp256K1, + Content = ByteString.CopyFrom(newSlice.Key.Export()) + }, + Quantity = new ProjectOrigin.Electricity.V1.Commitment + { + Content = ByteString.CopyFrom(newSlice.ci.Commitment.C), + RangeProof = ByteString.CopyFrom(newSlice.ci.CreateRangeProof(certificateId.StreamId.Value)) + } + }; + slicedEvent.NewSlices.Add(poSlice); + } + + return slicedEvent; + } } diff --git a/src/ProjectOrigin.Vault/EventHandlers/VaultTransferFullSliceConsumer.cs b/src/ProjectOrigin.Vault/EventHandlers/VaultTransferFullSliceConsumer.cs index ddd95a06..d22ded6d 100644 --- a/src/ProjectOrigin.Vault/EventHandlers/VaultTransferFullSliceConsumer.cs +++ b/src/ProjectOrigin.Vault/EventHandlers/VaultTransferFullSliceConsumer.cs @@ -1,9 +1,6 @@ -using Google.Protobuf; using MassTransit; using Microsoft.Extensions.Logging; using Npgsql; -using ProjectOrigin.Electricity.V1; -using ProjectOrigin.HierarchicalDeterministicKeys.Interfaces; using ProjectOrigin.Vault.Database; using ProjectOrigin.Vault.Exceptions; using ProjectOrigin.Vault.Extensions; @@ -11,7 +8,7 @@ using ProjectOrigin.Vault.Models; using System; using System.Linq; -using System.Security.Cryptography; +using System.Text.Json; using System.Threading.Tasks; namespace ProjectOrigin.Vault.EventHandlers; @@ -33,7 +30,6 @@ public class VaultTransferFullSliceConsumer : IConsumer logger, - IEndpointNameFormatter formatter, ITransferMetrics transferMetrics) { _unitOfWork = unitOfWork; @@ -52,9 +48,7 @@ public async Task Consume(ConsumeContext context) var sourceSlice = await _unitOfWork.CertificateRepository.GetWalletSlice(msg.SourceSliceId); var sourceEndpoint = await _unitOfWork.WalletRepository.GetWalletEndpoint(sourceSlice.WalletEndpointId); var externalEndpoint = await _unitOfWork.WalletRepository.GetExternalEndpoint(msg.ExternalEndpointId); - var nextReceiverPosition = await _unitOfWork.WalletRepository.GetNextNumberForId(externalEndpoint.Id); - var receiverPublicKey = externalEndpoint.PublicKey.Derive(nextReceiverPosition).GetPublicKey(); var transferredSlice = new TransferredSlice { @@ -71,19 +65,12 @@ public async Task Consume(ConsumeContext context) _logger.LogInformation($"Registering transfer for certificateId {sourceSlice.CertificateId}"); - var transferredEvent = CreateTransferEvent(sourceSlice, receiverPublicKey); - - var sourceSlicePrivateKey = await _unitOfWork.WalletRepository.GetPrivateKeyForSlice(sourceSlice.Id); - var transaction = sourceSlicePrivateKey.SignRegistryTransaction(transferredEvent.CertificateId, transferredEvent); var walletAttributes = await _unitOfWork.CertificateRepository.GetWalletAttributes(sourceEndpoint.WalletId, sourceSlice.CertificateId, sourceSlice.RegistryName, msg.HashedAttributes); - _unitOfWork.Commit(); - _logger.LogInformation("Ending consumer: {Consumer}, RequestId: {RequestId} ", nameof(VaultTransferFullSliceConsumer), msg.RequestStatusArgs.RequestId); - await context.Publish(new TransferFullSliceRegistryTransactionArguments + var message = new TransferFullSliceRegistryTransactionArguments { - Transaction = transaction, CertificateId = sourceSlice.CertificateId, RegistryName = sourceSlice.RegistryName, SliceId = sourceSlice.Id, @@ -91,7 +78,16 @@ await context.Publish(new Transfe RequestStatusArgs = msg.RequestStatusArgs, ExternalEndpointId = externalEndpoint.Id, WalletAttributes = walletAttributes.ToArray() + }; + await _unitOfWork.OutboxMessageRepository.Create(new OutboxMessage + { + Created = DateTimeOffset.UtcNow.ToUtcTime(), + Id = Guid.NewGuid(), + MessageType = typeof(TransferFullSliceRegistryTransactionArguments).ToString(), + JsonPayload = JsonSerializer.Serialize(message) }); + + _unitOfWork.Commit(); } catch (PostgresException ex) { @@ -108,21 +104,4 @@ await context.Publish(new Transfe throw; } } - - private static TransferredEvent CreateTransferEvent(WalletSlice sourceSlice, IPublicKey receiverPublicKey) - { - var sliceCommitment = new PedersenCommitment.SecretCommitmentInfo((uint)sourceSlice.Quantity, sourceSlice.RandomR); - - var transferredEvent = new TransferredEvent - { - CertificateId = sourceSlice.GetFederatedStreamId(), - NewOwner = new PublicKey - { - Content = ByteString.CopyFrom(receiverPublicKey.Export()), - Type = KeyType.Secp256K1 - }, - SourceSliceHash = ByteString.CopyFrom(SHA256.HashData(sliceCommitment.Commitment.C)) - }; - return transferredEvent; - } } diff --git a/src/ProjectOrigin.Vault/EventHandlers/VaultTransferPartialSliceConsumer.cs b/src/ProjectOrigin.Vault/EventHandlers/VaultTransferPartialSliceConsumer.cs index bb189206..39210b79 100644 --- a/src/ProjectOrigin.Vault/EventHandlers/VaultTransferPartialSliceConsumer.cs +++ b/src/ProjectOrigin.Vault/EventHandlers/VaultTransferPartialSliceConsumer.cs @@ -1,9 +1,6 @@ -using Google.Protobuf; using MassTransit; using Microsoft.Extensions.Logging; using Npgsql; -using ProjectOrigin.Electricity.V1; -using ProjectOrigin.HierarchicalDeterministicKeys.Interfaces; using ProjectOrigin.PedersenCommitment; using ProjectOrigin.Vault.Database; using ProjectOrigin.Vault.Exceptions; @@ -12,7 +9,7 @@ using ProjectOrigin.Vault.Models; using System; using System.Linq; -using System.Security.Cryptography; +using System.Text.Json; using System.Threading.Tasks; namespace ProjectOrigin.Vault.EventHandlers; @@ -58,7 +55,6 @@ public async Task Consume(ConsumeContext context) var receiverEndpoints = await _unitOfWork.WalletRepository.GetExternalEndpoint(msg.ExternalEndpointId); var receiverPosition = await _unitOfWork.WalletRepository.GetNextNumberForId(receiverEndpoints.Id); - var receiverPublicKey = receiverEndpoints.PublicKey.Derive(receiverPosition).GetPublicKey(); var receiverCommitment = new SecretCommitmentInfo(quantity); var transferredSlice = new TransferredSlice { @@ -75,7 +71,6 @@ public async Task Consume(ConsumeContext context) var remainderEndpoint = await _unitOfWork.WalletRepository.GetWalletRemainderEndpoint(sourceEndpoint.WalletId); var remainderPosition = await _unitOfWork.WalletRepository.GetNextNumberForId(remainderEndpoint.Id); - var remainderPublicKey = remainderEndpoint.PublicKey.Derive(remainderPosition).GetPublicKey(); var remainderCommitment = new SecretCommitmentInfo(remainder); var remainderSlice = new WalletSlice { @@ -90,27 +85,32 @@ public async Task Consume(ConsumeContext context) }; await _unitOfWork.CertificateRepository.InsertWalletSlice(remainderSlice); - var slicedEvent = CreateSliceEvent(sourceSlice, new NewSlice(receiverCommitment, receiverPublicKey), new NewSlice(remainderCommitment, remainderPublicKey)); - var sourceSlicePrivateKey = await _unitOfWork.WalletRepository.GetPrivateKeyForSlice(sourceSlice.Id); - var transaction = sourceSlicePrivateKey.SignRegistryTransaction(slicedEvent.CertificateId, slicedEvent); var walletAttributes = await _unitOfWork.CertificateRepository.GetWalletAttributes(sourceEndpoint.WalletId, sourceSlice.CertificateId, sourceSlice.RegistryName, msg.HashedAttributes); - _unitOfWork.Commit(); - _logger.LogInformation("Ending consumer: {Consumer}, RequestId: {RequestId} ", nameof(VaultTransferPartialSliceConsumer), msg.RequestStatusArgs.RequestId); - await context.Publish(new TransferPartialSliceRegistryTransactionArguments + var message = new TransferPartialSliceRegistryTransactionArguments { - Transaction = transaction, WalletAttributes = walletAttributes.ToArray(), ExternalEndpointId = receiverEndpoints.Id, TransferredSliceId = transferredSlice.Id, CertificateId = transferredSlice.CertificateId, - RegistryName = transaction.Header.FederatedStreamId.Registry, + RegistryName = sourceSlice.RegistryName, RemainderSliceId = remainderSlice.Id, RequestStatusArgs = msg.RequestStatusArgs, - SourceSliceId = sourceSlice.Id + SourceSliceId = sourceSlice.Id, + Quantity = msg.Quantity + }; + + await _unitOfWork.OutboxMessageRepository.Create(new OutboxMessage + { + Created = DateTimeOffset.UtcNow.ToUtcTime(), + Id = Guid.NewGuid(), + MessageType = typeof(TransferPartialSliceRegistryTransactionArguments).ToString(), + JsonPayload = JsonSerializer.Serialize(message) }); + + _unitOfWork.Commit(); } catch (PostgresException ex) { @@ -127,45 +127,4 @@ await context.Publish(new Tran throw; } } - - private sealed record NewSlice(SecretCommitmentInfo ci, IPublicKey Key); - - private static SlicedEvent CreateSliceEvent(WalletSlice sourceSlice, params NewSlice[] newSlices) - { - if (newSlices.Sum(s => s.ci.Message) != sourceSlice.Quantity) - throw new InvalidOperationException(); - - var certificateId = sourceSlice.GetFederatedStreamId(); - - var sourceSliceCommitment = new PedersenCommitment.SecretCommitmentInfo((uint)sourceSlice.Quantity, sourceSlice.RandomR); - var sumOfNewSlices = newSlices.Select(newSlice => newSlice.ci).Aggregate((left, right) => left + right); - var equalityProof = SecretCommitmentInfo.CreateEqualityProof(sourceSliceCommitment, sumOfNewSlices, certificateId.StreamId.Value); - - var slicedEvent = new SlicedEvent - { - CertificateId = certificateId, - SumProof = ByteString.CopyFrom(equalityProof), - SourceSliceHash = ByteString.CopyFrom(SHA256.HashData(sourceSliceCommitment.Commitment.C)) - }; - - foreach (var newSlice in newSlices) - { - var poSlice = new SlicedEvent.Types.Slice - { - NewOwner = new PublicKey - { - Type = KeyType.Secp256K1, - Content = ByteString.CopyFrom(newSlice.Key.Export()) - }, - Quantity = new ProjectOrigin.Electricity.V1.Commitment - { - Content = ByteString.CopyFrom(newSlice.ci.Commitment.C), - RangeProof = ByteString.CopyFrom(newSlice.ci.CreateRangeProof(certificateId.StreamId.Value)) - } - }; - slicedEvent.NewSlices.Add(poSlice); - } - - return slicedEvent; - } }