Skip to content

Commit

Permalink
Provide richer data for the TipChanged event
Browse files Browse the repository at this point in the history
  • Loading branch information
dahlia committed Sep 23, 2019
1 parent 6cf0c16 commit 8be5806
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 14 deletions.
7 changes: 5 additions & 2 deletions CHANGES.md
Expand Up @@ -69,8 +69,10 @@ To be released.

### Added interfaces

- Added `BlockChain<T>.TipChanged` event handler which invoked with argument
of `long` typed tip index when `BlockChain<T>.Tip` is changed. [[#517]]
- Added `BlockChain<T>.TipChanged` event which is invoked with an argument
of `BlockChain<T>.TipChangedEventArgs` when `BlockChain<T>.Tip` is changed.
[[#517], [#526]]
- Added `BlockChain<T>.TipChangedEventArgs` class. [[#526]]
- Added `Swarm<T>.PrepareAsync()` method. The method should be called before
calling `Swarm<T>.BootstrapAsync()`, `Swarm<T>.PreloadAsync()` and
`Swarm<T>.StartAsync()`. [[#353]]
Expand Down Expand Up @@ -145,6 +147,7 @@ To be released.
[#520]: https://github.com/planetarium/libplanet/pull/520
[#521]: https://github.com/planetarium/libplanet/pull/521
[#522]: https://github.com/planetarium/libplanet/pull/522
[#526]: https://github.com/planetarium/libplanet/pull/526
[Kademlia]: https://en.wikipedia.org/wiki/Kademlia
[Guid]: https://docs.microsoft.com/ko-kr/dotnet/api/system.guid?view=netframework-4.8
[RFC 4122]: https://tools.ietf.org/html/rfc4122
Expand Down
35 changes: 27 additions & 8 deletions Libplanet.Tests/Blockchain/BlockChainTest.cs
Expand Up @@ -1570,20 +1570,30 @@ void BuildIndex(Guid id, Block<DumbAction> block)
private async void TipChanged()
{
bool called = false;
long tip = -1;
long? prevTipIndex = null;
HashDigest<SHA256>? prevTipHash = null;
long tipIndex = -1;
HashDigest<SHA256> tipHash;

void TipChangedHandler(object target, long tipIndex)
void TipChangedHandler(object target, BlockChain<DumbAction>.TipChangedEventArgs args)
{
called = true;
tip = tipIndex;
prevTipIndex = args.PreviousIndex;
prevTipHash = args.PreviousHash;
tipIndex = args.Index;
tipHash = args.Hash;
}

_blockChain.TipChanged += TipChangedHandler;
// Mine block
called = false;
Block<DumbAction> block = await _blockChain.MineBlock(_fx.Address1);
Assert.True(called);
Assert.Equal(0, tip);
Assert.Null(prevTipHash);
Assert.Null(prevTipIndex);
Assert.Equal(block.Hash, tipHash);
Assert.Equal(0, tipIndex);
Assert.Equal(block.Hash, tipHash);
called = false;
Assert.Throws<InvalidBlockIndexException>(() => _blockChain.Append(block));
Assert.False(called);
Expand All @@ -1608,11 +1618,17 @@ private async void AbortMining()
chain2.Append(genesis);

bool called = false;
long tip = -1;
void TipChangedHandler(object target, long tipIndex)
long? prevTipIndex = null;
HashDigest<SHA256>? prevTipHash = null;
long tipIndex = -1;
HashDigest<SHA256> tipHash;
void TipChangedHandler(object target, BlockChain<DumbAction>.TipChangedEventArgs args)
{
called = true;
tip = tipIndex;
prevTipIndex = args.PreviousIndex;
prevTipHash = args.PreviousHash;
tipIndex = args.Index;
tipHash = args.Hash;
}

try
Expand All @@ -1624,7 +1640,10 @@ void TipChangedHandler(object target, long tipIndex)

chain2.Append(block);
Assert.True(called);
Assert.Equal(1, tip);
Assert.Equal(0, prevTipIndex);
Assert.Equal(genesis.Hash, prevTipHash);
Assert.Equal(1, tipIndex);
Assert.Equal(block.Hash, tipHash);
await Task.Delay(100);
Assert.True(miningTask.IsCanceled);
}
Expand Down
58 changes: 54 additions & 4 deletions Libplanet/Blockchain/BlockChain.cs
Expand Up @@ -60,10 +60,17 @@ internal BlockChain(IBlockPolicy<T> policy, IStore store, Guid id)
_rwlock?.Dispose();
}

public event EventHandler<long> TipChanged;
/// <summary>
/// An event which is invoked when <see cref="Tip"/> is changed.
/// </summary>
public event EventHandler<TipChangedEventArgs> TipChanged;

public IBlockPolicy<T> Policy { get; }

/// <summary>
/// The topmost <see cref="Block{T}"/> of the current blockchain.
/// Can be <c>null</c> if the blockchain is empty.
/// </summary>
public Block<T> Tip
{
get
Expand Down Expand Up @@ -485,7 +492,7 @@ public long GetNextTxNonce(Address address)
CancellationTokenSource cancellationTokenSource =
CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cts.Token);

void WatchTip(object target, long tipIndex)
void WatchTip(object target, TipChangedEventArgs args)
{
cts.Cancel();
}
Expand Down Expand Up @@ -621,14 +628,22 @@ bool renderActions
_rwlock.EnterWriteLock();
try
{
Block<T> prevTip = Tip;
Blocks[block.Hash] = block;
foreach (KeyValuePair<Address, long> pair in nonceDeltas)
{
Store.IncreaseTxNonce(Id, pair.Key, pair.Value);
}

Store.AppendIndex(Id, block.Hash);
TipChanged?.Invoke(this, block.Index);
var tipChangedEventArgs = new TipChangedEventArgs
{
PreviousIndex = prevTip?.Index,
PreviousHash = prevTip?.Hash,
Index = block.Index,
Hash = block.Hash,
};
TipChanged?.Invoke(this, tipChangedEventArgs);
ISet<TxId> txIds = block.Transactions
.Select(t => t.Id)
.ToImmutableHashSet();
Expand Down Expand Up @@ -1005,11 +1020,18 @@ internal void Swap(BlockChain<T> other, bool render)
{
_rwlock.EnterWriteLock();

var tipChangedEventArgs = new TipChangedEventArgs
{
PreviousHash = Tip?.Hash,
PreviousIndex = Tip?.Index,
Hash = other.Tip.Hash,
Index = other.Tip.Index,
};
Guid obsoleteId = Id;
Id = other.Id;
Store.SetCanonicalChainId(Id);
Blocks = new BlockSet<T>(Store);
TipChanged?.Invoke(this, Blocks.Count);
TipChanged?.Invoke(this, tipChangedEventArgs);
Transactions = new TransactionSet<T>(Store);
Store.DeleteChainId(obsoleteId);
}
Expand Down Expand Up @@ -1096,5 +1118,33 @@ bool buildStateReferences
Store.StoreStateReference(Id, updatedAddresses, block.Hash, block.Index);
}
}

/// <summary>
/// Provides data for the <see cref="TipChanged"/> event.
/// </summary>
public class TipChangedEventArgs : EventArgs
{
/// <summary>
/// The <see cref="Block{T}.Index"/> of <see cref="Tip"/> <em>before</em> changed.
/// Can be <c>null</c> if the blockchain was empty before.
/// </summary>
public long? PreviousIndex { get; set; }

/// <summary>
/// The <see cref="Block{T}.Hash"/> of <see cref="Tip"/> <em>before</em> changed.
/// Can be <c>null</c> if the blockchain was empty before.
/// </summary>
public HashDigest<SHA256>? PreviousHash { get; set; }

/// <summary>
/// The <see cref="Block{T}.Index"/> of <see cref="Tip"/> <em>after</em> changed.
/// </summary>
public long Index { get; set; }

/// <summary>
/// The <see cref="Block{T}.Hash"/> of <see cref="Tip"/> <em>after</em> changed.
/// </summary>
public HashDigest<SHA256> Hash { get; set; }
}
}
}

0 comments on commit 8be5806

Please sign in to comment.