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

Make Swarm<T>.RefreshTableAsync config constants configurable and change structure of PeerState #1215

Merged
merged 6 commits into from
Mar 26, 2021
Merged
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
18 changes: 15 additions & 3 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@ To be released.
- Removed `Swarm<T>.GetTrustedStateCompleterAsync()` method. [[#1117]]
- Removed `trustedStateValidators` parameter from `Swarm<T>.PreloadAsync()`
method. [[#1117]]
- Removed `Swarm<T>.TraceTable()` method. [[#1120]]
- Added `IActionContext.BlockAction` property. [[#1143]]
- Added nullable `TimeSpan`-typed `messageLifespan` parameter into
`NetMQTransport()` constructor. [[#1171]]
- Added `IStore.ForkTxNonces()` method. [[#1198]]

- Removed `PeerState.Address` Property. [[#1215]]
- `IProtocol.RebuildConnectionAsync(CancellationToken)` method was
replaced by, `IProtocol.RebuildConnectionAsync(int, CancellationToken)`
method. [[#1215]]

### Backward-incompatible network protocol changes

Expand Down Expand Up @@ -135,7 +139,6 @@ To be released.
class. [[#1119]]
- Added `InvalidBlockProtocolVersionException` class. [[#1142], [#1147]]
- Added `InvalidBlockTxHashException` class. [[#1116]]
- Removed `Swarm<T>.TraceTable()` method. [[#1120]]
- Added `Swarm<T>.PeerStates` property. [[#1120]]
- Added `IProtocol` interface. [[#1120]]
- Added `KademliaProtocol` class which implements `IProtocol`.
Expand All @@ -147,6 +150,11 @@ To be released.
to `Transaction<T>.Deserialize()`. [[#1149]]
- Added `SwarmOptions.MessageLifespan` property. [[#1171]]
- Added `InvalidTimestampException` class. [[#1171]]
- Added `PeerState.Peer` Property. [[#1215]]
- Added `SwarmOptions.RefreshPeriod` property,
which is 10 seconds by default. [[#1215]]
- Added `SwarmOptions.RefreshLifespan` property,
which is 60 seconds by default. [[#1215]]

### Behavioral changes

Expand Down Expand Up @@ -188,6 +196,9 @@ To be released.
`Swarm<T>.BootstrapAsync()` before `Swarm<T>.StartAsync()`,
peers in your table may not have you in their table right after
`Swarm<T>.StartAsync()` (which was almost guaranteed before). [[#1208]]
- Peers added during `Swarm<T>.BootstrapAsync()` before
`Swarm<T>.StartAsync()` are now marked as stale so that
`Swarm<T>.RefreshTableAsync()` will update. [[#1215]]
- Following classes became to leave log messages with its class as logging
context. [[#1218]]
- `TrieStateStore` class
Expand Down Expand Up @@ -284,6 +295,7 @@ To be released.
[#1204]: https://github.com/planetarium/libplanet/pull/1204
[#1208]: https://github.com/planetarium/libplanet/pull/1208
[#1212]: https://github.com/planetarium/libplanet/pull/1212
[#1215]: https://github.com/planetarium/libplanet/pull/1215
[#1218]: https://github.com/planetarium/libplanet/pull/1218


Expand All @@ -294,7 +306,7 @@ Version 0.10.3
Released on January 28, 2021.

- `BlockChain<T>.MineBlock()` became to unstage transactions that have lower
nonce than exepcted. [[#1174]]
nonce than expected. [[#1174]]

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

Expand Down
4 changes: 2 additions & 2 deletions Libplanet.Tests/Net/Protocols/TestTransport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ public TestTransport(

public DateTimeOffset? LastMessageTimestamp { get; private set; }

public bool Running => !(_swarmCancellationTokenSource is null);

internal ConcurrentBag<Message> ReceivedMessages { get; }

internal RoutingTable Table { get; }

internal IProtocol Protocol { get; }

internal bool Running => !(_swarmCancellationTokenSource is null);

public void Dispose()
{
}
Expand Down
21 changes: 21 additions & 0 deletions Libplanet.Tests/Net/SwarmTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,17 +237,38 @@ public async Task BootstrapAsyncWithoutStart()
Swarm<DumbAction> swarmA = CreateSwarm();
Swarm<DumbAction> swarmB = CreateSwarm();
Swarm<DumbAction> swarmC = CreateSwarm();
Swarm<DumbAction> swarmD = CreateSwarm();

try
{
await StartAsync(swarmA);
await StartAsync(swarmB);
await StartAsync(swarmD);

var bootstrappedAt = DateTimeOffset.UtcNow;
swarmC.RoutingTable.AddPeer((BoundPeer)swarmD.AsPeer);
await BootstrapAsync(swarmB, swarmA.AsPeer);
await BootstrapAsync(swarmC, swarmA.AsPeer);

Assert.Contains(swarmB.AsPeer, swarmC.Peers);
Assert.DoesNotContain(swarmC.AsPeer, swarmB.Peers);
foreach (PeerState state in swarmB.PeersStates)
{
Assert.InRange(state.LastUpdated, bootstrappedAt, DateTimeOffset.UtcNow);
}

foreach (PeerState state in swarmC.PeersStates)
{
if (state.Peer.Address == swarmD.AsPeer.Address)
{
// Peers added before bootstrap should not be marked as stale.
Assert.InRange(state.LastUpdated, bootstrappedAt, DateTimeOffset.UtcNow);
}
else
{
Assert.Equal(DateTimeOffset.MinValue, state.LastUpdated);
}
}
}
finally
{
Expand Down
7 changes: 7 additions & 0 deletions Libplanet/Net/ITransport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ public interface ITransport : IDisposable
[Pure]
DateTimeOffset? LastMessageTimestamp { get; }

/// <summary>
/// Whether this <see cref="ITransport"/> instance is running.
/// </summary>
/// <value>Gets the value indicates whether the instance is running.</value>
[Pure]
bool Running { get; }

/// <summary>
/// Initiates transport layer.
/// </summary>
Expand Down
5 changes: 1 addition & 4 deletions Libplanet/Net/NetMQTransport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,7 @@ public NetMQTransport(
/// <inheritdoc cref="ITransport.LastMessageTimestamp"/>
public DateTimeOffset? LastMessageTimestamp { get; private set; }

/// <summary>
/// Whether this <see cref="NetMQTransport"/> instance is running.
/// </summary>
/// <returns>Boolean value indicates whether the instance is running.</returns>
/// <inheritdoc cref="ITransport.Running"/>
public bool Running
{
get => _runningEvent.Task.Status == TaskStatus.RanToCompletion;
Expand Down
6 changes: 2 additions & 4 deletions Libplanet/Net/PeerState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ internal PeerState(BoundPeer peer, DateTimeOffset lastUpdated)
}

/// <summary>
/// <see cref="Address"/> of peer.
/// <see cref="BoundPeer"/> of the state.
/// </summary>
public Address Address => Peer.Address;
public BoundPeer Peer { get; set; }

/// <summary>
/// Last time messages were exchanged.
Expand All @@ -34,7 +34,5 @@ internal PeerState(BoundPeer peer, DateTimeOffset lastUpdated)
/// Delay of verification in milliseconds.
/// </summary>
public TimeSpan? Latency { get; internal set; }

internal BoundPeer Peer { get; set; }
}
}
3 changes: 2 additions & 1 deletion Libplanet/Net/Protocols/IProtocol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,11 @@ Task AddPeersAsync(
/// <summary>
/// Reconstructs network connection between peers on network.
/// </summary>
/// <param name="depth">Recursive operation depth to search peers from network.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification
/// that this operation should be canceled.</param>
/// <returns>An awaitable task without value.</returns>
Task RebuildConnectionAsync(CancellationToken cancellationToken);
Task RebuildConnectionAsync(int depth, CancellationToken cancellationToken);

/// <summary>
/// Checks the <see cref="KBucket"/> in the <see cref="RoutingTable"/> and if
Expand Down
6 changes: 3 additions & 3 deletions Libplanet/Net/Protocols/KademliaProtocol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ public async Task CheckAllPeersAsync(TimeSpan? timeout, CancellationToken cancel
}

/// <inheritdoc />
public async Task RebuildConnectionAsync(CancellationToken cancellationToken)
public async Task RebuildConnectionAsync(int depth, CancellationToken cancellationToken)
{
_logger.Verbose("Rebuilding connection...");
var buffer = new byte[20];
Expand All @@ -259,7 +259,7 @@ public async Task RebuildConnectionAsync(CancellationToken cancellationToken)
new ConcurrentBag<BoundPeer>(),
new Address(buffer),
null,
-1,
depth,
_requestTimeout,
cancellationToken));
}
Expand All @@ -269,7 +269,7 @@ public async Task RebuildConnectionAsync(CancellationToken cancellationToken)
new ConcurrentBag<BoundPeer>(),
_address,
null,
Kademlia.MaxDepth,
depth,
_requestTimeout,
cancellationToken));
try
Expand Down
21 changes: 17 additions & 4 deletions Libplanet/Net/Swarm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,8 @@ public async Task StartAsync(
{
tasks.Add(
RefreshTableAsync(
TimeSpan.FromSeconds(10),
TimeSpan.FromSeconds(10),
Options.RefreshPeriod,
Options.RefreshLifespan,
_cancellationToken));
tasks.Add(RebuildConnectionAsync(TimeSpan.FromMinutes(30), _cancellationToken));
tasks.Add(Transport.RunAsync(_cancellationToken));
Expand Down Expand Up @@ -435,13 +435,24 @@ public async Task BootstrapAsync(
}

IEnumerable<BoundPeer> peers = seedPeers.OfType<BoundPeer>();
IEnumerable<BoundPeer> peersBeforeBootstrap = RoutingTable.Peers;

await PeerDiscovery.BootstrapAsync(
peers,
pingSeedTimeout,
findNeighborsTimeout,
depth,
cancellationToken);

if (!Transport.Running)
{
// Mark added peers as stale if bootstrap is called before transport is running
// FIXME: Peers added before bootstrap might be updated.
foreach (BoundPeer peer in RoutingTable.Peers.Except(peersBeforeBootstrap))
{
RoutingTable.AddPeer(peer, DateTimeOffset.MinValue);
}
}
}

public void BroadcastBlock(Block<T> block)
Expand Down Expand Up @@ -1941,9 +1952,9 @@ private async Task RefreshTableAsync(
{
try
{
await Task.Delay(period, cancellationToken);
await PeerDiscovery.RefreshTableAsync(maxAge, cancellationToken);
await PeerDiscovery.CheckReplacementCacheAsync(cancellationToken);
await Task.Delay(period, cancellationToken);
}
catch (OperationCanceledException e)
{
Expand All @@ -1968,7 +1979,9 @@ private async Task RebuildConnectionAsync(
try
{
await Task.Delay(period, cancellationToken);
await PeerDiscovery.RebuildConnectionAsync(cancellationToken);
await PeerDiscovery.RebuildConnectionAsync(
Kademlia.MaxDepth,
cancellationToken);
}
catch (OperationCanceledException e)
{
Expand Down
12 changes: 12 additions & 0 deletions Libplanet/Net/SwarmOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Threading;
using Libplanet.Blocks;
using Libplanet.Net.Messages;
using Libplanet.Net.Protocols;
using Libplanet.Tx;

namespace Libplanet.Net
Expand Down Expand Up @@ -47,5 +48,16 @@ public class SwarmOptions
/// The lifespan of <see cref="Message"/>.
/// </summary>
public TimeSpan? MessageLifespan { get; set; } = null;

/// <summary>
/// The frequency of <see cref="IProtocol.RefreshTableAsync" />.
/// </summary>
public TimeSpan RefreshPeriod { get; set; } = TimeSpan.FromSeconds(10);

/// <summary>
/// The lifespan of <see cref="Peer"/> in routing table.
/// <seealso cref="IProtocol.RefreshTableAsync" />
/// </summary>
public TimeSpan RefreshLifespan { get; set; } = TimeSpan.FromSeconds(60);
}
}