66using System . Threading . Tasks ;
77using Microsoft . Extensions . Logging ;
88using NBitcoin ;
9+ using Newtonsoft . Json ;
910using Stratis . Bitcoin . AsyncWork ;
1011using Stratis . Bitcoin . Configuration ;
1112using Stratis . Bitcoin . Configuration . Logging ;
@@ -37,6 +38,12 @@ public interface IPoAMiner : IDisposable
3738 {
3839 /// <summary>Starts mining loop.</summary>
3940 void InitializeMining ( ) ;
41+
42+ /// <summary>
43+ /// Returns mining statistics in the last amount of blocks equal to the federation size.
44+ /// </summary>
45+ /// <returns>Returns <c>true</c> if the miner produced a block in the last round and block producer hits.</returns>
46+ MiningStatisticsModel MiningStatistics { get ; }
4047 }
4148
4249 /// <inheritdoc cref="IPoAMiner"/>
@@ -75,6 +82,8 @@ public class PoAMiner : IPoAMiner
7582
7683 private readonly NodeSettings nodeSettings ;
7784
85+ private MiningStatisticsModel miningStatistics ;
86+
7887 private readonly IWalletManager walletManager ;
7988
8089 protected readonly VotingManager votingManager ;
@@ -422,7 +431,6 @@ private void AddComponentStats(StringBuilder log)
422431 log . AppendLine ( ) ;
423432 return ;
424433 }
425-
426434 ChainedHeader tip = this . consensusManager . Tip ;
427435 ChainedHeader currentHeader = tip ;
428436
@@ -441,14 +449,21 @@ private void AddComponentStats(StringBuilder log)
441449 if ( timeHeader < currentHeader . Header . Time )
442450 timeHeader += this . network . ConsensusOptions . TargetSpacingSeconds ;
443451
452+ var statistics = new MiningStatisticsModel ( ) ;
453+
444454 // Iterate mining slots.
445455 for ( int i = 0 ; i < maxDepth ; i ++ )
446456 {
447457 int headerSlot = ( int ) ( timeHeader / this . network . ConsensusOptions . TargetSpacingSeconds ) % modifiedFederation . Count ;
448458
449459 PubKey pubKey = modifiedFederation [ headerSlot ] . PubKey ;
450460
451- string pubKeyRepresentation = ( pubKey == this . federationManager . CurrentFederationKey ? . PubKey ) ? "█████" : pubKey . ToString ( ) . Substring ( 0 , pubKeyTakeCharacters ) ;
461+ string pubKeyRepresentation = pubKey . ToString ( ) . Substring ( 0 , pubKeyTakeCharacters ) ;
462+ if ( pubKey == this . federationManager . CurrentFederationKey ? . PubKey )
463+ {
464+ pubKeyRepresentation = "█████" ;
465+ statistics . ProducedBlockInLastRound = true ;
466+ }
452467
453468 // Mined in this slot?
454469 if ( timeHeader == currentHeader . Header . Time )
@@ -471,13 +486,22 @@ private void AddComponentStats(StringBuilder log)
471486 log . AppendLine ( ) ;
472487 }
473488
489+ statistics . FederationSize = maxDepth ;
490+ statistics . MinerHits = hitCount ;
491+
474492 log . Append ( "..." ) ;
475493 log . AppendLine ( ) ;
476494 log . AppendLine ( $ "Miner hits". PadRight ( LoggingConfiguration . ColumnLength ) + $ ": { hitCount } of { maxDepth } ({ ( ( ( float ) hitCount / ( float ) maxDepth ) ) . ToString ( "P2" ) } )") ;
477495 log . AppendLine ( $ "Miner idle time". PadRight ( LoggingConfiguration . ColumnLength ) + $ ": { TimeSpan . FromSeconds ( this . network . ConsensusOptions . TargetSpacingSeconds * ( maxDepth - hitCount ) ) . ToString ( @"hh\:mm\:ss" ) } ") ;
478496 log . AppendLine ( ) ;
479497 }
480498
499+ /// <inheritdoc/>
500+ public MiningStatisticsModel MiningStatistics
501+ {
502+ get { return this . miningStatistics ; }
503+ }
504+
481505 /// <inheritdoc/>
482506 public virtual void Dispose ( )
483507 {
@@ -487,4 +511,16 @@ public virtual void Dispose()
487511 this . cancellation . Dispose ( ) ;
488512 }
489513 }
514+
515+ public sealed class MiningStatisticsModel
516+ {
517+ [ JsonProperty ( PropertyName = "federationSize" ) ]
518+ public int FederationSize { get ; set ; }
519+
520+ [ JsonProperty ( PropertyName = "minerHits" ) ]
521+ public int MinerHits { get ; set ; }
522+
523+ [ JsonProperty ( PropertyName = "producedBlockInLastRound" ) ]
524+ public bool ProducedBlockInLastRound { get ; set ; }
525+ }
490526}
0 commit comments