Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove tpke keys from state and wallet #301

Open
wants to merge 22 commits into
base: replace-tpke-keys-with-ts-keys
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/Lachain.Consensus/IPrivateConsensusKeySet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ namespace Lachain.Consensus
{
public interface IPrivateConsensusKeySet
{
Crypto.TPKE.PrivateKey TpkePrivateKey { get; }
Crypto.ThresholdSignature.PrivateKeyShare ThresholdSignaturePrivateKeyShare { get; }
EcdsaKeyPair EcdsaKeyPair { get; }
}
Expand Down
2 changes: 0 additions & 2 deletions src/Lachain.Consensus/IPublicConsensusKeySet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ public interface IPublicConsensusKeySet
{
int N { get; }
int F { get; }
PublicKey TpkePublicKey { get; }
PublicKeySet ThresholdSignaturePublicKeySet { get; }
IList<ECDSAPublicKey> EcdsaPublicKeySet { get; }
public int GetValidatorIndex(ECDSAPublicKey publicKey);
public PublicKey? GetTpkeVerificationKey(int playerIdx);
}
}
2 changes: 0 additions & 2 deletions src/Lachain.Consensus/PrivateConsensusKeySet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ public PrivateConsensusKeySet(
PrivateKeyShare thresholdSignaturePrivateKeyShare)
{
EcdsaKeyPair = ecdsaKeyPair;
TpkePrivateKey = tpkePrivateKey;
ThresholdSignaturePrivateKeyShare = thresholdSignaturePrivateKeyShare;
}

public PrivateKey TpkePrivateKey { get; }
public PrivateKeyShare ThresholdSignaturePrivateKeyShare { get; }
public EcdsaKeyPair EcdsaKeyPair { get; }
}
Expand Down
17 changes: 0 additions & 17 deletions src/Lachain.Consensus/PublicConsensusKeySet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,20 @@ public class PublicConsensusKeySet : IPublicConsensusKeySet
{
public int N { get; }
public int F { get; }
public PublicKey TpkePublicKey { get; }
public PublicKeySet ThresholdSignaturePublicKeySet { get; }
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
)
{
N = n;
F = f;
TpkePublicKey = tpkePublicKey;
ThresholdSignaturePublicKeySet = thresholdSignaturePublicKeySet;
_ecdsaPublicKeys = ecdsaPublicKeys.ToList();
_tpkeVerificationKeys = tpkeVerificationKeys.ToList();
}

public int GetValidatorIndex(ECDSAPublicKey publicKey)
Expand All @@ -43,16 +37,5 @@ public int GetValidatorIndex(ECDSAPublicKey publicKey)
.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
Expand Up @@ -8,15 +8,12 @@ namespace Lachain.Consensus.ThresholdKeygen.Data
{
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;

public UInt256 PublicPartHash()
{
return TpkePublicKey.ToBytes().Concat(ThresholdSignaturePublicKeySet.ToBytes()).Keccak();
return ThresholdSignaturePublicKeySet.ToBytes().Keccak();
}
}
}
11 changes: 8 additions & 3 deletions src/Lachain.Consensus/ThresholdKeygen/TrustlessKeygen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ public bool HandleConfirm(PublicKey tpkeKey, PublicKeySet tsKeys)
return _confirmations[keyringHash] == Players - Faulty;
}

public bool HandleConfirm(PublicKeySet tsKeys)
{
var keyringHash = tsKeys.ToBytes().Keccak();
_confirmations.PutIfAbsent(keyringHash, 0);
_confirmations[keyringHash] += 1;
return _confirmations[keyringHash] == Players - Faulty;
}

public bool Finished()
{
return _keyGenStates.Count(s => s.ValueCount() > 2 * Faulty) > Faulty;
Expand Down Expand Up @@ -170,9 +178,6 @@ public bool Finished()

return new ThresholdKeyring
{
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: 2 additions & 5 deletions src/Lachain.Console/TrustedKeygen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ public static void CloudKeygen(int n, int f, IEnumerable<string> ips, ushort bas
$"wallet{i + 1:D2}.json",
ecdsaPrivateKeys[i],
serializedHubPrivateKeys[i],
tpkeKeyGen.GetPrivKey(i).ToHex(),
privShares[i].ToHex(),
vault.Password
);
Expand Down Expand Up @@ -363,7 +362,6 @@ public static void LocalKeygen(int n, int f, int basePort, ushort target, ulong
$"wallet{i + 1:D2}.json",
ecdsaPrivateKeys[i],
serializedHubPrivateKeys[i],
tpkeKeyGen.GetPrivKey(i).ToHex(),
privShares[i].ToHex(),
vault.Password
);
Expand Down Expand Up @@ -393,12 +391,11 @@ public static void LocalKeygen(int n, int f, int basePort, ushort target, ulong
);
}

private static void GenWallet(string path, string ecdsaKey, string hubKey, string tpkeKey, string tsKey, string password)
private static void GenWallet(string path, string ecdsaKey, string hubKey, string tsKey, string password)
{
var config = new JsonWallet(
var config = new NewJsonWallet(
ecdsaKey,
hubKey,
new Dictionary<ulong, string> { { 0, tpkeKey } },
new Dictionary<ulong, string> { { 0, tsKey } }
);
var json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(config));
Expand Down
1 change: 1 addition & 0 deletions src/Lachain.Core/Blockchain/Hardfork/HardforkConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ public class HardforkConfig
[JsonProperty("hardfork_12")] public ulong? Hardfork_12 { get; set; }
[JsonProperty("hardfork_13")] public ulong? Hardfork_13 { get; set; }
[JsonProperty("hardfork_14")] public ulong? Hardfork_14 { get; set; }
[JsonProperty("hardfork_15")] public ulong? Hardfork_15 { get; set; }
}
}
10 changes: 10 additions & 0 deletions src/Lachain.Core/Blockchain/Hardfork/HardforkHeights.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static class HardforkHeights
private static ulong Hardfork_12;
private static ulong Hardfork_13;
private static ulong Hardfork_14;
private static ulong Hardfork_15;

//we need this value as default deploy height
public static ulong GetHardfork_3()
Expand Down Expand Up @@ -96,6 +97,11 @@ public static bool IsHardfork_14Active(ulong height)
{
return height >= Hardfork_14;
}

public static bool IsHardfork_15Active(ulong height)
{
return height >= Hardfork_15;
}

public static void SetHardforkHeights(HardforkConfig hardforkConfig)
{
Expand Down Expand Up @@ -159,6 +165,10 @@ public static void SetHardforkHeights(HardforkConfig hardforkConfig)
if(hardforkConfig.Hardfork_14 is null)
throw new Exception("hardfork_14 is null");
Hardfork_14 = (ulong) hardforkConfig.Hardfork_14;

if(hardforkConfig.Hardfork_15 is null)
throw new Exception("hardfork_15 is null");
Hardfork_15 = (ulong) hardforkConfig.Hardfork_15;
}
}
}
2 changes: 1 addition & 1 deletion src/Lachain.Core/Blockchain/Operations/BlockManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ public bool TryBuildGenesisBlock()
v.ThresholdSignaturePublicKey.HexToBytes()
)).ToArray()
);
snapshot.Validators.SetConsensusState(initialConsensusState, false);
snapshot.Validators.SetConsensusState(initialConsensusState, ConsensusStateStatus.OldState);

// stake delegation happens even before genesis block
// stake delegation means - some other address stakes for the validators
Expand Down
154 changes: 139 additions & 15 deletions src/Lachain.Core/Blockchain/SystemContracts/GovernanceContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,67 @@ public ExecutionStatus KeyGenConfirmWithVerification(UInt256 cycle, byte[] tpkeP
return ExecutionStatus.Ok;
}

[ContractMethod(GovernanceInterface.MethodKeygenConfirmWithOnlyTS)]
public ExecutionStatus KeygenConfirmWithOnlyTS(UInt256 cycle, byte[][] thresholdSignaturePublicKeys, SystemContractExecutionFrame frame)
{
Logger.LogDebug(
$"KeygenConfirmWithOnlyTS([{string.Join(", ", thresholdSignaturePublicKeys.Select(s => s.ToHex()))}])");
if (cycle.ToBigInteger() != GetConsensusGeneration(frame))
{
Logger.LogWarning($"Invalid cycle: {cycle}, now is {GetConsensusGeneration(frame)}");
return ExecutionStatus.Ok;
}

frame.ReturnValue = new byte[] { };
frame.UseGas(GasMetering.KeygenConfirmCost);

var senderPubKey = _context.Receipt.RecoverPublicKey(
HardforkHeights.IsHardfork_9Active(_context.Snapshot.Blocks.GetTotalBlockHeight())
);
var nextValidators = _nextValidators.Get()
.Batch(CryptoUtils.PublicKeyLength)
.Select(x => x.ToArray().ToPublicKey())
.ToArray();
if (!nextValidators.Contains(senderPubKey))
{
Logger.LogDebug($"non validator (public key: {senderPubKey.ToHex()}) sent MethodKeygenConfirmWithOnlyTS tx");
return ExecutionStatus.ExecutionHalted;
}

var players = thresholdSignaturePublicKeys.Length;
var faulty = (players - 1) / 3;

UInt256 keyringHash;
PublicKeySet tsKeys;
try
{
tsKeys = new PublicKeySet(
thresholdSignaturePublicKeys.Select(x => Lachain.Crypto.ThresholdSignature.PublicKey.FromBytes(x)),
faulty
);
keyringHash = tsKeys.ToBytes().Keccak();
}
catch
{
Logger.LogError("GovernanceContract is halted in KeyGenConfirm");
return ExecutionStatus.ExecutionHalted;
}

var gen = GetConsensusGeneration(frame);
var votes = GetConfirmations(keyringHash.ToBytes(), gen);
SetConfirmations(keyringHash.ToBytes(), gen, votes + 1);

Logger.LogDebug($"KeygenConfirmWithOnlyTS: {votes + 1} collected for this keyset");
if (votes + 1 != players - faulty) return ExecutionStatus.Ok;
Logger.LogDebug($"KeygenConfirmWithOnlyTS: succeeded since collected {votes + 1} votes");
_lastSuccessfulKeygenBlock.Set(new BigInteger(frame.InvocationContext.Receipt.Block).ToUInt256().ToBytes());
SetPlayersCount(players);
SetTSKeys(tsKeys);

Emit(GovernanceInterface.EventKeygenConfirmWithOnlyTS, thresholdSignaturePublicKeys);
return ExecutionStatus.Ok;
}

[ContractMethod(GovernanceInterface.MethodFinishCycle)]
public ExecutionStatus FinishCycle(UInt256 cycle, SystemContractExecutionFrame frame)
{
Expand All @@ -399,6 +460,33 @@ public ExecutionStatus FinishCycle(UInt256 cycle, SystemContractExecutionFrame f
return ExecutionStatus.ExecutionHalted;
}

ExecutionStatus validatorsUpdated;
if (HardforkHeights.IsHardfork_15Active(currentBlock))
validatorsUpdated = UpdateValidatorsV2(frame);
else
validatorsUpdated = UpdateValidatorsV1(frame);
if (validatorsUpdated != ExecutionStatus.Ok)
return validatorsUpdated;

var balanceOfExecutionResult = Hepler.CallSystemContract(frame,
ContractRegisterer.LatokenContract, ContractRegisterer.GovernanceContract,
Lrc20Interface.MethodBalanceOf,
ContractRegisterer.GovernanceContract);

if (balanceOfExecutionResult.Status != ExecutionStatus.Ok)
{
Logger.LogError("GovernanceContract is halted in FinishCycle");
return ExecutionStatus.ExecutionHalted;
}

var txFeesAmount = balanceOfExecutionResult.ReturnValue!.ToUInt256().ToMoney();
SetCollectedFees(txFeesAmount);
ClearPlayersCount();
return ExecutionStatus.Ok;
}

private ExecutionStatus UpdateValidatorsV1(SystemContractExecutionFrame frame)
{
var players = GetPlayersCount();
var gen = GetConsensusGeneration(frame) - 1;
if (players != null)
Expand All @@ -412,7 +500,8 @@ public ExecutionStatus FinishCycle(UInt256 cycle, SystemContractExecutionFrame f
if (votes + 1 < players - faulty)
{
Logger.LogError(
$"GovernanceContract is halted in FinishCycle, collected {votes} votes, need {players - faulty - 1}");
$"GovernanceContract is halted in FinishCycle, collected {votes} votes, need {players - faulty - 1}"
);
return ExecutionStatus.ExecutionHalted;
}

Expand All @@ -431,8 +520,14 @@ public ExecutionStatus FinishCycle(UInt256 cycle, SystemContractExecutionFrame f
Logger.LogWarning(k.ToHex());
}

_context.Snapshot.Validators.UpdateValidators(ecdsaPublicKeys, tsKeys, tpkeKey, tpkeVerificationKeys,
HardforkHeights.IsHardfork_12Active(currentBlock));
if (HardforkHeights.IsHardfork_12Active(frame.InvocationContext.Receipt.Block))
_context.Snapshot.Validators.UpdateValidators(
ecdsaPublicKeys, tsKeys, tpkeKey, tpkeVerificationKeys, ConsensusStateStatus.StateWithTpkeVerification
);
else
_context.Snapshot.Validators.UpdateValidators(
ecdsaPublicKeys, tsKeys, tpkeKey, tpkeVerificationKeys, ConsensusStateStatus.OldState
);

Emit(GovernanceInterface.EventFinishCycle);
Logger.LogDebug("Enough confirmations collected, validators will be changed in the next block");
Expand All @@ -441,21 +536,50 @@ public ExecutionStatus FinishCycle(UInt256 cycle, SystemContractExecutionFrame f
Logger.LogDebug($" - TS public keys: {string.Join(", ", tsKeys.Keys.Select(key => key.ToHex()))}");
Logger.LogDebug($" - TPKE public key: {tpkeKey.ToHex()}");
}
return ExecutionStatus.Ok;
}

var balanceOfExecutionResult = Hepler.CallSystemContract(frame,
ContractRegisterer.LatokenContract, ContractRegisterer.GovernanceContract,
Lrc20Interface.MethodBalanceOf,
ContractRegisterer.GovernanceContract);

if (balanceOfExecutionResult.Status != ExecutionStatus.Ok)
private ExecutionStatus UpdateValidatorsV2(SystemContractExecutionFrame frame)
{
var players = GetPlayersCount();
var gen = GetConsensusGeneration(frame) - 1;
if (players != null)
{
Logger.LogError("GovernanceContract is halted in FinishCycle");
return ExecutionStatus.ExecutionHalted;
}
var faulty = (players - 1) / 3;
var tsKeys = GetTSKeys();
var keyringHash = tsKeys.ToBytes().Keccak();
var votes = GetConfirmations(keyringHash.ToBytes(), gen);
if (votes + 1 < players - faulty)
{
Logger.LogError(
$"GovernanceContract is halted in FinishCycle, collected {votes} votes, need {players - faulty - 1}"
);
return ExecutionStatus.ExecutionHalted;
}

var txFeesAmount = balanceOfExecutionResult.ReturnValue!.ToUInt256().ToMoney();
SetCollectedFees(txFeesAmount);
ClearPlayersCount();
var ecdsaPublicKeys = _nextValidators.Get()
.Batch(CryptoUtils.PublicKeyLength)
.Select(x => x.ToArray().ToPublicKey())
.ToArray();

foreach (var k in ecdsaPublicKeys)
{
Logger.LogWarning(k.ToHex());
}

foreach (var k in tsKeys.Keys)
{
Logger.LogWarning(k.ToHex());
}

_context.Snapshot.Validators.UpdateValidators(ecdsaPublicKeys, tsKeys);

Emit(GovernanceInterface.EventFinishCycle);
Logger.LogDebug("Enough confirmations collected, validators will be changed in the next block");
Logger.LogDebug(
$" - ECDSA public keys: {string.Join(", ", ecdsaPublicKeys.Select(key => key.ToHex()))}");
Logger.LogDebug($" - TS public keys: {string.Join(", ", tsKeys.Keys.Select(key => key.ToHex()))}");
}
return ExecutionStatus.Ok;
}

Expand Down
Loading