private void ApplyMinerRewards(Block block, IBlockTracer tracer) { if (_logger.IsTrace) { _logger.Trace("Applying miner rewards:"); } var rewards = _rewardCalculator.CalculateRewards(block); for (int i = 0; i < rewards.Length; i++) { BlockReward reward = rewards[i]; ITxTracer txTracer = null; if (tracer.IsTracingRewards) { // we need this tracer to be able to track any potential miner account creation txTracer = tracer.StartNewTxTrace(null); } ApplyMinerReward(block, reward); if (tracer.IsTracingRewards) { tracer.EndTxTrace(); tracer.ReportReward(reward.Address, reward.RewardType.ToLowerString(), reward.Value); if (txTracer?.IsTracingState ?? false) { _stateProvider.Commit(_specProvider.GetSpec(block.Number), txTracer); } } } }
public void calculates_rewards_correctly_for_external_addresses() { _block.Header.Number = 10; _block.Body = new BlockBody(_block.Body.Transactions, new[] { Build.A.BlockHeader.WithBeneficiary(TestItem.Addresses[0]).WithNumber(9).TestObject, Build.A.BlockHeader.WithBeneficiary(TestItem.Addresses[1]).WithNumber(8).TestObject }); var expected = new BlockReward[] { new BlockReward(TestItem.AddressA, 1, BlockRewardType.External), new BlockReward(TestItem.AddressB, 3, BlockRewardType.External), new BlockReward(TestItem.AddressC, 5, BlockRewardType.External), new BlockReward(TestItem.AddressD, 8, BlockRewardType.External), }; SetupBlockRewards(new Dictionary <Address, BlockReward[]>() { { _address10, expected } }); var calculator = new AuRaRewardCalculator(_auraParameters, _abiEncoder, _transactionProcessor); var result = calculator.CalculateRewards(_block); result.Should().BeEquivalentTo(expected); }
// TODO: block processor pipeline private void ApplyMinerRewards(Block block, IBlockTracer tracer, IReleaseSpec spec) { if (_logger.IsTrace) { _logger.Trace("Applying miner rewards:"); } BlockReward[] rewards = _rewardCalculator.CalculateRewards(block); for (int i = 0; i < rewards.Length; i++) { BlockReward reward = rewards[i]; ITxTracer txTracer = NullTxTracer.Instance; if (tracer.IsTracingRewards) { // we need this tracer to be able to track any potential miner account creation txTracer = tracer.StartNewTxTrace(null); } ApplyMinerReward(block, reward, spec); if (tracer.IsTracingRewards) { tracer.EndTxTrace(); tracer.ReportReward(reward.Address, reward.RewardType.ToLowerString(), reward.Value); if (txTracer.IsTracingState) { _stateProvider.Commit(spec, txTracer); } } } }
public void calculates_rewards_correctly_for_ommers(long blockNumber, long expectedReward) { _block.Header.Number = blockNumber; _block.Body = new BlockBody(_block.Body.Transactions, new[] { Build.A.BlockHeader.WithBeneficiary(TestItem.AddressB).WithNumber(blockNumber - 1).TestObject, Build.A.BlockHeader.WithBeneficiary(TestItem.AddressD).WithNumber(blockNumber - 2).TestObject }); var expected = new BlockReward[] { new BlockReward(_block.Beneficiary, expectedReward, BlockRewardType.Block), new BlockReward(_block.Body.Ommers[0].Beneficiary, expectedReward, BlockRewardType.Uncle), new BlockReward(_block.Body.Ommers[1].Beneficiary, expectedReward, BlockRewardType.Uncle), }; SetupBlockRewards(new Dictionary <Address, BlockReward[]>() { { _address10, expected } }); var calculator = new AuRaRewardCalculator(_auraParameters, _abiEncoder, _transactionProcessor); var result = calculator.CalculateRewards(_block); result.Should().BeEquivalentTo(expected); }
public void EvaluatePromotion_GetBestPaymentReward() { //Agganre var blockReward = new BlockReward().WithChildrens(new RewardPaymentGetOfAbs() { Amount = 10m, PaymentMethod = "PayTest" }); var dynamicPromotion = new DynamicPromotion { DynamicExpression = AbstractTypeFactory <PromotionConditionAndRewardTree> .TryCreateInstance() }; dynamicPromotion.DynamicExpression.WithChildrens(blockReward); var evalPolicy = GetPromotionEvaluationPolicy(new[] { dynamicPromotion }); var productA = new ProductPromoEntry { ProductId = "ProductA", Price = 100, Quantity = 1 }; var context = new PromotionEvaluationContext { PaymentMethodCode = "PayTest", PaymentMethodPrice = 5m, PromoEntries = new[] { productA } }; //Act var rewards = evalPolicy.EvaluatePromotionAsync(context).GetAwaiter().GetResult().Rewards.OfType <PaymentReward>().ToList(); //Assert Assert.Equal(10m, rewards.First().Amount); Assert.True(rewards.First().IsValid); }
private void ApplyMinerRewards(Block block, IBlockTracer tracer) { if (_logger.IsTrace) { _logger.Trace("Applying miner rewards:"); } var rewards = _rewardCalculator.CalculateRewards(block); for (int i = 0; i < rewards.Length; i++) { BlockReward reward = rewards[i]; ITxTracer txTracer = null; if (tracer.IsTracingRewards) { txTracer = tracer.StartNewTxTrace(null); } ApplyMinerReward(block, reward, tracer.IsTracingRewards ? tracer : NullBlockTracer.Instance); if (tracer.IsTracingRewards) { tracer.EndTxTrace(); tracer.ReportReward(reward.Address, reward.RewardType.ToLowerString(), (UInt256)reward.Value); if (txTracer?.IsTracingState ?? false) { _stateProvider.Commit(_specProvider.GetSpec(block.Number), txTracer); } } } }
public override string ToString() { return("TAG: " + TagName + " | Name:" + FullName + " | Algo: " + Algo + " | BTC/day: " + BtcPerDay.ToString("#.00000000") + " | Coins/day: " + CoinsPerDay.ToString("#.00000000") + GetExchanges() + " | Weighted price: " + WeightedBtcPrice.ToString("#.00000000") + " | Total volume: " + TotalExchange.BtcVolume.ToString("#.0000") + " | Difficulty: " + Difficulty.ToString("#.###") + " | Blockreward: " + BlockReward.ToString("#.###")); }
public void calculates_rewards_correctly_after_contract_transition(long blockNumber, long expectedReward) { _block.Number = blockNumber; var expected = new BlockReward(_block.Beneficiary, expectedReward, BlockRewardType.Block); SetupBlockRewards(expected); var calculator = new AuRaRewardCalculator(_auraParameters, _abiEncoder, _transactionProcessor); var result = calculator.CalculateRewards(_block); result.Should().BeEquivalentTo(expected); }
public void calculates_rewards_correctly_after_contract_transition(long blockNumber, ulong expectedReward) { _block.Header.Number = blockNumber; var expected = new BlockReward(_block.Beneficiary, expectedReward, BlockRewardType.External); SetupBlockRewards(new Dictionary <Address, BlockReward[]>() { { _address10, new[] { expected } } }); var calculator = new AuRaRewardCalculator(_auraParameters, _abiEncoder, _transactionProcessor); var result = calculator.CalculateRewards(_block); result.Should().BeEquivalentTo(expected); }
private void ApplyMinerReward(Block block, BlockReward reward) { if (_logger.IsTrace) { _logger.Trace($" {(BigInteger) reward.Value / (BigInteger) Unit.Ether:N3}{Unit.EthSymbol} for account at {reward.Address}"); } if (!_stateProvider.AccountExists(reward.Address)) { _stateProvider.CreateAccount(reward.Address, reward.Value); } else { _stateProvider.AddToBalance(reward.Address, reward.Value, _specProvider.GetSpec(block.Number)); } }
public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); Timestamp = reader.ReadUInt32(); Nonce = reader.ReadUInt64(); NextConsensus = reader.ReadSerializable <UInt160>(); TransactionHashes = reader.ReadSerializableArray <UInt256>(Block.MaxTransactionsPerBlock); if (TransactionHashes.Distinct().Count() != TransactionHashes.Length) { throw new FormatException(); } BlockReward = reader.ReadSerializable <BlockReward>(); if (BlockReward.Hash != TransactionHashes[0]) { throw new FormatException(); } StateRootSignature = reader.ReadBytes(64); }
public void calculates_rewards_correctly_after_subsequent_contract_transitions(long blockNumber, long expectedReward, Address address) { _auraParameters.BlockRewardContractTransitions = new Dictionary <long, Address>() { { 50, _address50 }, { 150, _address150 } }; _block.Header.Number = blockNumber; var expected = new BlockReward(_block.Beneficiary, expectedReward, BlockRewardType.Block); SetupBlockRewards(new Dictionary <Address, BlockReward[]>() { { address, new[] { expected } } }); var calculator = new AuRaRewardCalculator(_auraParameters, _abiEncoder, _transactionProcessor); var result = calculator.CalculateRewards(_block); result.Should().BeEquivalentTo(expected); }
private void Fill() { IEnumerable <Transaction> memoryPoolTransactions = Blockchain.Singleton.MemPool.GetSortedVerifiedTransactions(); foreach (IPolicyPlugin plugin in Plugin.Policies) { memoryPoolTransactions = plugin.FilterForBlock(memoryPoolTransactions); } List <Transaction> transactions = memoryPoolTransactions.ToList(); Fixed8 amountNetFee = Block.CalculateNetFee(transactions); TransactionOutput[] outputs = new[] { new TransactionOutput { AssetId = Blockchain.GoverningToken.Hash, Value = Blockchain.Singleton.GetBlockReward() + amountNetFee, ScriptHash = wallet.GetChangeAddress() } }; while (true) { ulong nonce = GetNonce(); BlockReward tx = new BlockReward { Nonce = (uint)(nonce % (uint.MaxValue + 1ul)), Attributes = new TransactionAttribute[0], Inputs = new CoinReference[0], Outputs = outputs, Witnesses = new Witness[0] }; if (!Snapshot.ContainsTransaction(tx.Hash)) { Nonce = nonce; transactions.Insert(0, tx); break; } } TransactionHashes = transactions.Select(p => p.Hash).ToArray(); Transactions = transactions.ToDictionary(p => p.Hash); NextConsensus = Blockchain.GetConsensusAddress(Snapshot.GetValidators(transactions).ToArray()); Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestamp(), this.PrevHeader().Timestamp + 1); }
private BlockReward[] CalculateRewardsWithContract(Block block) { (Address[] beneficieries, ushort[] kinds) GetBeneficiaries() { var length = block.Ommers.Length + 1; Address[] beneficiariesList = new Address[length]; ushort[] kindsList = new ushort[length]; beneficiariesList[0] = block.Beneficiary; kindsList[0] = RewardContract.Definition.BenefactorKind.Author; for (int i = 0; i < block.Ommers.Length; i++) { var uncle = block.Ommers[i]; if (RewardContract.Definition.BenefactorKind.TryGetUncle(block.Number - uncle.Number, out var kind)) { beneficiariesList[i + 1] = uncle.Beneficiary; kindsList[i + 1] = kind; } } return(beneficiariesList, kindsList); } var(beneficiaries, kinds) = GetBeneficiaries(); var transaction = _contract.Reward(beneficiaries, kinds); _contract.InvokeTransaction(block.Header, _transactionProcessor, transaction, _tracer); var(addresses, rewards) = _contract.DecodeRewards(_tracer.ReturnValue); var blockRewards = new BlockReward[addresses.Length]; for (int index = 0; index < addresses.Length; index++) { var address = addresses[index]; blockRewards[index] = new BlockReward(address, rewards[index], GetBlockRewardType(address, beneficiaries, kinds, index)); } return(blockRewards); }
public void calculates_rewards_correctly_for_ommers(long blockNumber, long expectedReward) { _block.Number = blockNumber; _block.Body.Ommers = new[] { Prepare.A.BlockHeader().WithBeneficiary(Address.FromNumber(777)).WithNumber(blockNumber - 1).TestObject, Prepare.A.BlockHeader().WithBeneficiary(Address.FromNumber(888)).WithNumber(blockNumber - 2).TestObject }; var expected = new BlockReward[] { new BlockReward(_block.Beneficiary, expectedReward, BlockRewardType.Block), new BlockReward(_block.Body.Ommers[0].Beneficiary, expectedReward, BlockRewardType.Uncle), new BlockReward(_block.Body.Ommers[1].Beneficiary, expectedReward, BlockRewardType.Uncle), }; SetupBlockRewards(expected); var calculator = new AuRaRewardCalculator(_auraParameters, _abiEncoder, _transactionProcessor); var result = calculator.CalculateRewards(_block); result.Should().BeEquivalentTo(expected); }
public void calculates_rewards_correctly_for_external_addresses() { _block.Number = 10; _block.Body.Ommers = new[] { Prepare.A.BlockHeader().WithBeneficiary(Address.FromNumber(777)).WithNumber(9).TestObject, Prepare.A.BlockHeader().WithBeneficiary(Address.FromNumber(888)).WithNumber(8).TestObject }; var expected = new BlockReward[] { new BlockReward(TestItem.AddressA, 1, BlockRewardType.External), new BlockReward(TestItem.AddressB, 3, BlockRewardType.External), new BlockReward(TestItem.AddressC, 5, BlockRewardType.External), new BlockReward(TestItem.AddressD, 8, BlockRewardType.External), }; SetupBlockRewards(expected); var calculator = new AuRaRewardCalculator(_auraParameters, _abiEncoder, _transactionProcessor); var result = calculator.CalculateRewards(_block); result.Should().BeEquivalentTo(expected); }
private BlockReward[] CalculateRewardsWithContract(Block block, IRewardContract contract) { (Address[] beneficieries, ushort[] kinds) GetBeneficiaries() { var length = block.Uncles.Length + 1; Address[] beneficiariesList = new Address[length]; ushort[] kindsList = new ushort[length]; beneficiariesList[0] = block.Beneficiary; kindsList[0] = BenefactorKind.Author; for (int i = 0; i < block.Uncles.Length; i++) { var uncle = block.Uncles[i]; if (BenefactorKind.TryGetUncle(block.Number - uncle.Number, out var kind)) { beneficiariesList[i + 1] = uncle.Beneficiary; kindsList[i + 1] = kind; } } return(beneficiariesList, kindsList); } var(beneficiaries, kinds) = GetBeneficiaries(); var(addresses, rewards) = contract.Reward(block.Header, beneficiaries, kinds); var blockRewards = new BlockReward[addresses.Length]; for (int index = 0; index < addresses.Length; index++) { var address = addresses[index]; blockRewards[index] = new BlockReward(address, rewards[index], BlockRewardType.External); } return(blockRewards); }
public void TestSetup() { uut = new BlockReward(); }
public void DynamicPromotion_Clone() { var blockCustomer = new BlockCustomerCondition() .WithAvailConditions( new ConditionIsRegisteredUser(), new ConditionIsEveryone(), new ConditionIsFirstTimeBuyer(), new UserGroupsContainsCondition() { Group = "11" } ); var blockCatalog = new BlockCatalogCondition() .WithAvailConditions( new ConditionCategoryIs() { CategoryId = "11", CategoryName = "", ExcludingCategoryIds = new string[] { "1", "2" }, ExcludingProductIds = new string[] { "3", "4" } }, new ConditionCodeContains() { Keyword = "keyword" }, new ConditionCurrencyIs() { Currency = "USD" }, new ConditionEntryIs() { ProductIds = new string[] { "1", "2" }, ProductNames = new string[] { "name1", "name2" } }, new ConditionInStockQuantity() { CompareCondition = "CND", Quantity = 111, QuantitySecond = 222 }, new ConditionHasNoSalePrice() ); var blockCart = new BlockCartCondition() .WithAvailConditions( new ConditionAtNumItemsInCart() { CompareCondition = "CND", ExcludingCategoryIds = new string[] { "1", "2" }, ExcludingProductIds = new string[] { "3", "4" }, NumItem = 111, NumItemSecond = 222 }, new ConditionAtNumItemsInCategoryAreInCart() { CategoryId = "catid", CategoryName = "catname", CompareCondition = "CND", ExcludingCategoryIds = new string[] { "1", "2" }, ExcludingProductIds = new string[] { "3", "4" }, NumItem = 111, NumItemSecond = 222 }, new ConditionAtNumItemsOfEntryAreInCart() { CompareCondition = "CND", NumItem = 111, NumItemSecond = 222, ProductId = "Id", ProductName = "Name" }, new ConditionCartSubtotalLeast() { CompareCondition = "CND", ExcludingCategoryIds = new string[] { "1", "2" }, ExcludingProductIds = new string[] { "3", "4" }, SubTotal = 111, SubTotalSecond = 222 } ); var blockReward = new BlockReward() .WithAvailConditions( new RewardCartGetOfAbsSubtotal() { Amount = 444 }, new RewardCartGetOfRelSubtotal() { Amount = 444, MaxLimit = 555 }, new RewardItemGetFreeNumItemOfProduct() { NumItem = 55, ProductId = "Id", ProductName = "Name" }, new RewardItemGetOfAbs() { Amount = 444, ProductId = "Id", ProductName = "Name" }, new RewardItemGetOfAbsForNum() { Amount = 444, ProductId = "Id", ProductName = "Name", NumItem = 23 }, new RewardItemGetOfRel() { Amount = 444, ProductId = "Id", ProductName = "Name", MaxLimit = 23 }, new RewardItemGetOfRelForNum() { Amount = 444, ProductId = "Id", ProductName = "Name", MaxLimit = 23, NumItem = 32 }, new RewardItemGiftNumItem() { CategoryId = "catid", CategoryName = "catname", Description = "description", ProductId = "productId", ProductName = "ptoductName", Name = "Name", ImageUrl = "url:\\", MeasureUnit = "px", Quantity = 33 }, new RewardShippingGetOfAbsShippingMethod() { Amount = 444, ShippingMethod = "shipMethod" }, new RewardShippingGetOfRelShippingMethod() { Amount = 444, ShippingMethod = "shipMethod", MaxLimit = 22 }, new RewardPaymentGetOfAbs() { Amount = 444, PaymentMethod = "payMethod" }, new RewardPaymentGetOfRel() { Amount = 444, PaymentMethod = "payMethod", MaxLimit = 22 }, new RewardItemForEveryNumInGetOfRel() { Amount = 444, ForNthQuantity = 77, InEveryNthQuantity = 78, MaxLimit = 22, ItemLimit = 23, Product = new ProductContainer() { ProductId = "prodID", ProductName = "prodName" } }, new RewardItemForEveryNumOtherItemInGetOfRel() { Amount = 444, ForNthQuantity = 77, InEveryNthQuantity = 78, MaxLimit = 22, ItemLimit = 23, Product = new ProductContainer() { ProductId = "prodID", ProductName = "prodName" }, ConditionalProduct = new ProductContainer() { ProductId = "condProdID", ProductName = "condProdName" } } ); var dynamicPromotion = new DynamicPromotion { DynamicExpression = AbstractTypeFactory <PromotionConditionAndRewardTree> .TryCreateInstance() }; dynamicPromotion.DynamicExpression.WithChildrens( blockCustomer, blockCatalog, blockCart, blockReward ); dynamicPromotion.AssertCloneIndependency(); }
public void ConsensusService_Primary_Sends_PrepareRequest_After_OnStart() { TestProbe subscriber = CreateTestProbe(); var mockConsensusContext = new Mock <IConsensusContext>(); var mockStore = new Mock <Store>(); // context.Reset(): do nothing //mockConsensusContext.Setup(mr => mr.Reset()).Verifiable(); // void mockConsensusContext.SetupGet(mr => mr.MyIndex).Returns(2); // MyIndex == 2 mockConsensusContext.SetupGet(mr => mr.BlockIndex).Returns(2); mockConsensusContext.SetupGet(mr => mr.PrimaryIndex).Returns(2); mockConsensusContext.SetupGet(mr => mr.ViewNumber).Returns(0); mockConsensusContext.SetupProperty(mr => mr.Nonce); mockConsensusContext.SetupProperty(mr => mr.NextConsensus); mockConsensusContext.Object.NextConsensus = UInt160.Zero; mockConsensusContext.SetupGet(mr => mr.PreparationPayloads).Returns(new ConsensusPayload[7]); mockConsensusContext.SetupGet(mr => mr.CommitPayloads).Returns(new ConsensusPayload[7]); int timeIndex = 0; var timeValues = new[] { //new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc), // For tests here new DateTime(1968, 06, 01, 0, 0, 1, DateTimeKind.Utc), // For receiving block new DateTime(1968, 06, 01, 0, 0, (int)Blockchain.SecondsPerBlock, DateTimeKind.Utc), // For Initialize new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc), // unused new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc) // unused }; //TimeProvider.Current.UtcNow.ToTimestamp().Should().Be(4244941711); //1968-06-01 00:00:15 Console.WriteLine($"time 0: {timeValues[0].ToString()} 1: {timeValues[1].ToString()} 2: {timeValues[2].ToString()} 3: {timeValues[3].ToString()}"); //mockConsensusContext.Object.block_received_time = new DateTime(1968, 06, 01, 0, 0, 1, DateTimeKind.Utc); //mockConsensusContext.Setup(mr => mr.GetUtcNow()).Returns(new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc)); var timeMock = new Mock <TimeProvider>(); timeMock.SetupGet(tp => tp.UtcNow).Returns(() => timeValues[timeIndex]) .Callback(() => timeIndex++); //new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc)); TimeProvider.Current = timeMock.Object; //public void Log(string message, LogLevel level) // TODO: create ILogPlugin for Tests /* * mockConsensusContext.Setup(mr => mr.Log(It.IsAny<string>(), It.IsAny<LogLevel>())) * .Callback((string message, LogLevel level) => { * Console.WriteLine($"CONSENSUS LOG: {message}"); * } * ); */ // Creating proposed block Header header = new Header(); TestUtils.SetupHeaderWithValues(header, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out ulong consensusDataVal, out Witness scriptVal); header.Size.Should().Be(109); Console.WriteLine($"header {header} hash {header.Hash} timstamp {timestampVal}"); timestampVal.Should().Be(4244941696); //1968-06-01 00:00:00 // check basic ConsensusContext mockConsensusContext.Object.MyIndex.Should().Be(2); //mockConsensusContext.Object.block_received_time.ToTimestamp().Should().Be(4244941697); //1968-06-01 00:00:01 BlockReward minerTx = new BlockReward { Attributes = new TransactionAttribute[0], Inputs = new CoinReference[0], Outputs = new TransactionOutput[0], Witnesses = new Witness[0], Nonce = 42 }; PrepareRequest prep = new PrepareRequest { Nonce = mockConsensusContext.Object.Nonce, NextConsensus = mockConsensusContext.Object.NextConsensus, TransactionHashes = new UInt256[0], BlockReward = minerTx, //(BlockReward)Transactions[TransactionHashes[0]], StateRootSignature = new byte[64] }; ConsensusPayload prepPayload = new ConsensusPayload { Version = 0, PrevHash = mockConsensusContext.Object.PrevHash, BlockIndex = mockConsensusContext.Object.BlockIndex, ValidatorIndex = (ushort)mockConsensusContext.Object.MyIndex, ConsensusMessage = prep }; mockConsensusContext.Setup(mr => mr.MakePrepareRequest()).Returns(prepPayload); // ============================================================================ // creating ConsensusService actor // ============================================================================ TestActorRef <ConsensusService> actorConsensus = ActorOfAsTestActorRef <ConsensusService>( Akka.Actor.Props.Create(() => new ConsensusService(subscriber, subscriber, mockConsensusContext.Object)) ); Console.WriteLine("will trigger OnPersistCompleted!"); actorConsensus.Tell(new Blockchain.PersistCompleted { Block = new Block { Version = header.Version, PrevHash = header.PrevHash, MerkleRoot = header.MerkleRoot, Timestamp = header.Timestamp, Index = header.Index, ConsensusData = header.ConsensusData, NextConsensus = header.NextConsensus } }); // OnPersist will not launch timer, we need OnStart Console.WriteLine("will start consensus!"); actorConsensus.Tell(new ConsensusService.Start()); Console.WriteLine("OnTimer should expire!"); Console.WriteLine("Waiting for subscriber message!"); // Timer should expire in one second (block_received_time at :01, initialized at :02) var answer = subscriber.ExpectMsg <LocalNode.SendDirectly>(); Console.WriteLine($"MESSAGE 1: {answer}"); //var answer2 = subscriber.ExpectMsg<LocalNode.SendDirectly>(); // expects to fail! // ============================================================================ // finalize ConsensusService actor // ============================================================================ //Thread.Sleep(4000); Sys.Stop(actorConsensus); TimeProvider.ResetToDefault(); Assert.AreEqual(1, 1); }