void DispatchBlock()
        {
            try
            {
                _Hasher.Pause("dispatching block");

                MinerTrace.Information($"dispatching block with {_ValidatedTxs.Count()} txs");

                var txs = FSharpList <Types.Transaction> .Cons(_Coinbase, ListModule.OfSeq(_ValidatedTxs.Select(TransactionValidation.unpoint)));

                var block = new Types.Block(_Header, txs);


                var result = new HandleBlockAction(block).Publish().Result.BkResultEnum;

                if (result == BlockVerificationHelper.BkResultEnum.Accepted)
                {
                    if (OnMined != null)
                    {
                        OnMined(block);
                    }
                }
                else
                {
                    Reset();
                }

                MinerTrace.Information($"  block {block.header.blockNumber} is " + result);
            } catch (Exception e)
            {
                MinerTrace.Error("Dispatch block exception", e);
            }
        }
Exemple #2
0
        void Main()
        {
            MinerTrace.Information("Hasher started");

            while (true)
            {
                if (_Header == null)
                    Pause("no header");
                
				continueEvent.WaitOne();

				if (_cancel.IsCancellationRequested)
				{
					break;
				}

				var time = DateTime.Now.ToUniversalTime();

				var bkHash = Merkle.blockHeaderHasher.Invoke(_Header);

				var c = 0;

				if (Difficulty != 0)
				{
					var bits = new BitArray(bkHash);
					var len = bits.Length - 1;
					for (var i = 0; i < len; i++)
						if (!bits[len - i])
							c++;
						else
							break;
				}

				if (c >= Difficulty)
				{
					MinerTrace.Information($"Hasher solved a {Difficulty} difficulty");
                    if (OnMined != null)
                        OnMined();
                }
				else
				{
                    //TODO: just increment the nonce, no need to ramdon again
					var random = new Random();
					random.NextBytes(_Header.nonce);
				}
            }

			MinerTrace.Information("Hasher stopped");
        }
        void Populate()
        {
            _BlockChainListener.Pause();

            _TransactionQueue.Clear();

            lock (_BlockChain.memPool.TxPool)
            {
                foreach (var item in _BlockChain.memPool.TxPool)
                {
                    _TransactionQueue.Push(item.Value);
                }
            }

            MinerTrace.Information($"Populated, having {_TransactionQueue.Count} txs");

            RecalculateHeader();

            _BlockChainListener.Continue();
        }
        void OnBlockChainMessage(BlockChainMessage m)
        {
            _Hasher.Pause("BlockChain message");

            if (m is TxMessage)
            {
                MinerTrace.Information($"Got tx ({((TxMessage)m).State})");

                if (((TxMessage)m).State == TxStateEnum.Unconfirmed)
                {
                    _TransactionQueue.Push(((TxMessage)m).Ptx);
                }

                RecalculateHeader();
            }
            else if (m is BlockMessage)
            {
                MinerTrace.Information("Got bk");

                Reset();
            }
        }
        void RecalculateHeader()
        {
            if (_BlockChain.Tip == null)
            {
                return;
            }

            if (_TransactionQueue.IsStuck)
            {
                MinerTrace.Information("Queue is stuck. count = " + _TransactionQueue.Count);
            }

            while (!_TransactionQueue.IsStuck && _ValidatedTxs.Count < TxsPerBlockLimit)
            {
                var ptx = _TransactionQueue.Take();

                if (IsTransactionValid(ptx))
                {
                    _ValidatedTxs.Add(ptx);

                    _TransactionQueue.Remove();

                    HandleTx(ptx);
                }
                else
                {
                    MinerTrace.Information("Tx invalid");
                    _TransactionQueue.Next();
                }
            }

            if (_ValidatedTxs.Count == 0)
            {
                MinerTrace.Information("No txs");
                return;                 // don't allow empty blocks
            }

            CalculateCoinbase();

            var txs = ListModule.OfSeq(FSharpList <Types.Transaction> .Cons(_Coinbase, ListModule.OfSeq(_ValidatedTxs.Select(TransactionValidation.unpoint))));

            _Header = new Types.BlockHeader(
                0,
                _BlockChain.Tip.Key,
                _BlockChain.Tip.Value.header.blockNumber + 1,
                Merkle.merkleRoot(
                    new byte[] { },
                    Merkle.transactionHasher,
                    txs
                    ),
                new byte[] { },
                new byte[] { },
                ListModule.Empty <byte[]>(),
                DateTime.Now.ToUniversalTime().Ticks,
                Difficulty,
                new byte[12]
                );

            MinerTrace.Information($"Mining block number {_BlockChain.Tip.Value.header.blockNumber + 1} with {_ValidatedTxs.Count()} txs");

            _Hasher.SetHeader(_Header);
            _Hasher.Continue();
        }
        void HandleTx(TransactionValidation.PointedTransaction ptx)
        {
            //TODO: try simplify using hash from message
            var txHash = Merkle.transactionHasher.Invoke(TransactionValidation.unpoint(ptx));

            var activationSacrifice = 0UL;

            for (var i = 0; i < ptx.outputs.Length; i++)
            {
                var output = ptx.outputs[i];

                if ([email protected])
                {
                    if (!output.spend.asset.SequenceEqual(Tests.zhash))
                    {
                        continue;                         // not Zen
                    }
                    var contractSacrificeLock = (Types.OutputLock.ContractSacrificeLock)output.@lock;

                    if (contractSacrificeLock.IsHighVLock)
                    {
                        continue;                         // not current version
                    }
                    if (contractSacrificeLock.Item.lockData.Length == 0)
                    {
                        activationSacrifice += output.spend.amount;
                    }
                }

                //todo: fix  to exclude CSLocks&FLocks, instead of including by locktype
                if ([email protected] || [email protected])
                {
                    var outpoint = new Types.Outpoint(txHash, (uint)i);
                    _UtxoSet.Add(new Tuple <Types.Outpoint, Types.Output>(outpoint, output));
                }
            }

            if (FSharpOption <Types.ExtendedContract> .get_IsSome(ptx.contract) && !ptx.contract.Value.IsHighVContract)
            {
                var codeBytes    = ((Types.ExtendedContract.Contract)ptx.contract.Value).Item.code;
                var contractHash = Merkle.innerHash(codeBytes);
                var contractCode = System.Text.Encoding.ASCII.GetString(codeBytes);

                if (!_ActiveContracts.Contains(contractHash))
                {
                    if (activationSacrifice > ActiveContractSet.KalapasPerBlock(contractCode))
                    {
                        try
                        {
                            var compiledCodeOpt = ContractExamples.FStarExecution.compile(contractCode);

                            if (FSharpOption <byte[]> .get_IsSome(compiledCodeOpt))
                            {
                                _ActiveContracts.Add(contractHash);
                            }
                        }
                        catch (Exception e)
                        {
                            MinerTrace.Error("Could not compile contract " + Convert.ToBase64String(contractHash), e);
                        }
                    }
                }
            }
        }
        bool IsTransactionValid(TransactionValidation.PointedTransaction ptx)
        {
            if (!HasUtxos(ptx))
            {
                MinerTrace.Information("could not validate tx - utxo missing");
                return(false);
            }

            var utxoLookup = UtxoLookup.FromConverter(outpoint =>
            {
                var outputs = _UtxoSet.Where(t => t.Item1.Equals(outpoint)).Select(t => t.Item2);
                return(!outputs.Any() ? FSharpOption <Types.Output> .None : new FSharpOption <Types.Output>(outputs.First()));
            });

            var contractLookup = FSharpFunc <byte[], FSharpOption <ContractFunction> > .FromConverter(contractHash =>
            {
                if (!_ActiveContracts.Contains(contractHash))
                {
                    return(FSharpOption <ContractFunction> .None);
                }

                try
                {
                    var code = new GetContractCodeAction(contractHash).Publish().Result;

                    //TODO: module name
                    var extration = ContractExamples.FStarExecution.extract(System.Text.Encoding.ASCII.GetString(code));

                    if (FSharpOption <string> .get_IsNone(extration))
                    {
                        MinerTrace.Information("Could not extract contract");
                        return(null);
                    }

                    var compilation = ContractExamples.FStarExecution.compile(extration.Value);

                    if (FSharpOption <byte[]> .get_IsNone(compilation))
                    {
                        MinerTrace.Information("Could not complie contract");
                        return(null);
                    }

                    return(ContractExamples.FStarExecution.deserialize(compilation.Value).Value.Item1);
                }
                catch (Exception e)
                {
                    MinerTrace.Error("Could not compile contract " + Convert.ToBase64String(contractHash), e);
                    return(null);
                }
            });

            if (!TransactionValidation.validateNonCoinbaseTx(
                    ptx,
                    utxoLookup,
                    contractLookup
                    ))
            {
                MinerTrace.Information("could not validate tx");
                return(false);
            }

            MinerTrace.Information("validated tx");

            //TODO: memory management issues. trying to explicitly collect DynamicMethods
            GC.Collect();
            GC.WaitForPendingFinalizers();

            return(true);
        }
Exemple #8
0
		public void Continue()
		{
			MinerTrace.Information("Hasher resumed");
			continueEvent.Set();
		}
Exemple #9
0
		public void Pause(string reason)
		{
			MinerTrace.Information("Hasher paused: " + reason);
			continueEvent.Reset();
		}