Beispiel #1
0
        public void Fill()
        {
            IEnumerable <Transaction> mem_pool = blockchain.GetVerifiedTransactions();

            foreach (IPolicyPlugin plugin in PluginManager.Singleton.Policies)
            {
                mem_pool = plugin.FilterForBlock(mem_pool);
            }
            List <Transaction> transactions = mem_pool.ToList();

            while (true)
            {
                ulong            nonce = Transaction.GetNonce();
                MinerTransaction tx    = new MinerTransaction
                {
                    ChainHash  = blockchain.ChainHash,
                    Nonce      = nonce,
                    Account    = wallet.GetChangeAddress(),
                    Attributes = new TransactionAttribute[0],
                    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(), PrevHeader.Timestamp + 1);
        }
Beispiel #2
0
        public async Task Persist_MinerTx_NoSpecialCalls()
        {
            var input  = new MinerTransaction();
            var testee = AutoMockContainer.Create <TransactionPersister>();

            await testee.Persist(input);
        }
Beispiel #3
0
        public void SerializeDeserialize_MinerTransaction()
        {
            var original = new MinerTransaction()
            {
                Version = 0x00,
                Nonce   = (uint)_random.Next(0, int.MaxValue)
            };

            FillRandomTx(original);

            var ret   = _serializer.Serialize(original);
            var copy  = _deserializer.Deserialize <Transaction>(ret);
            var copy2 = _deserializer.Deserialize <MinerTransaction>(ret);

            // Check exclusive data

            foreach (var check in new MinerTransaction[] { (MinerTransaction)copy, copy2 })
            {
                Assert.AreEqual(original.Nonce, check.Nonce);
            }

            // Check base data

            EqualTx(original, copy, copy2);
        }
Beispiel #4
0
        /*
         * private void FillContext()
         * {
         *  IEnumerable<Transaction> mem_pool = Blockchain.Singleton.GetMemoryPool();
         *  foreach (IPolicyPlugin plugin in Plugin.Policies)
         *      mem_pool = plugin.FilterForBlock(mem_pool);
         *  List<Transaction> transactions = mem_pool.ToList();
         *  Fixed8 amount_netfee = Block.CalculateNetFee(transactions);
         *  TransactionOutput[] outputs = amount_netfee == Fixed8.Zero ? new TransactionOutput[0] : new[] { new TransactionOutput
         *  {
         *      AssetId = Blockchain.UtilityToken.Hash,
         *      Value = amount_netfee,
         *      ScriptHash = wallet.GetChangeAddress()
         *  } };
         *  while (true)
         *  {
         *      ulong nonce = GetNonce();
         *      MinerTransaction tx = new MinerTransaction
         *      {
         *          Nonce = (uint)(nonce % (uint.MaxValue + 1ul)),
         *          Attributes = new TransactionAttribute[0],
         *          Inputs = new CoinReference[0],
         *          Outputs = outputs,
         *          Witnesses = new Witness[0]
         *      };
         *      if (!context.Snapshot.ContainsTransaction(tx.Hash))
         *      {
         *          context.Nonce = nonce;
         *          transactions.Insert(0, tx);
         *          break;
         *      }
         *  }
         *  context.TransactionHashes = transactions.Select(p => p.Hash).ToArray();
         *  context.Transactions = transactions.ToDictionary(p => p.Hash);
         *  context.NextConsensus = Blockchain.GetConsensusAddress(context.Snapshot.GetValidators(transactions).ToArray());
         * }
         */

        /// <summary>
        /// 添加挖矿产出
        /// </summary>
        private void FillContext()
        {
            IEnumerable <Transaction> mem_pool = Blockchain.Singleton.GetMemoryPool();

            foreach (IPolicyPlugin plugin in Plugin.Policies)
            {
                mem_pool = plugin.FilterForBlock(mem_pool);
            }
            List <Transaction> transactions  = mem_pool.ToList();
            Fixed8             amount_netfee = Block.CalculateNetFee(transactions);

            MiningTransaction miningTransaction = new MiningTransaction(amount_netfee);

            while (true)
            {
                ulong            nonce = GetNonce();
                MinerTransaction tx    = miningTransaction.GetMinerTransaction(nonce, context.BlockIndex, wallet);
                if (!context.Snapshot.ContainsTransaction(tx.Hash))
                {
                    context.Nonce = nonce;
                    transactions.Insert(0, tx);
                    break;
                }
            }

            context.TransactionHashes = transactions.Select(p => p.Hash).ToArray();
            context.Transactions      = transactions.ToDictionary(p => p.Hash);
            context.NextConsensus     = Blockchain.GetConsensusAddress(context.Snapshot.GetValidators(transactions).ToArray());
        }
Beispiel #5
0
        public async Task Process_MinerTx_NoSpecialCalls()
        {
            var input  = new MinerTransaction();
            var testee = AutoMockContainer.Create <TransactionProcessor>();

            await testee.Process(input);
        }
Beispiel #6
0
        /// <summary>
        /// The first miner transaction
        /// </summary>
        /// <returns>The miner transaction.</returns>
        public static MinerTransaction GenesisMinerTransaction()
        {
            uint genesisMinerNonce       = 2083236893;
            var  genesisMinerTransaction = new MinerTransaction
            {
                Nonce      = genesisMinerNonce,
                Attributes = new TransactionAttribute[0],
                Inputs     = new CoinReference[0],
                Outputs    = new TransactionOutput[0],
                Witness    = new Witness[0]
            };

            return(genesisMinerTransaction);
        }
Beispiel #7
0
        public MinerTransaction GetMinerTransaction(ulong nonce, uint blockIndex, Wallet wallet)
        {
            if (blockIndex < 1)
            {
                return(new MinerTransaction
                {
                    Nonce = (uint)(nonce % (uint.MaxValue + 1ul)),
                    Attributes = new TransactionAttribute[0],
                    Inputs = new CoinReference[0],
                    Outputs = amount_netfee == Fixed8.Zero ? new TransactionOutput[0] : new TransactionOutput[] { NetFeeOutput(wallet, amount_netfee) },
                    Witnesses = new Witness[0]
                });
            }

            if (outputs == null)
            {
                MakeTransactionOutputs(blockIndex, wallet, amount_netfee);
                byte[] hashDataOfMining = GetHashData();
                if (hashDataOfMining != null)
                {
                    //Signature
                    WalletAccount account = wallet.GetAccount(wallet.GetChangeAddress());
                    if (account?.HasKey == true)
                    {
                        KeyPair key = account.GetKey();
                        signatureOfMining = Crypto.Default.Sign(hashDataOfMining, key.PrivateKey, key.PublicKey.EncodePoint(false).Skip(1).ToArray());
                    }
                }
            }

            MinerTransaction tx = new MinerTransaction
            {
                Nonce      = (uint)(nonce % (uint.MaxValue + 1ul)),
                Attributes = signatureOfMining == null ? new TransactionAttribute[0] :
                             new TransactionAttribute[]
                {
                    new TransactionAttribute
                    {
                        Usage = TransactionAttributeUsage.Description,
                        Data  = signatureOfMining
                    }
                },
                Inputs    = new CoinReference[0],
                Outputs   = outputs,
                Witnesses = new Witness[0]
            };

            return(tx);
        }
 public override void Deserialize(BinaryReader reader)
 {
     base.Deserialize(reader);
     Nonce             = reader.ReadUInt64();
     TransactionHashes = reader.ReadSerializableArray <UInt256>();
     if (TransactionHashes.Distinct().Count() != TransactionHashes.Length)
     {
         throw new FormatException();
     }
     MinerTransaction = reader.ReadSerializable <MinerTransaction>();
     if (MinerTransaction.Hash != TransactionHashes[0])
     {
         throw new FormatException();
     }
     Signature = reader.ReadBytes(64);
 }
Beispiel #9
0
 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();
     }
     MinerTransaction = reader.ReadSerializable <MinerTransaction>();
     if (MinerTransaction.Hash != TransactionHashes[0])
     {
         throw new FormatException();
     }
 }
Beispiel #10
0
        private void FillContext()
        {
            ReportNeoBlockchain reportObj = new ReportNeoBlockchain("[NeoConsensusService-FillContext]");

            List <Transaction> transactions = LocalNode.GetMemoryPool().Where(p => CheckPolicy(p)).ToList();

            if (transactions.Count >= Settings.Default.MaxTransactionsPerBlock)
            {
                transactions = transactions.OrderByDescending(p => p.NetworkFee / p.Size).Take(Settings.Default.MaxTransactionsPerBlock - 1).ToList();
            }
            Fixed8 amount_netfee = Block.CalculateNetFee(transactions);

            TransactionOutput[] outputs = amount_netfee == Fixed8.Zero ? new TransactionOutput[0] : new[] { new TransactionOutput
                                                                                                            {
                                                                                                                AssetId    = Blockchain.UtilityToken.Hash,
                                                                                                                Value      = amount_netfee,
                                                                                                                ScriptHash = wallet.GetChangeAddress()
                                                                                                            } };
            while (true)
            {
                ulong            nonce = GetNonce();
                MinerTransaction tx    = new MinerTransaction
                {
                    Nonce      = (uint)(nonce % (uint.MaxValue + 1ul)),
                    Attributes = new TransactionAttribute[0],
                    Inputs     = new CoinReference[0],
                    Outputs    = outputs,
                    Scripts    = new Witness[0]
                };
                if (Blockchain.Default.GetTransaction(tx.Hash) == null)
                {
                    context.Nonce = nonce;
                    transactions.Insert(0, tx);
                    break;
                }
            }
            context.TransactionHashes = transactions.Select(p => p.Hash).ToArray();
            context.Transactions      = transactions.ToDictionary(p => p.Hash);
            context.NextConsensus     = Blockchain.GetConsensusAddress(Blockchain.Default.GetValidators(transactions).ToArray());

            reportObj.appendElapsedTime();
        }
Beispiel #11
0
        private void FillContext()
        {
            TR.Enter();
            IEnumerable <Transaction> mem_pool = LocalNode.GetMemoryPool().Where(p => CheckPolicy(p));

            foreach (PolicyPlugin plugin in PolicyPlugin.Instances)
            {
                mem_pool = plugin.Filter(mem_pool);
            }
            List <Transaction> transactions  = mem_pool.ToList();
            Fixed8             amount_netfee = Block.CalculateNetFee(transactions);

            TransactionOutput[] outputs = amount_netfee == Fixed8.Zero ? new TransactionOutput[0] : new[] { new TransactionOutput
                                                                                                            {
                                                                                                                AssetId    = Blockchain.UtilityToken.Hash,
                                                                                                                Value      = amount_netfee,
                                                                                                                ScriptHash = wallet.GetChangeAddress()
                                                                                                            } };
            while (true)
            {
                ulong            nonce = GetNonce();
                MinerTransaction tx    = new MinerTransaction
                {
                    Nonce      = (uint)(nonce % (uint.MaxValue + 1ul)),
                    Attributes = new TransactionAttribute[0],
                    Inputs     = new CoinReference[0],
                    Outputs    = outputs,
                    Scripts    = new Witness[0]
                };
                if (Blockchain.Default.GetTransaction(tx.Hash) == null)
                {
                    context.Nonce = nonce;
                    transactions.Insert(0, tx);
                    break;
                }
            }
            context.TransactionHashes = transactions.Select(p => p.Hash).ToArray();
            context.Transactions      = transactions.ToDictionary(p => p.Hash);
            context.NextConsensus     = Blockchain.GetConsensusAddress(Blockchain.Default.GetValidators(transactions).ToArray());
            TR.Exit();
        }
Beispiel #12
0
        public override void Deserialize(BinaryReader reader)
        {
            ReportNeoBlockchain reportObj = new ReportNeoBlockchain("[NeoPrepareRequest-Deserialize]");

            base.Deserialize(reader);
            Nonce             = reader.ReadUInt64();
            NextConsensus     = reader.ReadSerializable <UInt160>();
            TransactionHashes = reader.ReadSerializableArray <UInt256>();
            if (TransactionHashes.Distinct().Count() != TransactionHashes.Length)
            {
                throw new FormatException();
            }
            MinerTransaction = reader.ReadSerializable <MinerTransaction>();
            if (MinerTransaction.Hash != TransactionHashes[0])
            {
                throw new FormatException();
            }
            Signature = reader.ReadBytes(64);

            reportObj.appendElapsedTime();
        }
        public void Fill()
        {
            IEnumerable <Transaction> mem_pool = Blockchain.Singleton.GetMemoryPool();

            foreach (IPolicyPlugin plugin in Plugin.Policies)
            {
                mem_pool = plugin.FilterForBlock(mem_pool);
            }
            List <Transaction> transactions  = mem_pool.ToList();
            Fixed8             amount_netfee = Block.CalculateNetFee(transactions);

            TransactionOutput[] outputs = amount_netfee == Fixed8.Zero ? new TransactionOutput[0] : new[] { new TransactionOutput
                                                                                                            {
                                                                                                                AssetId    = Blockchain.UtilityToken.Hash,
                                                                                                                Value      = amount_netfee,
                                                                                                                ScriptHash = wallet.GetChangeAddress()
                                                                                                            } };
            while (true)
            {
                ulong            nonce = GetNonce();
                MinerTransaction tx    = new MinerTransaction
                {
                    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(), PrevHeader.Timestamp + 1);
        }
Beispiel #14
0
        private void FillContext()
        {
            IEnumerable <Transaction> mem_pool = blockchain.GetMemoryPool();

            foreach (IPolicyPlugin plugin in system.PluginMgr.Policies)
            {
                mem_pool = plugin.FilterForBlock(mem_pool);
            }
            List <Transaction> transactions  = mem_pool.ToList();
            Fixed8             amount_netfee = Block.CalculateNetFee(transactions);

            TransactionOutput[] outputs = amount_netfee == Fixed8.Zero ? new TransactionOutput[0] : new[] { new TransactionOutput
                                                                                                            {
                                                                                                                AssetId    = Blockchain.UtilityToken.Hash,
                                                                                                                Value      = amount_netfee,
                                                                                                                ScriptHash = wallet.GetChangeAddress()
                                                                                                            } };
            while (true)
            {
                ulong            nonce = GetNonce();
                MinerTransaction tx    = new MinerTransaction
                {
                    ChainHash  = chainHash,
                    Nonce      = (uint)(nonce % (uint.MaxValue + 1ul)),
                    Attributes = new TransactionAttribute[0],
                    Inputs     = new CoinReference[0],
                    Outputs    = outputs,
                    Witnesses  = new Witness[0]
                };
                if (!context.Snapshot.ContainsTransaction(tx.Hash))
                {
                    context.Nonce = nonce;
                    transactions.Insert(0, tx);
                    break;
                }
            }
            context.TransactionHashes = transactions.Select(p => p.Hash).ToArray();
            context.Transactions      = transactions.ToDictionary(p => p.Hash);
            context.NextConsensus     = Blockchain.GetConsensusAddress(context.Snapshot.GetValidators(transactions).ToArray());
        }
Beispiel #15
0
        public MinerTransaction MakeMinerTransaction(Wallet wallet, uint blockIndex, ulong nonce, Fixed8 amount_txfee, Fixed8 amount_netfee)
        {
            List <TransactionOutput>    outputs    = new List <TransactionOutput>();
            List <TransactionAttribute> attributes = new List <TransactionAttribute>();

            if (blockIndex > 0)
            {
                AddMiningTransaction(wallet, blockIndex, outputs, attributes);
                AddTxFee(outputs, amount_txfee, blockIndex);
                AddNetFee(wallet, outputs, amount_netfee);
            }

            MinerTransaction tx = new MinerTransaction
            {
                Nonce      = (uint)(nonce % (uint.MaxValue + 1ul)),
                Attributes = attributes.ToArray(),
                Inputs     = new CoinReference[0],
                Outputs    = outputs.ToArray(),
                Witnesses  = new Witness[0]
            };

            return(tx);
        }
Beispiel #16
0
        static void Mining(BhpSystem system)
        {
            Fixed8 amount_netfee   = Fixed8.Zero;
            Fixed8 transaction_fee = Fixed8.Zero;

            ulong nonce = 100156895;

            BRC6Wallet wallet = new BRC6Wallet(new Bhp.Wallets.WalletIndexer(@"walletindex"), @"D:\BHP\Test\t1.json");

            wallet.Unlock("1");
            wallet.WalletTransaction += Wallet_WalletTransaction;

            MiningTransaction miningTransaction = new MiningTransaction();
            MinerTransaction  tx = miningTransaction.MakeMinerTransaction(wallet, 1000, nonce, Fixed8.Zero, Fixed8.Zero);

            Console.WriteLine(tx.ToJson());

            Console.WriteLine("\n Staring Sign......");
            ContractParametersContext context = new ContractParametersContext(tx);

            wallet.Sign(context);
            if (context.Completed)
            {
                Console.WriteLine("\n Sign successfully.");
                context.Verifiable.Witnesses = context.GetWitnesses();
                string hexString = GetTxHashData(context.Verifiable).ToHexString();
                Console.WriteLine($"\n {hexString}");
                system.LocalNode.Tell(new LocalNode.Relay {
                    Inventory = tx
                });

                RelayResultReason reason = system.Blockchain.Ask <RelayResultReason>(tx).Result;
                Console.WriteLine("\n relay tx: " + reason);
            }

            Console.ReadLine();
        }
Beispiel #17
0
        public static Transaction CreateMinnerTransaction(SignDelegate2 sign)
        {
            // d55ccd8b368aca2402003f39549ad7b75385c226009b3080e0d886959b75b5ce
            TransactionOutput[] outputs = new TransactionOutput[]
            {
                new TransactionOutput
                {
                    AssetId    = Blockchain.GoverningToken.Hash,
                    Value      = Fixed8.FromDecimal(444),
                    ScriptHash = currentAddress.ToScriptHash()
                }
            };
            ulong            nonce = GetNonce();
            MinerTransaction tx    = new MinerTransaction
            {
                Nonce      = (uint)(nonce % (uint.MaxValue + 1ul)),
                Attributes = new TransactionAttribute[0],
                Inputs     = new CoinReference[0],
                Outputs    = outputs,
                Witnesses  = new Witness[0]
            };

            return(sign.Invoke(tx));
        }
Beispiel #18
0
 public void TestSetup()
 {
     uut = new MinerTransaction();
 }
        // Since ConensusContext's constructor is internal, it can't be used from neo-express.
        // CreatePreloadBlock replicates the following logic for creating an empty block with ConensusContext

        // var ctx = new Neo.Consensus.ConsensusContext(wallet, store);
        // ctx.Reset(0);
        // ctx.MakePrepareRequest();
        // ctx.MakeCommit();
        // ctx.Save();
        // Block block = ctx.CreateBlock();

        static Block CreatePreloadBlock(Neo.Wallets.Wallet wallet, Random random, Transaction?transaction = null)
        {
            using var snapshot = Blockchain.Singleton.GetSnapshot();
            var validators = snapshot.GetValidators();

            if (validators.Length != 1)
            {
                throw new InvalidOperationException("Preload only supported for single-node blockchains");
            }

            var amountNetFee = Block.CalculateNetFee(Enumerable.Empty <Transaction>());

            if (amountNetFee != Fixed8.Zero)
            {
                throw new InvalidOperationException("amountNetFee must be zero");
            }

            var keyPair   = wallet.GetAccount(validators[0]).GetKey();
            var prevHash  = snapshot.CurrentBlockHash;
            var prevBlock = snapshot.GetBlock(prevHash);
            var nonce     = NextNonce(random);

            var minerTx = new MinerTransaction
            {
                Nonce      = (uint)(nonce % (uint.MaxValue + 1ul)),
                Attributes = Array.Empty <TransactionAttribute>(),
                Inputs     = Array.Empty <CoinReference>(),
                Outputs    = Array.Empty <TransactionOutput>(),
                Witnesses  = Array.Empty <Witness>()
            };

            var blockTransactions = transaction == null ? new Transaction[] { minerTx } : new Transaction[] { minerTx, transaction };
            var txHashes          = blockTransactions.Select(tx => tx.Hash).ToArray();
            var merkleRoot        = MerkleTree.ComputeRoot(txHashes);
            var nextConsensus     = Blockchain.GetConsensusAddress(snapshot.GetValidators(blockTransactions).ToArray());
            var consensusData     = nonce;

            var block = new Block()
            {
                Version       = 0,
                PrevHash      = prevHash,
                MerkleRoot    = merkleRoot,
                Timestamp     = prevBlock.Timestamp + 1,
                Index         = prevBlock.Index + 1,
                ConsensusData = nonce,
                NextConsensus = nextConsensus,
                Transactions  = Array.Empty <Transaction>(),
            };

            var commit = new Neo.Consensus.Commit()
            {
                ViewNumber = 0,
                Signature  = block.Sign(keyPair)
            };
            var payload = new ConsensusPayload
            {
                Version        = 0,
                PrevHash       = prevHash,
                BlockIndex     = block.Index,
                ValidatorIndex = (ushort)0,
                Data           = Neo.IO.Helper.ToArray(commit)
            };

            {
                var sc = new ContractParametersContext(payload);
                wallet.Sign(sc);
                payload.Witness = sc.GetWitnesses()[0];
            }

            {
                var      m                   = validators.Length - ((validators.Length - 1) / 3);
                Contract contract            = Contract.CreateMultiSigContract(m, validators);
                ContractParametersContext sc = new ContractParametersContext(block);
                for (int i = 0, j = 0; i < validators.Length && j < m; i++)
                {
                    sc.AddSignature(contract, validators[0], payload.GetDeserializedMessage <Neo.Consensus.Commit>().Signature);
                    j++;
                }
                block.Witness      = sc.GetWitnesses()[0];
                block.Transactions = blockTransactions;
            }
            return(block);
        }
Beispiel #20
0
        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

            MinerTransaction minerTx = new MinerTransaction
            {
                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],
                MinerTransaction  = minerTx //(MinerTransaction)Transactions[TransactionHashes[0]],
            };

            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);
        }