Skip to content

Commit

Permalink
Merge pull request #266 from LATOKEN/shares_validation
Browse files Browse the repository at this point in the history
Partially decrypted shares from peers validation
  • Loading branch information
sgladkov authored Sep 2, 2022
2 parents 3e09a28 + 25982e0 commit cc26152
Show file tree
Hide file tree
Showing 35 changed files with 793 additions and 48 deletions.
36 changes: 32 additions & 4 deletions src/Lachain.Consensus/HoneyBadger/HoneyBadger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ public class HoneyBadger : AbstractProtocol
private EncryptedShare? _encryptedShare;
private ISet<IRawShare>? _result;
private bool _takenSet;
private bool _skipDecryptedShareValidation;

public HoneyBadger(HoneyBadgerId honeyBadgerId, IPublicConsensusKeySet wallet,
PrivateKey privateKey, IConsensusBroadcaster broadcaster)
PrivateKey privateKey, bool skipDecryptedShareValidation, IConsensusBroadcaster broadcaster)
: base(wallet, honeyBadgerId, broadcaster)
{
_honeyBadgerId = honeyBadgerId;
Expand All @@ -43,6 +44,7 @@ public HoneyBadger(HoneyBadgerId honeyBadgerId, IPublicConsensusKeySet wallet,
_taken = new bool[N];
_shares = new IRawShare[N];
_requested = ResultStatus.NotRequested;
_skipDecryptedShareValidation = skipDecryptedShareValidation;
}

public override void ProcessMessage(MessageEnvelope envelope)
Expand Down Expand Up @@ -136,6 +138,19 @@ private void HandleCommonSubset(ProtocolResult<CommonSubsetId, ISet<EncryptedSha
var dec = _privateKey.Decrypt(share);
_taken[share.Id] = true;
_receivedShares[share.Id] = share;
if (_decryptedShares[share.Id].Count > 0) // if we have any partially decrypted shares for this share - verify them
{
if (!_skipDecryptedShareValidation)
{
if (Wallet.GetTpkeVerificationKey(share.Id) is null)
_decryptedShares[share.Id].Clear();
else
_decryptedShares[share.Id] = _decryptedShares[share.Id]
.Where(ps => Wallet.GetTpkeVerificationKey(ps.DecryptorId)!.VerifyShare(share, ps))
.ToHashSet();
}
}

// todo think about async access to protocol method. This may pose threat to protocol internal invariants
CheckDecryptedShares(share.Id);
Broadcaster.Broadcast(CreateDecryptedMessage(dec));
Expand All @@ -151,7 +166,7 @@ private void HandleCommonSubset(ProtocolResult<CommonSubsetId, ISet<EncryptedSha
CheckResult();
}

private ConsensusMessage CreateDecryptedMessage(PartiallyDecryptedShare share)
protected virtual ConsensusMessage CreateDecryptedMessage(PartiallyDecryptedShare share)
{
var message = new ConsensusMessage
{
Expand All @@ -169,12 +184,25 @@ private void HandleDecryptedMessage(TPKEPartiallyDecryptedShareMessage msg, int
{
// Converting any random bytes to G1 is not possible
share = Wallet.TpkePublicKey.Decode(msg);
if (!(_receivedShares[share.ShareId] is null))
{
if (!_skipDecryptedShareValidation)
{
if (Wallet.GetTpkeVerificationKey(share.DecryptorId) is null)
throw new Exception("No verification key for this sender");
if (!Wallet.GetTpkeVerificationKey(share.DecryptorId)!.VerifyShare(
_receivedShares[share.ShareId]!, share))
throw new Exception("Invalid share");
}
}

_decryptedShares[share.ShareId].Add(share);
}
catch (Exception exception)
catch (Exception ex)
{
share = null;
var pubKey = Broadcaster.GetPublicKeyById(senderId)!.ToHex();
Logger.LogWarning($"Exception occured handling Decrypted message: {msg} from {senderId} ({pubKey})");
Logger.LogWarning($"Exception occured handling Decrypted message: {msg} from {senderId} ({pubKey}), exception: {ex}");
}

if (!(share is null))
Expand Down
1 change: 1 addition & 0 deletions src/Lachain.Consensus/IPublicConsensusKeySet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ public interface IPublicConsensusKeySet
PublicKeySet ThresholdSignaturePublicKeySet { get; }
IList<ECDSAPublicKey> EcdsaPublicKeySet { get; }
public int GetValidatorIndex(ECDSAPublicKey publicKey);
public PublicKey? GetTpkeVerificationKey(int playerIdx);
}
}
17 changes: 17 additions & 0 deletions src/Lachain.Consensus/PublicConsensusKeySet.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Lachain.Crypto.ThresholdSignature;
Expand All @@ -15,8 +16,11 @@ public class PublicConsensusKeySet : IPublicConsensusKeySet
private readonly List<ECDSAPublicKey> _ecdsaPublicKeys;
public IList<ECDSAPublicKey> EcdsaPublicKeySet => _ecdsaPublicKeys;

private List<PublicKey> _tpkeVerificationKeys;

public PublicConsensusKeySet(int n, int f,
PublicKey tpkePublicKey,
IEnumerable<PublicKey> tpkeVerificationKeys,
PublicKeySet thresholdSignaturePublicKeySet,
IEnumerable<ECDSAPublicKey> ecdsaPublicKeys
)
Expand All @@ -26,6 +30,7 @@ IEnumerable<ECDSAPublicKey> ecdsaPublicKeys
TpkePublicKey = tpkePublicKey;
ThresholdSignaturePublicKeySet = thresholdSignaturePublicKeySet;
_ecdsaPublicKeys = ecdsaPublicKeys.ToList();
_tpkeVerificationKeys = tpkeVerificationKeys.ToList();
}

public int GetValidatorIndex(ECDSAPublicKey publicKey)
Expand All @@ -37,5 +42,17 @@ public int GetValidatorIndex(ECDSAPublicKey publicKey)
.DefaultIfEmpty(-1)
.First();
}

public PublicKey? GetTpkeVerificationKey(int playerIdx)
{
try
{
return _tpkeVerificationKeys[playerIdx];
}
catch (Exception e)
{
return null;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using Lachain.Crypto;
using Lachain.Proto;
Expand All @@ -9,6 +10,7 @@ public struct ThresholdKeyring
{
public Crypto.TPKE.PrivateKey TpkePrivateKey;
public Crypto.TPKE.PublicKey TpkePublicKey;
public List<Crypto.TPKE.PublicKey> TpkeVerificationPublicKeys;
public Crypto.ThresholdSignature.PublicKeySet ThresholdSignaturePublicKeySet;
public Crypto.ThresholdSignature.PrivateKeyShare ThresholdSignaturePrivateKey;

Expand Down
1 change: 1 addition & 0 deletions src/Lachain.Consensus/ThresholdKeygen/TrustlessKeygen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ public bool Finished()
{
TpkePrivateKey = new PrivateKey(secretKey, _myIdx),
TpkePublicKey = new PublicKey(pubKeys[0], Faulty),
TpkeVerificationPublicKeys = new List<PublicKey>(pubKeys.Skip(1).Select(x => new PublicKey(x, Faulty))),
ThresholdSignaturePrivateKey = new PrivateKeyShare(secretKey),
ThresholdSignaturePublicKeySet =
new PublicKeySet(pubKeys.Skip(1).Select(x => new Crypto.ThresholdSignature.PublicKey(x)), Faulty)
Expand Down
7 changes: 6 additions & 1 deletion src/Lachain.Core/Blockchain/Operations/BlockManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using Lachain.Core.Blockchain.SystemContracts.Utils;
using Lachain.Core.Blockchain.SystemContracts.Storage;
using Lachain.Core.Blockchain.Validators;
using Lachain.Utility.Serialization;


namespace Lachain.Core.Blockchain.Operations
Expand Down Expand Up @@ -748,15 +749,19 @@ public bool TryBuildGenesisBlock()
var genesisConfig = _configManager.GetConfig<GenesisConfig>("genesis");
if (genesisConfig is null) return false;
genesisConfig.ValidateOrThrow();
var fakeVerificationKeys = Enumerable.Range(0, genesisConfig.Validators.Count)
.Select(i => genesisConfig.ThresholdEncryptionPublicKey.HexToBytes())
.ToArray();
var initialConsensusState = new ConsensusState(
genesisConfig.ThresholdEncryptionPublicKey.HexToBytes(),
fakeVerificationKeys,
genesisConfig.Validators.Select(v => new ValidatorCredentials
(
v.EcdsaPublicKey.HexToBytes().ToPublicKey(),
v.ThresholdSignaturePublicKey.HexToBytes()
)).ToArray()
);
snapshot.Validators.SetConsensusState(initialConsensusState);
snapshot.Validators.SetConsensusState(initialConsensusState, false);

// stake delegation happens even before genesis block
// stake delegation means - some other address stakes for the validators
Expand Down
4 changes: 4 additions & 0 deletions src/Lachain.Core/Blockchain/Operations/TransactionExecuter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,14 @@ private OperatingError _InvokeContract(
{
if (receipt.GasUsed > transaction.GasLimit)
return OperatingError.OutOfGas;
Logger.LogDebug($"ContractInvoker.Invoke({addressTo.ToHex()}, conttext, {input.ToHex()})");
var result = ContractInvoker.Invoke(addressTo, context, input, transaction.GasLimit - receipt.GasUsed);
receipt.GasUsed += result.GasUsed;
if (result.Status != ExecutionStatus.Ok)
{
Logger.LogWarning($"Contract invoke failed, status is {result.Status}");
return OperatingError.ContractFailed;
}

if (receipt.GasUsed > transaction.GasLimit) return OperatingError.OutOfGas;
/* this OnSystemContractInvoked is useful for internal communication (for example - during keyGeneration) */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Lachain.Core.Blockchain.Interface;
using Lachain.Core.Blockchain.SystemContracts.ContractManager.Attributes;
using Lachain.Core.Blockchain.VM;
using Lachain.Logger;
using Lachain.Proto;
using Lachain.Utility;
using Lachain.Utility.Utils;
Expand All @@ -15,6 +16,9 @@ namespace Lachain.Core.Blockchain.SystemContracts.ContractManager
{
public class ContractRegisterer : IContractRegisterer
{
private static readonly ILogger<ContractRegisterer> Logger =
LoggerFactory.GetLoggerForClass<ContractRegisterer>();

private readonly ConcurrentDictionary<UInt160, Type> _contracts
= new ConcurrentDictionary<UInt160, Type>();

Expand Down Expand Up @@ -78,23 +82,38 @@ private void RegisterContract<T>(UInt160 address)

public SystemContractCall? DecodeContract(InvocationContext context, UInt160 address, byte[] input)
{
if (input.Length < 4) return null;
if (input.Length < 4)
{
Logger.LogWarning("Input too small");
return null;
}

if (!_contracts.TryGetValue(address, out var contract) ||
!_signatures.TryGetValue(address, out var signatures)
)
)
{
Logger.LogWarning("Failed to get signatures");
return null;
}

var signature = ContractEncoder.MethodSignatureAsInt(input);
if (!signatures.TryGetValue(signature, out var tuple))
{
Logger.LogWarning("Failed to get method info");
return null;
}

var (methodName, methodInfo) = tuple;
Logger.LogDebug($"Method {methodName}");
var decoder = new ContractDecoder(input);
var instance = Activator.CreateInstance(contract, context);
try
{
return new SystemContractCall(instance, methodInfo, decoder.Decode(methodName), address);
}
catch (Exception)
catch (Exception ex)
{
Logger.LogWarning($"Exception {ex} while call construction");
return null;
}
}
Expand Down
Loading

0 comments on commit cc26152

Please sign in to comment.