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

Feature/delayed consensus #4008

Merged
merged 10 commits into from
Dec 13, 2024
20 changes: 19 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,31 @@ Version 5.4.2

To be released.

### Backward-incompatible API changes

- Removed `ContextTimeoutOption` class. Instead, added `ContextOption` class.
The unit of the time-related options in `ContextOption` is millisecond,
whereas `ContextTimeoutOption` was second. [[#4007]]
- Removed `ConsensusReactorOption.ContextTimeoutOptions` property.
Instead, added `ConsensusReactorOption.ContextOption` property. [[#4007]]
- `ConsensusReactor` constructor requires `ContextOption` parameter
instead of the `ContextTimeoutOption` parameter. [[#4007]]

### Behavioral changes

- `Gossip.RebuildTableAsync()` now bootstrap peers from the seed peers.
[[#4007]]


[#4007]: https://github.com/planetarium/libplanet/pull/4007


Version 5.4.1
-------------

Released on November 22, 2024.

- Ported changes from [Libplanet 5.3.2] release. [[#3973]]
- Ported changes from [Libplanet 5.3.2] release. [[#3973]]

[#3973]: https://github.com/planetarium/libplanet/pull/3973
[Libplanet 5.3.2]: https://www.nuget.org/packages/Libplanet/5.3.2
Expand Down
12 changes: 6 additions & 6 deletions src/Libplanet.Net/Consensus/ConsensusContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace Libplanet.Net.Consensus
public partial class ConsensusContext : IDisposable
{
private readonly object _contextLock;
private readonly ContextTimeoutOption _contextTimeoutOption;
private readonly ContextOption _contextOption;
private readonly IConsensusMessageCommunicator _consensusMessageCommunicator;
private readonly BlockChain _blockChain;
private readonly PrivateKey _privateKey;
Expand All @@ -58,22 +58,22 @@ private readonly EvidenceExceptionCollector _evidenceCollector
/// <param name="newHeightDelay">A time delay in starting the consensus for the next height
/// block. <seealso cref="OnTipChanged"/>
/// </param>
/// <param name="contextTimeoutOption">A <see cref="ContextTimeoutOption"/> for
/// configuring a timeout for each <see cref="Step"/>.</param>
/// <param name="contextOption">A <see cref="ContextOption"/> for
/// configuring a timeout or delay for each <see cref="Step"/>.</param>
public ConsensusContext(
IConsensusMessageCommunicator consensusMessageCommunicator,
BlockChain blockChain,
PrivateKey privateKey,
TimeSpan newHeightDelay,
ContextTimeoutOption contextTimeoutOption)
ContextOption contextOption)
{
_consensusMessageCommunicator = consensusMessageCommunicator;
_blockChain = blockChain;
_privateKey = privateKey;
Running = false;
_newHeightDelay = newHeightDelay;

_contextTimeoutOption = contextTimeoutOption;
_contextOption = contextOption;
_currentContext = CreateContext(
_blockChain.Tip.Index + 1,
_blockChain.GetBlockCommit(_blockChain.Tip.Index));
Expand Down Expand Up @@ -498,7 +498,7 @@ private Context CreateContext(long height, BlockCommit? lastCommit)
lastCommit,
_privateKey,
validatorSet,
contextTimeoutOptions: _contextTimeoutOption);
contextOption: _contextOption);
return context;
}

Expand Down
6 changes: 3 additions & 3 deletions src/Libplanet.Net/Consensus/ConsensusReactor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class ConsensusReactor : IReactor
/// <param name="newHeightDelay">A time delay in starting the consensus for the next height
/// block.
/// </param>
/// <param name="contextTimeoutOption">A <see cref="ContextTimeoutOption"/> for
/// <param name="contextOption">A <see cref="ContextOption"/> for
/// configuring a timeout for each <see cref="ConsensusStep"/>.</param>
public ConsensusReactor(
ITransport consensusTransport,
Expand All @@ -52,7 +52,7 @@ public ConsensusReactor(
ImmutableList<BoundPeer> validatorPeers,
ImmutableList<BoundPeer> seedPeers,
TimeSpan newHeightDelay,
ContextTimeoutOption contextTimeoutOption)
ContextOption contextOption)
{
validatorPeers ??= ImmutableList<BoundPeer>.Empty;
seedPeers ??= ImmutableList<BoundPeer>.Empty;
Expand All @@ -71,7 +71,7 @@ public ConsensusReactor(
blockChain,
privateKey,
newHeightDelay,
contextTimeoutOption);
contextOption);

_logger = Log
.ForContext("Tag", "Consensus")
Expand Down
6 changes: 3 additions & 3 deletions src/Libplanet.Net/Consensus/ConsensusReactorOption.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace Libplanet.Net.Consensus
{
/// <summary>
/// A option struct for initializing <see cref="ConsensusReactor"/>.
/// An option struct for initializing <see cref="ConsensusReactor"/>.
/// </summary>
public struct ConsensusReactorOption
{
Expand Down Expand Up @@ -42,8 +42,8 @@ public struct ConsensusReactorOption
public TimeSpan TargetBlockInterval { get; set; }

/// <summary>
/// A timeout second and multiplier value for used in <see cref="Context"/>.
/// A timeout and delay value for used in <see cref="Context"/> in milliseconds.
/// </summary>
public ContextTimeoutOption ContextTimeoutOptions { get; set; }
public ContextOption ContextOption { get; set; }
}
}
56 changes: 56 additions & 0 deletions src/Libplanet.Net/Consensus/Context.Async.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,40 @@ private void AppendBlock(Block block)
_ = Task.Run(() => _blockChain.Append(block, GetBlockCommit()));
}

private async Task EnterPreCommitWait(int round, BlockHash hash)
{
if (!_preCommitWaitFlags.Add(round))
{
return;
}

if (_contextOption.EnterPreCommitDelay > 0)
{
await Task.Delay(
_contextOption.EnterPreCommitDelay,
_cancellationTokenSource.Token);
}

ProduceMutation(() => EnterPreCommit(round, hash));
}

private async Task EnterEndCommitWait(int round)
{
if (!_endCommitWaitFlags.Add(round))
{
return;
}

if (_contextOption.EnterEndCommitDelay > 0)
{
await Task.Delay(
_contextOption.EnterEndCommitDelay,
_cancellationTokenSource.Token);
}

ProduceMutation(() => EnterEndCommit(round));
}

/// <summary>
/// Schedules <see cref="ProcessTimeoutPropose"/> to be queued after
/// <see cref="TimeoutPropose"/> amount of time.
Expand All @@ -212,7 +246,18 @@ private async Task OnTimeoutPropose(int round)
/// <param name="round">A round that the timeout task is scheduled for.</param>
private async Task OnTimeoutPreVote(int round)
{
if (_preCommitTimeoutFlags.Contains(round) || !_preVoteTimeoutFlags.Add(round))
{
return;
}

TimeSpan timeout = TimeoutPreVote(round);
_logger.Debug(
"PreVote step in round {Round} is scheduled to be timed out after {Timeout} " +
"because 2/3+ PreVotes are collected for the round. (context: {Context})",
round,
timeout,
ToString());
await Task.Delay(timeout, _cancellationTokenSource.Token);
_logger.Information(
"TimeoutPreVote has occurred in {Timeout}. {Info}",
Expand All @@ -228,7 +273,18 @@ private async Task OnTimeoutPreVote(int round)
/// <param name="round">The round that the timeout task is scheduled for.</param>
private async Task OnTimeoutPreCommit(int round)
{
if (!_preCommitTimeoutFlags.Add(round))
{
return;
}

TimeSpan timeout = TimeoutPreCommit(round);
_logger.Debug(
"PreCommit step in round {Round} is scheduled to be timed out in {Timeout} " +
"because 2/3+ PreCommits are collected for the round. (context: {Context})",
round,
timeout,
ToString());
await Task.Delay(timeout, _cancellationTokenSource.Token);
_logger.Information(
"TimeoutPreCommit has occurred in {Timeout}. {Info}",
Expand Down
Loading
Loading