private async Task CollectPiecesWithSecretSharingAsync(SecretSharingInformation secretSharingInformation, Hash newInValue, string selfPubkey) { var encryptedPieces = new Dictionary <string, byte[]>(); var decryptedPieces = new Dictionary <string, byte[]>(); var minersCount = secretSharingInformation.PreviousRound.RealTimeMinersInformation.Count; var minimumCount = minersCount.Mul(2).Div(3); var secretShares = SecretSharingHelper.EncodeSecret(newInValue.ToByteArray(), minimumCount, minersCount); foreach (var pair in secretSharingInformation.PreviousRound.RealTimeMinersInformation .OrderBy(m => m.Value.Order).ToDictionary(m => m.Key, m => m.Value.Order)) { var pubkey = pair.Key; var order = pair.Value; var plainMessage = secretShares[order - 1]; var receiverPublicKey = ByteArrayHelper.HexStringToByteArray(pubkey); var encryptedPiece = await _accountService.EncryptMessageAsync(receiverPublicKey, plainMessage); encryptedPieces[pubkey] = encryptedPiece; if (secretSharingInformation.PreviousRound.RealTimeMinersInformation.ContainsKey(selfPubkey) && secretSharingInformation.PreviousRound.RealTimeMinersInformation[selfPubkey].EncryptedPieces .ContainsKey(pubkey)) { secretSharingInformation.PreviousRound.RealTimeMinersInformation[selfPubkey] .EncryptedPieces[pubkey] = ByteString.CopyFrom(encryptedPiece); } else { continue; } if (!secretSharingInformation.PreviousRound.RealTimeMinersInformation.ContainsKey(pubkey)) { continue; } var encryptedShares = secretSharingInformation.PreviousRound.RealTimeMinersInformation[pubkey].EncryptedPieces; if (!encryptedShares.Any()) { continue; } var interestingMessage = encryptedShares[selfPubkey]; var senderPublicKey = ByteArrayHelper.HexStringToByteArray(pubkey); var decryptedPiece = await _accountService.DecryptMessageAsync(senderPublicKey, interestingMessage.ToByteArray()); decryptedPieces[pubkey] = decryptedPiece; secretSharingInformation.PreviousRound.RealTimeMinersInformation[pubkey].DecryptedPieces[selfPubkey] = ByteString.CopyFrom(decryptedPiece); } _encryptedPieces[secretSharingInformation.CurrentRoundId] = encryptedPieces; _decryptedPieces[secretSharingInformation.CurrentRoundId] = decryptedPieces; }
public async Task AddSharingInformationAsync(LogEvent logEvent) { try { var selfPubkey = (await _accountService.GetPublicKeyAsync()).ToHex(); var secretSharingInformation = new SecretSharingInformation(); secretSharingInformation.MergeFrom(logEvent); if (!secretSharingInformation.PreviousRound.RealTimeMinersInformation.ContainsKey(selfPubkey)) { return; } var newInValue = await GenerateInValueAsync(secretSharingInformation); Logger.LogInformation( $"Add in value {newInValue} for round id {secretSharingInformation.CurrentRoundId}"); _inValueCache.AddInValue(secretSharingInformation.CurrentRoundId, newInValue); if (secretSharingInformation.PreviousRound.RealTimeMinersInformation.Count == 1) { return; } await CollectPiecesWithSecretSharingAsync(secretSharingInformation, newInValue, selfPubkey); RevealPreviousInValues(secretSharingInformation, selfPubkey); } catch (Exception e) { Logger.LogError($"Error in AddSharingInformationAsync.\n{e.Message}\n{e.StackTrace}"); } }
protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) { var secretSharingInformation = new SecretSharingInformation(); secretSharingInformation.MergeFrom(logEvent); await _secretSharingService.AddSharingInformationAsync(secretSharingInformation); }
private void RevealPreviousInValues(SecretSharingInformation secretSharingInformation, string selfPubkey) { var round = secretSharingInformation.PreviousRound; var minersCount = round.RealTimeMinersInformation.Count; var minimumCount = minersCount.Mul(2).Div(3); minimumCount = minimumCount == 0 ? 1 : minimumCount; var revealedInValues = new Dictionary <string, Hash>(); foreach (var pair in round.RealTimeMinersInformation.OrderBy(m => m.Value.Order)) { // Skip himself. if (pair.Key == selfPubkey) { continue; } var pubkey = pair.Key; var minerInRound = pair.Value; if (minerInRound.EncryptedPieces.Count < minimumCount) { continue; } if (minerInRound.DecryptedPieces.Count < minersCount) { continue; } // Reveal another miner's in value for target round: var orders = minerInRound.DecryptedPieces.Select((t, i) => round.RealTimeMinersInformation.Values .First(m => m.Pubkey == minerInRound.DecryptedPieces.Keys.ToList()[i]).Order) .ToList(); var sharedParts = minerInRound.DecryptedPieces.Values.ToList() .Select(s => s.ToByteArray()).ToList(); var revealedInValue = Hash.FromRawBytes(SecretSharingHelper.DecodeSecret(sharedParts, orders, minimumCount)); Logger.LogDebug($"Revealed in value of {pubkey} of round {round.RoundNumber}: {revealedInValue}"); revealedInValues[pubkey] = revealedInValue; } _revealedInValues[secretSharingInformation.CurrentRoundId] = revealedInValues; }
public Task AddSharingInformationAsync(LogEvent logEvent) { try { var secretSharingInformation = new SecretSharingInformation(); secretSharingInformation.MergeFrom(logEvent); var newInValue = GenerateInValue(secretSharingInformation); _inValueCacheService.AddInValue(secretSharingInformation.CurrentRoundId, newInValue); //Logger.LogTrace( //$"Handling sharing information: {secretSharingInformation}. New in value: {newInValue}"); if (secretSharingInformation.PreviousRound.RealTimeMinersInformation.Count == 1) { return(Task.CompletedTask); } var encryptedPieces = new Dictionary <string, byte[]>(); var decryptedPieces = new Dictionary <string, byte[]>(); var minersCount = secretSharingInformation.PreviousRound.RealTimeMinersInformation.Count; var minimumCount = minersCount.Mul(2).Div(3); var secretShares = SecretSharingHelper.EncodeSecret(newInValue.ToByteArray(), minimumCount, minersCount); var selfPubkey = AsyncHelper.RunSync(_accountService.GetPublicKeyAsync).ToHex(); foreach (var pair in secretSharingInformation.PreviousRound.RealTimeMinersInformation .OrderBy(m => m.Value.Order).ToDictionary(m => m.Key, m => m.Value.Order)) { var pubkey = pair.Key; var order = pair.Value; var plainMessage = secretShares[order - 1]; var receiverPublicKey = ByteArrayHelper.HexStringToByteArray(pubkey); var encryptedPiece = AsyncHelper.RunSync(() => _accountService.EncryptMessageAsync(receiverPublicKey, plainMessage)); encryptedPieces[pubkey] = encryptedPiece; if (secretSharingInformation.PreviousRound.RealTimeMinersInformation.ContainsKey(selfPubkey) && secretSharingInformation.PreviousRound.RealTimeMinersInformation[selfPubkey].EncryptedPieces .ContainsKey(pubkey)) { secretSharingInformation.PreviousRound.RealTimeMinersInformation[selfPubkey] .EncryptedPieces[pubkey] = ByteString.CopyFrom(encryptedPiece); } else { continue; } if (!secretSharingInformation.PreviousRound.RealTimeMinersInformation.ContainsKey(pubkey)) { continue; } var encryptedShares = secretSharingInformation.PreviousRound.RealTimeMinersInformation[pubkey].EncryptedPieces; if (!encryptedShares.Any()) { continue; } var interestingMessage = encryptedShares[selfPubkey]; var senderPublicKey = ByteArrayHelper.HexStringToByteArray(pubkey); var decryptedPiece = AsyncHelper.RunSync(() => _accountService.DecryptMessageAsync(senderPublicKey, interestingMessage.ToByteArray())); decryptedPieces[pubkey] = decryptedPiece; secretSharingInformation.PreviousRound.RealTimeMinersInformation[pubkey].DecryptedPieces[selfPubkey] = ByteString.CopyFrom(decryptedPiece); } _encryptedPieces[secretSharingInformation.CurrentRoundId] = encryptedPieces; _decryptedPieces[secretSharingInformation.CurrentRoundId] = decryptedPieces; RevealPreviousInValues(secretSharingInformation, selfPubkey); Logger.LogTrace($"Final secret sharing information: {secretSharingInformation}"); } catch (Exception e) { Logger.LogError($"Error in AddSharingInformationAsync.\n{e.Message}\n{e.StackTrace}"); } return(Task.CompletedTask); }