예제 #1
0
        bool IsContractActive(byte[] contractHash)
        {
            using (var dbTx = _DBContext.GetTransactionContext())
            {
                return(ActiveContractSet.IsActive(dbTx, contractHash));
            }

            //TODO: get number of blocks
            //var lastBlock = ActiveContractSet.LastBlock(dbTx, contractHash);
            //var currentHeight = Tip == null ? 0 : Tip.Value.header.blockNumber;
            //return nextBlocks > currentHeight - lastBlock;
        }
예제 #2
0
        /// <summary>
        /// Handles a new transaction from network or wallet.
        /// </summary>
        TxResultEnum HandleTransaction(Types.Transaction tx, bool checkInDb = true)
        {
            using (var dbTx = _DBContext.GetTransactionContext())
            {
                TransactionValidation.PointedTransaction ptx;
                var txHash = Merkle.transactionHasher.Invoke(tx);

                lock (memPool)
                {
                    if (memPool.TxPool.Contains(txHash) || memPool.ICTxPool.Contains(txHash) || memPool.OrphanTxPool.Contains(txHash))
                    {
                        BlockChainTrace.Information("Tx already in mempool", txHash);
                        return(TxResultEnum.Known);
                    }

                    if (checkInDb && BlockStore.TxStore.ContainsKey(dbTx, txHash) && BlockStore.TxStore.Get(dbTx, txHash).Value.InMainChain)
                    {
                        BlockChainTrace.Information("Tx already in store", txHash);
                        return(TxResultEnum.Known);
                    }

                    Action removeDeps = () =>
                    {
                        memPool.ICTxPool.GetDependencies(txHash).ToList().ForEach(t => t.Item1.RemoveWithDependencies(t.Item2));
                        memPool.OrphanTxPool.GetDependencies(txHash).ToList().ForEach(t => t.Item1.RemoveWithDependencies(t.Item2));
                    };

                    if (IsDoubleSpend(dbTx, tx, false))
                    {
                        new TxMessage(txHash, null, TxStateEnum.Invalid).Publish();
                        removeDeps();
                        return(TxResultEnum.DoubleSpend);
                    }

                    switch (IsOrphanTx(dbTx, tx, false, out ptx))
                    {
                    case IsTxOrphanResult.Orphan:
                        BlockChainTrace.Information("tx added as orphan", tx);
                        memPool.OrphanTxPool.Add(txHash, tx);
                        return(TxResultEnum.Orphan);

                    case IsTxOrphanResult.Invalid:
                        BlockChainTrace.Information("tx refers to an output that cannot exist", tx);
                        removeDeps();
                        return(TxResultEnum.Invalid);
                    }

                    if (IsCoinbaseTx(ptx))
                    {
                        BlockChainTrace.Information("tx is coinbase", tx);
                        return(TxResultEnum.Invalid);
                    }

                    if (!IsReferencedCoinbaseTxsValid(dbTx, ptx))
                    {
                        BlockChainTrace.Information("referenced coinbase immature", tx);
                        return(TxResultEnum.Invalid);
                    }

                    //if (!IsStructurallyValidTx(dbTx, ptx))
                    //{
                    //	BlockChainTrace.Information("tx invalid - structural", ptx);
                    //	return TxResultEnum.Invalid;
                    //}

                    byte[] contractHash;
                    switch (IsContractGeneratedTx(ptx, out contractHash))
                    {
                    case IsContractGeneratedTxResult.ContractGenerated:
                        if (!ActiveContractSet.IsActive(dbTx, contractHash))
                        {
                            BlockChainTrace.Information("tx added to ICTx mempool", tx);
                            BlockChainTrace.Information(" of contract", contractHash);
                            memPool.TxPool.ICTxPool.Add(txHash, ptx);
                            return(TxResultEnum.InactiveContract);
                        }

                        var utxoLookup       = UtxoLookupFactory(dbTx, false, ptx);
                        var contractFunction = ActiveContractSet.GetContractFunction(dbTx, contractHash);

                        if (!IsValidAutoTx(ptx, utxoLookup, contractHash, contractFunction))
                        {
                            BlockChainTrace.Information("auto-tx invalid", ptx);
                            removeDeps();
                            return(TxResultEnum.Invalid);
                        }
                        break;

                    case IsContractGeneratedTxResult.Invalid:
                        BlockChainTrace.Information("tx invalid - input locks", tx);
                        return(TxResultEnum.Invalid);

                    case IsContractGeneratedTxResult.NotContractGenerated:     // assume user generated
                        if (!IsValidUserGeneratedTx(dbTx, ptx))
                        {
                            BlockChainTrace.Information("tx invalid - input locks", tx);
                            removeDeps();
                            return(TxResultEnum.Invalid);
                        }
                        break;
                    }

                    BlockChainTrace.Information("tx added to mempool", ptx);
                    memPool.TxPool.Add(txHash, ptx);
                    new TxMessage(txHash, ptx, TxStateEnum.Unconfirmed).Publish();
                    new HandleOrphansOfTxAction(txHash).Publish();
                }

                return(TxResultEnum.Accepted);
            }
        }