diff --git a/CHANGES.md b/CHANGES.md index 921d84409b..2884ad5140 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -103,6 +103,8 @@ To be released. - Added `StateCompleterSet` struct. - Added `StateCompleters` static class. - Added `FungibleAssetStateCompleters` static class. + - Added `Reorged` event on `BlockChain`. [[#945]] + - Added `ReorgedEventArgs` class. [[#945]] ### Behavioral changes @@ -192,6 +194,7 @@ To be released. [#936]: https://github.com/planetarium/libplanet/pull/936 [#940]: https://github.com/planetarium/libplanet/pull/940 [#941]: https://github.com/planetarium/libplanet/pull/941 +[#945]: https://github.com/planetarium/libplanet/pull/945 [sleep mode]: https://en.wikipedia.org/wiki/Sleep_mode diff --git a/Libplanet.Tests/Blockchain/BlockChainTest.cs b/Libplanet.Tests/Blockchain/BlockChainTest.cs index 5d4a0c1de8..863f025158 100644 --- a/Libplanet.Tests/Blockchain/BlockChainTest.cs +++ b/Libplanet.Tests/Blockchain/BlockChainTest.cs @@ -2173,6 +2173,43 @@ void TipChangedHandler(object target, BlockChain.TipChangedEventArgs // TODO: Add test cases for swap } + [Fact] + private async void Reorged() + { + Block actualOldTip = null; + Block actualNewTip = null; + Block actualBranchpoint = null; + int callCount = 0; + + _blockChain.Reorged += (target, args) => + { + actualOldTip = args.OldTip; + actualNewTip = args.NewTip; + actualBranchpoint = args.Branchpoint; + callCount += 1; + }; + var branchpoint = _blockChain.Tip; + var fork = _blockChain.Fork(_blockChain.Tip.Hash); + await fork.MineBlock(_fx.Address1); + await fork.MineBlock(_fx.Address2); + await _blockChain.MineBlock(_fx.Address3); + + var oldTip = _blockChain.Tip; + var newTip = fork.Tip; + + Assert.Null(actualOldTip); + Assert.Null(actualNewTip); + Assert.Null(actualBranchpoint); + Assert.Equal(0, callCount); + + _blockChain.Swap(fork, false); + + Assert.Equal(oldTip.Hash, actualOldTip.Hash); + Assert.Equal(newTip.Hash, actualNewTip.Hash); + Assert.Equal(branchpoint.Hash, actualBranchpoint.Hash); + Assert.Equal(1, callCount); + } + [Fact] private async void AbortMining() { diff --git a/Libplanet/Blockchain/BlockChain.cs b/Libplanet/Blockchain/BlockChain.cs index e1862573fa..30cf9d1e90 100644 --- a/Libplanet/Blockchain/BlockChain.cs +++ b/Libplanet/Blockchain/BlockChain.cs @@ -176,6 +176,11 @@ bool render /// public event EventHandler TipChanged; + /// + /// An event which is invoked when the chain is reorged. + /// + public event EventHandler Reorged; + public IBlockPolicy Policy { get; } /// @@ -1344,11 +1349,20 @@ IEnumerable GetTxIdsWithRange(BlockChain chain, Block start, Block(Store); TipChanged?.Invoke(this, tipChangedEventArgs); + Reorged?.Invoke(this, reorgedEventArgs); _transactions = new TransactionSet(Store); Store.DeleteChainId(obsoleteId); } @@ -1624,5 +1638,26 @@ public class TipChangedEventArgs : EventArgs /// public HashDigest Hash { get; set; } } + + /// + /// Provides data for the event. + /// + public class ReorgedEventArgs : EventArgs + { + /// + /// The before the chain is reorged. + /// + public Block OldTip { get; set; } + + /// + /// The after the chain is reorged. + /// + public Block NewTip { get; set; } + + /// + /// The point of the chain branches off. + /// + public Block Branchpoint { get; set; } + } } }