public TransactionMsg deposit(dwacc value)
        {
            TransactionMsg ob = new TransactionMsg();

            ob.Message = "Success";
            return(ob);
        }
        public TransactionMsg withdraw(dwacc value)
        {
            TransactionMsg ob      = new TransactionMsg();
            string         data    = JsonConvert.SerializeObject(value);
            StringContent  content = new StringContent(data, Encoding.UTF8, "application/json");

            HttpResponseMessage response = client.PostAsync(client.BaseAddress + "/Rules/evaluateMinBal/", content).Result;

            if (response.IsSuccessStatusCode)
            {
                string     data1 = response.Content.ReadAsStringAsync().Result;
                ruleStatus s1    = JsonConvert.DeserializeObject <ruleStatus>(data1);
                if (s1.message == "Warning")
                {
                    ob.Message = "Warning";
                    return(ob);
                }
                ob.Message = "No Warning";
                return(ob);
            }



            return(null);
        }
        public TransactionMsg transfer(transfers value)
        {
            dwacc ob4 = new dwacc {
                AccountId = value.source_accid, Balance = value.amount
            };
            TransactionMsg ob      = new TransactionMsg();
            string         data    = JsonConvert.SerializeObject(ob4);
            StringContent  content = new StringContent(data, Encoding.UTF8, "application/json");

            HttpResponseMessage response = client.PostAsync(client.BaseAddress + "/Rules/evaluateMinBal/", content).Result;

            if (response.IsSuccessStatusCode)
            {
                string     data1 = response.Content.ReadAsStringAsync().Result;
                ruleStatus s1    = JsonConvert.DeserializeObject <ruleStatus>(data1);
                if (s1.message == "Warning")
                {
                    ob.Message = "Warning";
                    return(ob);
                }
                ob.Message = "No Warning";
                return(ob);
            }



            return(null);
        }
Esempio n. 4
0
        private BlockMsg convertEntityToBlockMsg(Block entity)
        {
            var txDac     = new TransactionDac();
            var inputDac  = new InputDac();
            var outputDac = new OutputDac();

            var blockMsg  = new BlockMsg();
            var headerMsg = new BlockHeaderMsg();

            headerMsg.Version           = entity.Version;
            headerMsg.Hash              = entity.Hash;
            headerMsg.Height            = entity.Height;
            headerMsg.PreviousBlockHash = entity.PreviousBlockHash;
            headerMsg.Bits              = entity.Bits;
            headerMsg.Nonce             = entity.Nonce;
            headerMsg.Timestamp         = entity.Timestamp;

            var transactions = txDac.SelectByBlockHash(entity.Hash);

            headerMsg.TotalTransaction = transactions == null ? 0: transactions.Count;

            foreach (var tx in transactions)
            {
                var txMsg = new TransactionMsg();
                txMsg.Version   = tx.Version;
                txMsg.Hash      = tx.Hash;
                txMsg.Timestamp = tx.Timestamp;
                txMsg.Locktime  = tx.LockTime;

                var inputs  = inputDac.SelectByTransactionHash(tx.Hash);
                var outputs = outputDac.SelectByTransactionHash(tx.Hash);

                foreach (var input in inputs)
                {
                    txMsg.Inputs.Add(new InputMsg
                    {
                        OutputTransactionHash = input.OutputTransactionHash,
                        OutputIndex           = input.OutputIndex,
                        Size         = input.Size,
                        UnlockScript = input.UnlockScript
                    });
                }

                foreach (var output in outputs)
                {
                    txMsg.Outputs.Add(new OutputMsg
                    {
                        Index      = output.Index,
                        Amount     = output.Amount,
                        Size       = output.Size,
                        LockScript = output.LockScript
                    });
                }

                blockMsg.Transactions.Add(txMsg);
            }

            blockMsg.Header = headerMsg;
            return(blockMsg);
        }
Esempio n. 5
0
        public static bool Consume(string pFilePath)
        {
            try {
                if (isImportFile(pFilePath))
                {
                    new DialPlanImportExportTask().Run(pFilePath);
                }
                else
                {
                    var _txMsg = TransactionMsg.Deserialize(pFilePath);
                    if (_txMsg == null)
                    {
                        TimokLogger.Instance.LogRbr(LogSeverity.Critical, "R_Rbr.Consume", string.Format("TransactionMsg.Deserialize Error, File={0}", pFilePath));
                        return(false);
                    }
                    _txMsg.Execute();
                }

                TimokLogger.Instance.LogRbr(LogSeverity.Status, "R_Rbr.Consume", string.Format("Finished, File={0}", pFilePath));
            }
            catch (Exception _ex) {
                TimokLogger.Instance.LogRbr(LogSeverity.Critical, "R_Rbr.Consume", string.Format("File={0}, Exception:\r\n{1}", pFilePath, _ex));
                return(false);
            }
            return(true);
        }
Esempio n. 6
0
        public void AddTxNoOutput(TransactionMsg transaction)
        {
            if (IsolateTxHashes.Contains(transaction.Hash))
            {
                return;
            }

            Storage.Instance.PutData(IsolateTxsContainerName, transaction.Hash, transaction);

            var myAccounts = AccountDac.Default.GetAccountBook();
            var outputs    = transaction.GetUtxoSets();
            var myOutputs  = outputs.Where(x => myAccounts.Contains(x.Account));

            var spents = transaction.Inputs.Select(x => $"{x.OutputTransactionHash}_{x.OutputIndex}").ToArray();

            Monitor.Enter(isolateObj);
            IsolateTxHashes.Add(transaction.Hash);
            foreach (var myOutput in myOutputs)
            {
                var key = $"{myOutput.TransactionHash}_{myOutput.Index}";
                MyIsolateUtxoSets.Add(key, myOutput);
            }

            IsolateSpentUtxos.AddRange(spents);
            Monitor.Exit(isolateObj);

            if (IsolateTxsExecThread == null || !IsolateTxsExecThread.IsAlive)
            {
                IsolateTxsExecThread = new Thread(new ParameterizedThreadStart(Start));
                IsolateTxsExecThread.Start();
            }
        }
Esempio n. 7
0
        public static Transaction ConvertToEntity(this TransactionMsg transactionMsg, TransExtensionParams transExtension, bool isCoinbase = false)
        {
            Transaction transaction = new Transaction();

            transaction.BlockHash   = transExtension.BlockHash;
            transaction.ExpiredTime = transactionMsg.ExpiredTime;
            transaction.Hash        = transactionMsg.Hash;
            transaction.Inputs      = transExtension.Inputs;
            transaction.IsDiscarded = false;
            transaction.LockTime    = transactionMsg.Locktime;
            transaction.Outputs     = transExtension.Outputs;
            transaction.Size        = transactionMsg.Size;
            transaction.Timestamp   = transactionMsg.Timestamp;
            transaction.TotalInput  = transExtension.TotalInput;
            transaction.TotalOutput = transExtension.TotalOutput;
            transaction.Version     = transactionMsg.Version;

            if (isCoinbase)
            {
                transaction.Fee = 0;
            }
            else
            {
                transaction.Fee = transExtension.TotalInput - transExtension.TotalOutput;
            }

            return(transaction);
        }
Esempio n. 8
0
        public static TransOM ConvertToOM(this TransactionMsg transaction)
        {
            TransOM result = new TransOM();

            result.Hash      = transaction.Hash;
            result.Size      = transaction.Size;
            result.Timestamp = transaction.Timestamp;

            var firstUtxo = UtxoSetDac.Default.Get(transaction.Hash, 0);

            result.OutputAffirm = GlobalParameters.LocalHeight - firstUtxo.BlockHeight;
            result.OutputAmount = transaction.Outputs.Sum(x => x.Amount);

            result.InputList = new List <InputOM>();
            if (transaction.InputCount == 1 && transaction.Inputs[0].OutputTransactionHash.Equals(DbDomains.EmptyHash))
            {
                result.InputList.Add(new InputOM
                {
                    AccountId             = "Coinbase",
                    Amount                = 0,
                    OutputTransactionHash = DbDomains.EmptyHash,
                    UnlockScript          = transaction.Inputs[0].UnlockScript
                });
            }
            else
            {
                var spentHashIndexs = transaction.Inputs.Select(x => $"{x.OutputTransactionHash}_{x.OutputIndex}");
                var utxos           = UtxoSetDac.Default.Get(spentHashIndexs);

                transaction.Inputs.ForEach(x =>
                {
                    var utxo = utxos.FirstOrDefault(p => p.Index == x.OutputIndex && p.TransactionHash == x.OutputTransactionHash);
                    if (utxo != null)
                    {
                        InputOM input               = new InputOM();
                        input.AccountId             = utxo.Account;
                        input.Amount                = utxo.Amount;
                        input.OutputTransactionHash = utxo.TransactionHash;
                        input.UnlockScript          = utxo.LockScript;
                        result.InputList.Add(input);
                    }
                });
            }

            result.OutputList = new List <OutputOM>();
            var newUtxos = transaction.GetUtxoSets();

            newUtxos.ForEach(x =>
            {
                OutputOM output   = new OutputOM();
                output.Amount     = x.Amount;
                output.LockScript = x.LockScript;
                output.ReceiverId = x.Account;
                output.Spent      = UtxoSetDac.Default.Get(x.TransactionHash, x.Index).IsSpent;
                result.OutputList.Add(output);
            });
            return(result);
        }
Esempio n. 9
0
        public IRpcMethodResult GetTxOut(string txid, int vount, bool unconfirmed = false)
        {
            try
            {
                GetTxOutOM result = null;

                var            txComponent    = new TransactionComponent();
                var            blockComponent = new BlockComponent();
                string         blockHash      = null;
                TransactionMsg tx             = txComponent.GetTransactionMsgFromDB(txid, out blockHash);

                if (tx == null && unconfirmed)
                {
                    tx = txComponent.GetTransactionMsgFromPool(txid);
                }


                if (tx != null && tx.OutputCount > vount)
                {
                    var  output        = tx.Outputs[vount];
                    long confirmations = 0;

                    if (!string.IsNullOrWhiteSpace(blockHash))
                    {
                        var block = blockComponent.GetBlockMsgByHash(blockHash);

                        if (block != null)
                        {
                            var latestHeight = blockComponent.GetLatestHeight();

                            if (latestHeight > block.Header.Height)
                            {
                                confirmations = latestHeight - block.Header.Height;
                            }
                        }
                    }

                    result               = new GetTxOutOM();
                    result.bestblock     = blockHash;
                    result.confirmations = confirmations;
                    result.value         = output.Amount;
                    result.scriptPubKey  = output.LockScript;
                    result.version       = tx.Version;
                    result.coinbase      = (tx.InputCount == 0 && tx.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash()));
                }

                return(Ok(result));
            }
            catch (CommonException ce)
            {
                return(Error(ce.ErrorCode, ce.Message, ce));
            }
            catch (Exception ex)
            {
                return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
            }
        }
Esempio n. 10
0
        /// <summary>
        /// 估算交易费率
        /// </summary>
        /// <returns></returns>
        public long EstimateSmartFee()
        {
            //对象初始化
            var  txDac           = new TransactionDac();
            var  transactionMsgs = new List <TransactionMsg>();
            var  txPool          = TransactionPool.Instance;
            long totalSize       = 0;
            long totalFee        = 0;
            //设置最大上限
            long maxSize = BlockSetting.MAX_BLOCK_SIZE - (1 * 1024);
            //交易池中的项目按照费率从高到低排列
            List <TransactionPoolItem> poolItemList = txPool.MainPool.OrderByDescending(t => t.FeeRate).ToList();
            var index = 0;

            while (totalSize < maxSize && index < poolItemList.Count)
            {
                //获取totalFee和totalSize
                TransactionMsg tx = poolItemList[index].Transaction;
                //判断交易Hash是否在交易Msg中
                if (tx != null && transactionMsgs.Where(t => t.Hash == tx.Hash).Count() == 0)
                {
                    totalFee += Convert.ToInt64(poolItemList[index].FeeRate * tx.Serialize().LongLength / 1024.0);
                    if (txDac.SelectByHash(tx.Hash) == null)
                    {
                        transactionMsgs.Add(tx);
                        totalSize += tx.Size;
                    }
                    else
                    {
                        txPool.RemoveTransaction(tx.Hash);
                    }
                }

                /*
                 * else
                 * {
                 *  break;
                 * }
                 */
                index++;
            }
            //获取费率
            if (poolItemList.Count == 0)
            {
                return(1024);
            }
            long feeRate = Convert.ToInt64(Math.Ceiling((totalFee / (totalSize / 1024.0)) / poolItemList.Count));

            if (feeRate < 1024)
            {
                feeRate = 1024;
            }
            return(feeRate);
        }
Esempio n. 11
0
        public void AddNewTransaction(long feeRate, TransactionMsg transaction)
        {
            var item = new TransactionPoolItem(feeRate, transaction);

            if (TransactionPoolDac.Default.Insert(item))
            {
                Storage.Instance.PutData(containerName, transaction.Hash, item);
                var payments = transaction.GetPayments();
                PaymentDac.Default.InsertMem(payments);
            }
        }
Esempio n. 12
0
        public void AddToBlackFile(TransactionMsg txMsg)
        {
            if (txMsg == null)
            {
                return;
            }

            lock (lockTxFileObj)
            {
                Storage.Instance.PutData(containerName, txMsg.Hash, txMsg);
            }
        }
Esempio n. 13
0
 public void AddNewTransaction(long feeRate, TransactionMsg transaction)
 {
     if (this.MainPool.Where(item => item.Transaction.Hash == transaction.Hash).Count() == 0)
     {
         var item = new TransactionPoolItem(feeRate, transaction);
         item.Isolate = false;
         this.MainPool.Add(item);
         Storage.Instance.PutData(this.containerName, transaction.Hash, item);
         //Storage.Instance.Put(this.containerName, transaction.Hash, JsonConvert.SerializeObject(item, Formatting.Indented, new JsonSerializerSettings() {
         //    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
         //}));
     }
 }
Esempio n. 14
0
        public TransactionMsg CreateNewTransactionMsg(List <UtxoMsg> utxos, Dictionary <string, long> receiverIdAndValues)
        {
            var outputDac  = new OutputDac();
            var accountDac = new AccountDac();

            var transaction = new TransactionMsg();

            transaction.Timestamp = Time.EpochTime;
            transaction.Locktime  = 0;

            foreach (var utxo in utxos)
            {
                var account = accountDac.SelectById(utxo.AccountId);

                if (account == null || account.WatchedOnly)
                {
                    //TODO: throw exception;
                    return(null);
                }

                var privateKey = account.PrivateKey;
                var inputMsg   = new InputMsg();
                inputMsg.OutputTransactionHash = utxo.TransactionHash;
                inputMsg.OutputIndex           = utxo.OutputIndex;
                inputMsg.UnlockScript          = Script.BuildUnlockScript(utxo.TransactionHash, utxo.OutputIndex, Base16.Decode(privateKey), Base16.Decode(account.PublicKey));
                inputMsg.Size = inputMsg.UnlockScript.Length;

                transaction.Inputs.Add(inputMsg);
                outputDac.UpdateSpentStatus(utxo.TransactionHash, utxo.OutputIndex);
            }

            int index = 0;

            foreach (var key in receiverIdAndValues.Keys)
            {
                var value = receiverIdAndValues[key];

                var outputMsg = new OutputMsg();
                outputMsg.Index      = index;
                outputMsg.Amount     = value;
                outputMsg.LockScript = Script.BuildLockScipt(key);
                outputMsg.Size       = outputMsg.LockScript.Length;

                transaction.Outputs.Add(outputMsg);
                index++;
            }

            transaction.Hash = transaction.GetHash();
            return(transaction);
        }
Esempio n. 15
0
        public void CreateNewTransaction(TransactionMsg transaction, long feeRate)
        {
            var spents     = transaction.Inputs.Select(x => $"{x.OutputTransactionHash}_{x.OutputIndex}");
            var spentUtxos = UtxoSetDac.Default.Get(spents);

            if (spents.Count() == spentUtxos.Count() && !spentUtxos.Any(x => !x.IsConfirmed(GlobalParameters.LocalHeight)))
            {
                TransactionPool.Instance.AddNewTransaction(feeRate, transaction);
            }
            else
            {
                TransactionPool.Instance.AddTxNoOutput(transaction);
            }
        }
Esempio n. 16
0
        public TransactionMsg GetTransactionByHash(string transactionHash)
        {
            TransactionMsg msg = null;

            foreach (var root in this.RootList)
            {
                msg = this.getTransactionByHash(root, transactionHash);

                if (msg != null)
                {
                    return(msg);
                }
            }

            return(null);
        }
Esempio n. 17
0
        public void AddTransactionToPool(TransactionMsg transaction)
        {
            var isBlacked = BlacklistTxs.Current.IsBlacked(transaction.Hash);

            if (isBlacked)
            {
                return;
            }

            if (TransactionPoolDac.Default.IsExist(transaction.Hash))
            {
                return;
            }

            if (TransactionDac.Default.HasTransaction(transaction.Hash))
            {
                return;
            }

            long feeRate     = 0;
            long totalInput  = 0;
            long totalOutput = 0;
            long fee         = 0;

            try
            {
                var result = VerifyTransaction(transaction, out fee, out totalOutput, out totalInput);
                if (!result)
                {
                    TransactionPool.Instance.AddTxNoOutput(transaction);
                    return;
                }
                else
                {
                    CreateNewTransaction(transaction, feeRate);
                }
            }
            catch (CommonException ex)
            {
                LogHelper.Error(transaction.Hash + ":" + ex.ToString());
                //交易出错时,需要添加到黑名单所在的文件夹
                BlacklistTxs.Current.Add(transaction.Hash);
                BlacklistTxs.Current.AddToBlackFile(transaction);
                throw ex;
            }
        }
Esempio n. 18
0
        public GetTxOutOM GetTxOut(string txid, int vount, bool unconfirmed = false)
        {
            GetTxOutOM     result = null;
            TransactionMsg tx     = null;

            tx = TransactionDac.Default.GetTransaction(txid);
            if (tx == null && unconfirmed)
            {
                tx = TransactionPoolDac.Default.Get(txid);
            }

            if (tx == null)
            {
                return(result);
            }

            if (!unconfirmed)
            {
                var utxo = UtxoSetDac.Default.Get(txid, vount);
                if (utxo == null)
                {
                    return(result);
                }
                result               = new GetTxOutOM();
                result.bestblock     = utxo.BlockHash;
                result.coinbase      = utxo.IsCoinbase;
                result.confirmations = GlobalParameters.LocalHeight - utxo.BlockHeight;
                result.scriptPubKey  = utxo.LockScript;
                result.value         = utxo.Amount;
            }
            else
            {
                var output = tx.Outputs[vount];
                result.bestblock     = null;
                result.coinbase      = false;
                result.confirmations = 0;
                result.scriptPubKey  = output.LockScript;
                result.value         = output.Amount;
            }
            result.version = Versions.EngineVersion;
            return(result);
        }
Esempio n. 19
0
        public static bool HasAddress(this TransactionMsg transaction, string account)
        {
            var newUtxos = transaction.GetUtxoSets();

            if (newUtxos.Any(x => x.Account.Equals(account)))
            {
                return(true);
            }

            var spentHashIndexs = transaction.Inputs.Select(x => $"{x.OutputTransactionHash}_{x.OutputIndex}");

            foreach (var input in transaction.Inputs)
            {
                var utxo = UtxoSetDac.Default.Get(input.OutputTransactionHash, input.OutputIndex);
                if (utxo != null && utxo.Account.Equals(account))
                {
                    return(true);
                }
            }
            return(false);
        }
Esempio n. 20
0
        public static Output ConvertToEntiry(this OutputMsg outputMsg, TransactionMsg transaction, BlockMsg blockMsg)
        {
            Output output = new Output();

            output.Amount          = outputMsg.Amount;
            output.BlockHash       = blockMsg.Header.Hash;
            output.Index           = outputMsg.Index;
            output.LockScript      = outputMsg.LockScript;
            output.Size            = outputMsg.Size;
            output.Index           = transaction.Outputs.IndexOf(outputMsg);
            output.TransactionHash = transaction.Hash;
            output.Spent           = false;
            output.IsDiscarded     = false;
            var receiverId = AccountIdHelper.CreateAccountAddressByPublicKeyHash(
                Base16.Decode(
                    Script.GetPublicKeyHashFromLockScript(outputMsg.LockScript)
                    ));

            output.ReceiverId = receiverId;
            return(output);
        }
Esempio n. 21
0
        public TransactionMsg ConvertTxEntityToMsg(Transaction tx)
        {
            var inputDac  = new InputDac();
            var outputDac = new OutputDac();

            var txMsg = new TransactionMsg();

            txMsg.Version   = tx.Version;
            txMsg.Hash      = tx.Hash;
            txMsg.Timestamp = tx.Timestamp;
            txMsg.Locktime  = tx.LockTime;

            var inputs  = inputDac.SelectByTransactionHash(tx.Hash);
            var outputs = outputDac.SelectByTransactionHash(tx.Hash);

            foreach (var input in inputs)
            {
                txMsg.Inputs.Add(new InputMsg
                {
                    OutputTransactionHash = input.OutputTransactionHash,
                    OutputIndex           = input.OutputIndex,
                    Size         = input.Size,
                    UnlockScript = input.UnlockScript
                });
            }

            foreach (var output in outputs)
            {
                txMsg.Outputs.Add(new OutputMsg
                {
                    Index      = output.Index,
                    Amount     = output.Amount,
                    Size       = output.Size,
                    LockScript = output.LockScript
                });
            }

            return(txMsg);
        }
Esempio n. 22
0
        public static List <UtxoSet> GetUtxoSets(this TransactionMsg transaction)
        {
            List <UtxoSet> sets = new List <UtxoSet>();

            foreach (var output in transaction.Outputs)
            {
                sets.Add(new UtxoSet
                {
                    BlockHeight     = 0,
                    IsCoinbase      = false,
                    IsSpent         = false,
                    Locktime        = transaction.Locktime,
                    TransactionHash = transaction.Hash,
                    Index           = output.Index,
                    Amount          = output.Amount,
                    BlockHash       = null,
                    BlockTime       = 0,
                    TransactionTime = transaction.Timestamp,
                    LockScript      = output.LockScript,
                    Account         = GetAccountByLockScript == null ? null : GetAccountByLockScript(output.LockScript)
                });
            }
            return(sets);
        }
Esempio n. 23
0
        public IRpcMethodResult EstimateTxFeeForSendToAddress(string toAddress, long amount, string comment, string commentTo, bool deductFeeFromAmount)
        {
            try
            {
                EstimateTxFeeOM result               = new EstimateTxFeeOM();
                var             utxoComponent        = new UtxoComponent();
                var             txComponent          = new TransactionComponent();
                var             settingComponent     = new SettingComponent();
                var             addressBookComponent = new AddressBookComponent();
                var             accountComponent     = new AccountComponent();

                if (!AccountIdHelper.AddressVerify(toAddress))
                {
                    throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID);
                }

                var setting   = settingComponent.GetSetting();
                var utxos     = utxoComponent.GetAllConfirmedOutputs();
                var tx        = new TransactionMsg();
                var totalSize = tx.Serialize().Length;

                var output = new OutputMsg();
                output.Amount     = amount;
                output.Index      = 0;
                output.LockScript = Script.BuildLockScipt(toAddress);
                output.Size       = output.LockScript.Length;
                tx.Outputs.Add(output);
                totalSize += output.Serialize().Length;

                var blockComponent  = new BlockComponent();
                var lastBlockHeight = blockComponent.GetLatestHeight();

                var    totalInput  = 0L;
                var    index       = 0;
                double totalAmount = amount;
                double totalFee    = setting.FeePerKB * ((double)totalSize / 1024.0);

                while (index < utxos.Count)
                {
                    var account = accountComponent.GetAccountById(utxos[index].AccountId);

                    if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey))
                    {
                        var   utxoTX    = txComponent.GetTransactionMsgByHash(utxos[index].TransactionHash);
                        Block utxoBlock = blockComponent.GetBlockEntiytByHash(utxos[index].BlockHash);

                        if (utxoTX == null || utxoBlock == null)
                        {
                            index++;
                            continue;
                        }

                        if (!utxoBlock.IsVerified)
                        {
                            index++;
                            continue;
                        }

                        if (Time.EpochTime < utxoTX.Locktime)
                        {
                            index++;
                            continue;
                        }

                        if (utxoTX.InputCount == 1 && utxoTX.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash()))
                        {
                            var blockHeight = utxoBlock.Height;

                            if (lastBlockHeight - blockHeight < 100L)
                            {
                                index++;
                                continue;
                            }
                        }

                        var input = new InputMsg();
                        input.OutputTransactionHash = utxos[index].TransactionHash;
                        input.OutputIndex           = utxos[index].OutputIndex;
                        input.UnlockScript          = Script.BuildUnlockScript(input.OutputTransactionHash, input.OutputIndex, Base16.Decode(decryptPrivateKey(account.PrivateKey)), Base16.Decode(account.PublicKey));
                        input.Size = input.UnlockScript.Length;
                        tx.Inputs.Add(input);

                        var size = input.Serialize().Length;
                        totalSize  += size;
                        totalFee   += setting.FeePerKB * ((double)size / 1024.0);
                        totalInput += utxos[index].Amount;
                    }
                    else
                    {
                        index++;
                        continue;
                    }

                    if (!deductFeeFromAmount)
                    {
                        totalAmount = amount + totalFee;
                    }

                    if (totalInput >= (long)Math.Ceiling(totalAmount))
                    {
                        var size = output.Serialize().Length;

                        if ((totalInput - (long)Math.Ceiling(totalAmount)) > (setting.FeePerKB * (double)size / 1024.0))
                        {
                            totalSize += size;
                            totalFee  += setting.FeePerKB * ((double)size / 1024.0);
                        }

                        break;
                    }

                    index++;
                }

                if (totalInput < totalAmount)
                {
                    throw new CommonException(ErrorCode.Service.Transaction.BALANCE_NOT_ENOUGH);
                }

                if (deductFeeFromAmount)
                {
                    output.Amount -= (long)Math.Ceiling(totalFee);

                    if (output.Amount <= 0)
                    {
                        throw new CommonException(ErrorCode.Service.Transaction.SEND_AMOUNT_LESS_THAN_FEE);
                    }
                }

                result.totalFee  = Convert.ToInt64(totalFee);
                result.totalSize = Convert.ToInt32(totalSize);

                return(Ok(result));
            }
            catch (CommonException ce)
            {
                return(Error(ce.ErrorCode, ce.Message, ce));
            }
            catch (Exception ex)
            {
                return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
            }
        }
Esempio n. 24
0
        public IRpcMethodResult SendMany(string fromAccount, SendManyOutputIM[] receivers, string[] feeDeductAddresses)
        {
            try
            {
                string result                      = null;
                var    utxoComponent               = new UtxoComponent();
                var    txComponent                 = new TransactionComponent();
                var    settingComponent            = new SettingComponent();
                var    addressBookComponent        = new AddressBookComponent();
                var    accountComponent            = new AccountComponent();
                var    transactionCommentComponent = new TransactionCommentComponent();
                var    blockComponent              = new BlockComponent();
                var    lastBlockHeight             = blockComponent.GetLatestHeight();

                var    setting     = settingComponent.GetSetting();
                var    utxos       = utxoComponent.GetAllConfirmedOutputs();
                var    tx          = new TransactionMsg();
                double totalOutput = 0;
                var    totalSize   = tx.Serialize().Length;

                if (receivers == null || receivers.Length == 0)
                {
                    throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID);
                }

                foreach (var receiver in receivers)
                {
                    if (!AccountIdHelper.AddressVerify(receiver.address))
                    {
                        throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID);
                    }

                    var output = new OutputMsg();
                    output.Amount     = receiver.amount;
                    output.Index      = tx.Outputs.Count;
                    output.LockScript = Script.BuildLockScipt(receiver.address);
                    output.Size       = output.LockScript.Length;
                    tx.Outputs.Add(output);

                    totalSize   += output.Serialize().Length;
                    totalOutput += receiver.amount;
                }

                foreach (var address in feeDeductAddresses)
                {
                    if (receivers.Where(r => r.address == address).Count() == 0)
                    {
                        throw new CommonException(ErrorCode.Service.Transaction.FEE_DEDUCT_ADDRESS_INVALID);
                    }
                }

                var    totalInput  = 0L;
                var    index       = 0;
                double totalFee    = setting.FeePerKB * ((double)totalSize / 1024.0);
                double totalAmount = totalOutput;

                while (index < utxos.Count)
                {
                    var account = accountComponent.GetAccountById(utxos[index].AccountId);

                    if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey))
                    {
                        var   utxoTX    = txComponent.GetTransactionMsgByHash(utxos[index].TransactionHash);
                        Block utxoBlock = blockComponent.GetBlockEntiytByHash(utxos[index].BlockHash);

                        if (utxoTX == null || utxoBlock == null)
                        {
                            index++;
                            continue;
                        }

                        if (!utxoBlock.IsVerified)
                        {
                            index++;
                            continue;
                        }

                        if (Time.EpochTime < utxoTX.Locktime)
                        {
                            index++;
                            continue;
                        }

                        if (utxoTX.InputCount == 1 && utxoTX.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash()))
                        {
                            var blockHeight = utxoBlock.Height;

                            if (lastBlockHeight - blockHeight < 100L)
                            {
                                index++;
                                continue;
                            }
                        }

                        var input = new InputMsg();
                        input.OutputTransactionHash = utxos[index].TransactionHash;
                        input.OutputIndex           = utxos[index].OutputIndex;
                        input.UnlockScript          = Script.BuildUnlockScript(input.OutputTransactionHash, input.OutputIndex, Base16.Decode(decryptPrivateKey(account.PrivateKey)), Base16.Decode(account.PublicKey));
                        input.Size = input.UnlockScript.Length;
                        tx.Inputs.Add(input);

                        var size = input.Serialize().Length;
                        totalSize  += size;
                        totalFee   += setting.FeePerKB * ((double)size / 1024.0);
                        totalInput += utxos[index].Amount;
                    }
                    else
                    {
                        index++;
                        continue;
                    }

                    if (feeDeductAddresses == null || feeDeductAddresses.Length == 0)
                    {
                        totalAmount = totalOutput + totalFee;
                    }

                    if (totalInput >= (long)Math.Ceiling(totalAmount))
                    {
                        var size = tx.Outputs[0].Serialize().Length;

                        if ((totalInput - (long)Math.Ceiling(totalAmount)) > (setting.FeePerKB * (double)size / 1024.0))
                        {
                            totalSize += size;
                            totalFee  += setting.FeePerKB * ((double)size / 1024.0);

                            if (feeDeductAddresses == null || feeDeductAddresses.Length == 0)
                            {
                                totalAmount = totalOutput + totalFee;
                            }


                            var newAccount = accountComponent.GenerateNewAccount();

                            if (setting.Encrypt)
                            {
                                if (!string.IsNullOrWhiteSpace(_cache.Get <string>("WalletPassphrase")))
                                {
                                    newAccount.PrivateKey = AES128.Encrypt(newAccount.PrivateKey, _cache.Get <string>("WalletPassphrase"));
                                    accountComponent.UpdatePrivateKeyAr(newAccount);
                                }
                                else
                                {
                                    throw new CommonException(ErrorCode.Service.Wallet.WALLET_HAS_BEEN_LOCKED);
                                }
                            }

                            var newOutput = new OutputMsg();
                            newOutput.Amount     = totalInput - (long)Math.Ceiling(totalAmount);
                            newOutput.Index      = tx.Outputs.Count;
                            newOutput.LockScript = Script.BuildLockScipt(newAccount.Id);
                            newOutput.Size       = newOutput.LockScript.Length;
                            tx.Outputs.Add(newOutput);
                        }

                        break;
                    }

                    index++;
                }

                if (totalInput < totalAmount)
                {
                    throw new CommonException(ErrorCode.Service.Transaction.BALANCE_NOT_ENOUGH);
                }

                if (feeDeductAddresses != null && feeDeductAddresses.Length > 0)
                {
                    var averageFee = totalFee / feeDeductAddresses.Length;

                    for (int i = 0; i < receivers.Length; i++)
                    {
                        if (feeDeductAddresses.Contains(receivers[i].address))
                        {
                            tx.Outputs[i].Amount -= (long)Math.Ceiling(averageFee);

                            if (tx.Outputs[i].Amount <= 0)
                            {
                                throw new CommonException(ErrorCode.Service.Transaction.SEND_AMOUNT_LESS_THAN_FEE);
                            }
                        }
                    }
                }

                tx.Timestamp = Time.EpochTime;
                tx.Hash      = tx.GetHash();
                txComponent.AddTransactionToPool(tx);
                Startup.P2PBroadcastTransactionAction(tx.Hash);
                result = tx.Hash;

                for (int i = 0; i < receivers.Length; i++)
                {
                    var receiver = receivers[i];

                    if (!string.IsNullOrWhiteSpace(receiver.tag))
                    {
                        addressBookComponent.SetTag(receiver.address, receiver.tag);
                    }

                    if (!string.IsNullOrWhiteSpace(receiver.comment))
                    {
                        transactionCommentComponent.Add(tx.Hash, i, receiver.comment);
                    }
                }

                return(Ok(result));
            }
            catch (CommonException ce)
            {
                return(Error(ce.ErrorCode, ce.Message, ce));
            }
            catch (Exception ex)
            {
                return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
            }
        }
Esempio n. 25
0
 public TransactionPoolItem(long feeRate, TransactionMsg transaction)
 {
     this.FeeRate     = feeRate;
     this.Transaction = transaction;
 }
Esempio n. 26
0
        /// <summary>
        /// 创建新的区块
        /// </summary>
        /// <param name="minerName"></param>
        /// <param name="generatorId"></param>
        /// <param name="accountId"></param>
        /// <returns></returns>
        public BlockMsg CreateNewBlock(string minerName, string generatorId, string remark = null, string accountId = null)
        {
            var accountDac      = new AccountDac();
            var blockDac        = new BlockDac();
            var outputDac       = new OutputDac();
            var txDac           = new TransactionDac();
            var txPool          = TransactionPool.Instance;
            var transactionMsgs = new List <TransactionMsg>();

            long   lastBlockHeight    = -1;
            string lastBlockHash      = Base16.Encode(HashHelper.EmptyHash());
            long   lastBlockBits      = -1;
            string lastBlockGenerator = null;

            //获取最后一个区块
            var blockEntity = blockDac.SelectLast();

            if (blockEntity != null)
            {
                lastBlockHeight    = blockEntity.Height;
                lastBlockHash      = blockEntity.Hash;
                lastBlockBits      = blockEntity.Bits;
                lastBlockGenerator = blockEntity.GeneratorId;
            }

            long totalSize    = 0;
            long maxSize      = BlockSetting.MAX_BLOCK_SIZE - (1 * 1024);
            var  poolItemList = txPool.MainPool.OrderByDescending(t => t.FeeRate).ToList();
            var  index        = 0;

            while (totalSize < maxSize && index < poolItemList.Count)
            {
                var tx = poolItemList[index].Transaction;

                if (tx != null && transactionMsgs.Where(t => t.Hash == tx.Hash).Count() == 0)
                {
                    if (txDac.SelectByHash(tx.Hash) == null)
                    {
                        transactionMsgs.Add(tx);
                        totalSize += tx.Size;
                    }
                    else
                    {
                        txPool.RemoveTransaction(tx.Hash);
                    }
                }
                else
                {
                    break;
                }

                index++;
            }


            var minerAccount = accountDac.SelectDefaultAccount();

            if (accountId != null)
            {
                var account = accountDac.SelectById(accountId);

                if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey))
                {
                    minerAccount = account;
                }
            }

            var minerAccountId = minerAccount.Id;

            BlockMsg       newBlockMsg = new BlockMsg();
            BlockHeaderMsg headerMsg   = new BlockHeaderMsg();

            headerMsg.Hash              = Base16.Encode(HashHelper.EmptyHash());
            headerMsg.GeneratorId       = generatorId;
            newBlockMsg.Header          = headerMsg;
            headerMsg.Height            = lastBlockHeight + 1;
            headerMsg.PreviousBlockHash = lastBlockHash;

            if (headerMsg.Height == 0)
            {
                minerAccountId = BlockSetting.GenesisBlockReceiver;
                remark         = BlockSetting.GenesisBlockRemark;
            }

            long totalAmount = 0;
            long totalFee    = 0;

            foreach (var tx in transactionMsgs)
            {
                long totalInputsAmount = 0L;
                long totalOutputAmount = 0L;

                foreach (var input in tx.Inputs)
                {
                    var utxo = outputDac.SelectByHashAndIndex(input.OutputTransactionHash, input.OutputIndex);

                    if (utxo != null)
                    {
                        totalInputsAmount += utxo.Amount;
                    }
                }

                foreach (var output in tx.Outputs)
                {
                    totalOutputAmount += output.Amount;
                }

                totalAmount += totalOutputAmount;
                totalFee    += (totalInputsAmount - totalOutputAmount);
            }

            //var work = new POW(headerMsg.Height);
            BlockMsg prevBlockMsg     = null;
            BlockMsg prevStepBlockMsg = null;

            if (blockEntity != null)
            {
                prevBlockMsg = this.convertEntityToBlockMsg(blockEntity);
            }

            if (headerMsg.Height >= POC.DIFFIUCLTY_ADJUST_STEP)
            {
                prevStepBlockMsg = this.GetBlockMsgByHeight(headerMsg.Height - POC.DIFFIUCLTY_ADJUST_STEP - 1);
            }

            var newBlockReward = POC.GetNewBlockReward(headerMsg.Height);

            headerMsg.Bits             = POC.CalculateBaseTarget(headerMsg.Height, prevBlockMsg, prevStepBlockMsg);
            headerMsg.TotalTransaction = transactionMsgs.Count + 1;

            var coinbaseTxMsg = new TransactionMsg();

            coinbaseTxMsg.Timestamp = Time.EpochTime;
            coinbaseTxMsg.Locktime  = 0;

            var coinbaseInputMsg = new InputMsg();

            coinbaseTxMsg.Inputs.Add(coinbaseInputMsg);
            coinbaseInputMsg.OutputIndex           = 0;
            coinbaseInputMsg.OutputTransactionHash = Base16.Encode(HashHelper.EmptyHash());
            coinbaseInputMsg.UnlockScript          = Script.BuildMinerScript(minerName, remark);
            coinbaseInputMsg.Size = coinbaseInputMsg.UnlockScript.Length;

            var coinbaseOutputMsg = new OutputMsg();

            coinbaseTxMsg.Outputs.Add(coinbaseOutputMsg);
            coinbaseOutputMsg.Amount     = newBlockReward + totalFee;
            coinbaseOutputMsg.LockScript = Script.BuildLockScipt(minerAccountId);
            coinbaseOutputMsg.Size       = coinbaseOutputMsg.LockScript.Length;
            coinbaseOutputMsg.Index      = 0;

            coinbaseTxMsg.Hash = coinbaseTxMsg.GetHash();

            newBlockMsg.Transactions.Insert(0, coinbaseTxMsg);

            foreach (var tx in transactionMsgs)
            {
                newBlockMsg.Transactions.Add(tx);
            }

            headerMsg.PayloadHash = newBlockMsg.GetPayloadHash();
            var dsa        = ECDsa.ImportPrivateKey(Base16.Decode(minerAccount.PrivateKey));
            var signResult = dsa.SingnData(Base16.Decode(headerMsg.PayloadHash));

            headerMsg.BlockSignature   = Base16.Encode(signResult);
            headerMsg.BlockSigSize     = headerMsg.BlockSignature.Length;
            headerMsg.TotalTransaction = newBlockMsg.Transactions.Count;
            return(newBlockMsg);
        }
Esempio n. 27
0
        public Transaction ConvertTxMsgToEntity(TransactionMsg txMsg)
        {
            var outputDac = new OutputDac();
            var entity    = new Transaction();

            entity.Hash      = txMsg.Hash;
            entity.BlockHash = null;
            entity.Version   = txMsg.Version;
            entity.Timestamp = txMsg.Timestamp;
            entity.LockTime  = txMsg.Locktime;
            entity.Inputs    = new List <Input>();
            entity.Outputs   = new List <Output>();

            long totalInput  = 0L;
            long totalOutput = 0L;

            foreach (var inputMsg in txMsg.Inputs)
            {
                var input = new Input();
                input.TransactionHash       = txMsg.Hash;
                input.OutputTransactionHash = inputMsg.OutputTransactionHash;
                input.OutputIndex           = inputMsg.OutputIndex;
                input.Size         = inputMsg.Size;
                input.UnlockScript = inputMsg.UnlockScript;

                var output = outputDac.SelectByHashAndIndex(inputMsg.OutputTransactionHash, inputMsg.OutputIndex);

                if (output != null)
                {
                    input.Amount    = output.Amount;
                    input.AccountId = output.ReceiverId;
                }

                entity.Inputs.Add(input);
                totalInput += input.Amount;
            }

            foreach (var outputMsg in txMsg.Outputs)
            {
                var output = new Output();
                output.Index           = outputMsg.Index;
                output.TransactionHash = entity.Hash;
                var address = AccountIdHelper.CreateAccountAddressByPublicKeyHash(
                    Base16.Decode(
                        Script.GetPublicKeyHashFromLockScript(outputMsg.LockScript)
                        ));
                output.ReceiverId = address;
                output.Amount     = outputMsg.Amount;
                output.Size       = outputMsg.Size;
                output.LockScript = outputMsg.LockScript;
                entity.Outputs.Add(output);
                totalOutput += output.Amount;
            }

            entity.TotalInput  = totalInput;
            entity.TotalOutput = totalOutput;
            entity.Fee         = totalInput - totalOutput;
            entity.Size        = txMsg.Size;

            if (txMsg.Inputs.Count == 1 &&
                txMsg.Outputs.Count == 1 &&
                txMsg.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash()))
            {
                entity.Fee = 0;
            }

            return(entity);
        }
Esempio n. 28
0
        public static Transaction ConvertTxMsgToEntity(this TransactionMsg txMsg, bool isSelf = false)
        {
            var entity = new Transaction();

            entity.Hash      = txMsg.Hash;
            entity.BlockHash = null;
            entity.Version   = txMsg.Version;
            entity.Timestamp = txMsg.Timestamp;
            entity.LockTime  = txMsg.Locktime;
            entity.Inputs    = new List <Input>();
            entity.Outputs   = new List <Output>();

            long totalInput  = 0L;
            long totalOutput = 0L;

            foreach (var inputMsg in txMsg.Inputs)
            {
                var input = new Input();
                input.TransactionHash       = txMsg.Hash;
                input.OutputTransactionHash = inputMsg.OutputTransactionHash;
                input.OutputIndex           = inputMsg.OutputIndex;
                input.Size         = inputMsg.Size;
                input.UnlockScript = inputMsg.UnlockScript;
                var utxo = UtxoSetDac.Default.Get(inputMsg.OutputTransactionHash, inputMsg.OutputIndex);
                if (utxo != null)
                {
                    input.Amount    = utxo.Amount;
                    input.AccountId = utxo.Account;
                    input.BlockHash = utxo.BlockHash;
                }
                else
                {
                    input.Amount    = 0;
                    input.AccountId = "";
                }

                entity.Inputs.Add(input);
                totalInput += input.Amount;
            }

            foreach (var outputMsg in txMsg.Outputs)
            {
                var output = new Output();
                output.Index           = outputMsg.Index;
                output.TransactionHash = entity.Hash;
                var address = AccountIdHelper.CreateAccountAddressByPublicKeyHash(
                    Base16.Decode(
                        Script.GetPublicKeyHashFromLockScript(outputMsg.LockScript)
                        ));
                output.ReceiverId = address;
                output.Amount     = outputMsg.Amount;
                output.Size       = outputMsg.Size;
                output.LockScript = outputMsg.LockScript;
                entity.Outputs.Add(output);
                totalOutput += output.Amount;
            }

            entity.TotalInput  = totalInput;
            entity.TotalOutput = totalOutput;
            entity.Fee         = totalInput - totalOutput;
            entity.Size        = txMsg.Size;

            var coinbaseHashIndex = $"{txMsg.Hash}_{0}";
            var utxoset           = UtxoSetDac.Default.Get(coinbaseHashIndex);

            entity.BlockHash = utxoset?.BlockHash;

            if (txMsg.Inputs.Count == 1 &&
                txMsg.Outputs.Count == 1 &&
                txMsg.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash()))
            {
                entity.Fee = 0;
            }

            return(entity);
        }
Esempio n. 29
0
        public bool VerifyTransaction(TransactionMsg transaction, out long txFee, out long totalOutput, out long totalInput)
        {
            var blockComponent = new BlockComponent();

            txFee = 0;
            //compatible with old node
            if (transaction.Locktime > 0 && transaction.ExpiredTime == transaction.Locktime)
            {
                transaction.ExpiredTime = 0;
            }

            //step 0
            if (transaction.Hash != transaction.GetHash())
            {
                LogHelper.Error("Tx Hash Error:" + transaction.Hash);
                LogHelper.Error("Timestamp:" + transaction.Timestamp);
                LogHelper.Error("Locktime:" + transaction.Locktime);
                LogHelper.Error("ExpiredTime:" + transaction.ExpiredTime);
                LogHelper.Error("InputCount:" + transaction.InputCount);
                LogHelper.Error("OutputCount:" + transaction.OutputCount);

                throw new CommonException(ErrorCode.Engine.Transaction.Verify.TRANSACTION_HASH_ERROR);
            }

            //step 1
            if (transaction.InputCount == 0 || transaction.OutputCount == 0)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.INPUT_AND_OUTPUT_CANNOT_BE_EMPTY);
            }

            //step 2
            if (transaction.Hash == Base16.Encode(HashHelper.EmptyHash()))
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.HASH_CANNOT_BE_EMPTY);
            }

            //step 3
            if (transaction.Locktime < 0 || transaction.Locktime > (Time.EpochTime + BlockSetting.LOCK_TIME_MAX))
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.LOCK_TIME_EXCEEDED_THE_LIMIT);
            }

            //step 4
            if (transaction.Serialize().Length < BlockSetting.TRANSACTION_MIN_SIZE)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.TRANSACTION_SIZE_BELOW_THE_LIMIT);
            }

            //step 5
            if (this.existsInDB(transaction.Hash))
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.TRANSACTION_HAS_BEEN_EXISTED);
            }

            totalOutput = 0;
            totalInput  = 0;

            foreach (var output in transaction.Outputs)
            {
                if (output.Amount <= 0 || output.Amount > BlockSetting.OUTPUT_AMOUNT_MAX)
                {
                    throw new CommonException(ErrorCode.Engine.Transaction.Verify.OUTPUT_EXCEEDED_THE_LIMIT);
                }

                if (!Script.VerifyLockScriptFormat(output.LockScript))
                {
                    throw new CommonException(ErrorCode.Engine.Transaction.Verify.SCRIPT_FORMAT_ERROR);
                }

                totalOutput += output.Amount;
            }

            var count = transaction.Inputs.Distinct().Count();

            if (count != transaction.Inputs.Count)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.UTXO_DUPLICATED_IN_ONE_TRANSACTION);
            }

            foreach (var input in transaction.Inputs)
            {
                if (!Script.VerifyUnlockScriptFormat(input.UnlockScript))
                {
                    throw new CommonException(ErrorCode.Engine.Transaction.Verify.SCRIPT_FORMAT_ERROR);
                }

                var utxo = UtxoSetDac.Default.Get(input.OutputTransactionHash, input.OutputIndex);
                if (utxo != null)
                {
                    if (!utxo.IsConfirmed(GlobalParameters.LocalHeight))
                    {
                        if (utxo.IsCoinbase)
                        {
                            throw new CommonException(ErrorCode.Engine.Transaction.Verify.COINBASE_NEED_100_CONFIRMS);
                        }
                        else
                        {
                            return(false);
                        }
                    }

                    if (Time.EpochTime < utxo.Locktime)
                    {
                        throw new CommonException(ErrorCode.Engine.Transaction.Verify.TRANSACTION_IS_LOCKED);
                    }

                    if (utxo.IsSpent())
                    {
                        throw new CommonException(ErrorCode.Engine.Transaction.Verify.UTXO_HAS_BEEN_SPENT);
                    }

                    if (!Script.VerifyLockScriptByUnlockScript(input.OutputTransactionHash, input.OutputIndex, utxo.LockScript, input.UnlockScript))
                    {
                        throw new CommonException(ErrorCode.Engine.Transaction.Verify.UTXO_UNLOCK_FAIL);
                    }

                    totalInput += utxo.Amount;
                }
                else
                {
                    //not found output, wait for other transactions or blocks;
                    txFee = 0;
                    return(false);
                }
            }

            if (totalOutput >= totalInput)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.OUTPUT_LARGE_THAN_INPUT);
            }

            if ((totalInput - totalOutput) < BlockSetting.TRANSACTION_MIN_FEE)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.TRANSACTION_FEE_IS_TOO_FEW);
            }

            if (totalInput > BlockSetting.INPUT_AMOUNT_MAX)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.INPUT_EXCEEDED_THE_LIMIT);
            }

            if (totalOutput > BlockSetting.OUTPUT_AMOUNT_MAX)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.OUTPUT_EXCEEDED_THE_LIMIT);
            }

            txFee = totalInput - totalOutput;
            return(true);
        }
Esempio n. 30
0
        public bool VerifyTransaction(TransactionMsg transaction, out long txFee, out long totalOutput, out long totalInput)
        {
            totalOutput = 0;
            totalInput  = 0;
            txFee       = 0;
            totalOutput = transaction.Outputs.Sum(x => x.Amount);

            foreach (var input in transaction.Inputs)
            {
                if (!Script.VerifyUnlockScriptFormat(input.UnlockScript))
                {
                    throw new CommonException(ErrorCode.Engine.Transaction.Verify.SCRIPT_FORMAT_ERROR);
                }

                var utxo = UtxoSetDac.Default.Get(input.OutputTransactionHash, input.OutputIndex);
                if (utxo != null)
                {
                    if (!utxo.IsConfirmed(GlobalParameters.LocalHeight))
                    {
                        if (utxo.IsCoinbase)
                        {
                            throw new CommonException(ErrorCode.Engine.Transaction.Verify.COINBASE_NEED_100_CONFIRMS);
                        }
                        else
                        {
                            return(false);
                        }
                    }

                    if (Time.EpochTime < utxo.Locktime)
                    {
                        throw new CommonException(ErrorCode.Engine.Transaction.Verify.TRANSACTION_IS_LOCKED);
                    }

                    if (utxo.IsSpent())
                    {
                        throw new CommonException(ErrorCode.Engine.Transaction.Verify.UTXO_HAS_BEEN_SPENT);
                    }

                    if (Time.EpochTime < utxo.DepositTime)
                    {
                        throw new CommonException(ErrorCode.Engine.Transaction.Verify.DEPOSIT_TIME_NOT_EXPIRED);
                    }
                    if (!Script.VerifyLockScriptByUnlockScript(input.OutputTransactionHash, input.OutputIndex, utxo.LockScript, input.UnlockScript))
                    {
                        throw new CommonException(ErrorCode.Engine.Transaction.Verify.UTXO_UNLOCK_FAIL);
                    }

                    totalInput += utxo.Amount;
                }
                else
                {
                    txFee = 0;
                    return(false);
                }
            }

            if (totalOutput >= totalInput)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.OUTPUT_LARGE_THAN_INPUT);
            }

            if ((totalInput - totalOutput) < BlockSetting.TRANSACTION_MIN_FEE)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.TRANSACTION_FEE_IS_TOO_FEW);
            }

            if (totalInput > BlockSetting.INPUT_AMOUNT_MAX)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.INPUT_EXCEEDED_THE_LIMIT);
            }

            if (totalOutput > BlockSetting.OUTPUT_AMOUNT_MAX)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.OUTPUT_EXCEEDED_THE_LIMIT);
            }

            txFee = totalInput - totalOutput;
            return(true);
        }