Ejemplo n.º 1
0
        public string GetAccountByLockScript(string lockScript)
        {
            var publicKeyHash = Base16.Decode(Script.GetPublicKeyHashFromLockScript(lockScript));
            var address       = AccountIdHelper.CreateAccountAddressByPublicKeyHash(publicKeyHash);

            return(address);
        }
Ejemplo n.º 2
0
        private void getOutputsByAccountId(BlockPoolItem node, string accountId, Dictionary <string, List <OutputMsg> > dict)
        {
            foreach (var tx in node.Block.Transactions)
            {
                if (!dict.ContainsKey(tx.Hash))
                {
                    dict.Add(tx.Hash, new List <OutputMsg>());
                }

                foreach (var output in tx.Outputs)
                {
                    var publicKeyHash = Script.GetPublicKeyHashFromLockScript(output.LockScript);
                    var id            = AccountIdHelper.CreateAccountAddressByPublicKeyHash(Base16.Decode(publicKeyHash));

                    if (id == accountId)
                    {
                        dict[tx.Hash].Add(output);
                    }
                }
            }

            foreach (var child in node.Children)
            {
                getOutputsByAccountId(child, accountId, dict);
            }
        }
Ejemplo n.º 3
0
        public Account GenerateNewAccount(bool isAddtoCache = true)
        {
            var dac = AccountDac.Default;

            byte[] privateKey;
            byte[] publicKey;
            using (var dsa = ECDsa.GenerateNewKeyPair())
            {
                privateKey = dsa.PrivateKey;
                publicKey  = dsa.PublicKey;
            }

            var id = AccountIdHelper.CreateAccountAddress(publicKey);

            if (dac.IsExisted(id))
            {
                throw new Exception("Account id is existed");
            }

            Account account = new Account();

            account.Id          = id;
            account.PrivateKey  = Base16.Encode(privateKey);
            account.PublicKey   = Base16.Encode(publicKey);
            account.Balance     = 0;
            account.IsDefault   = false;
            account.WatchedOnly = false;

            AccountDac.Default.Insert(account);
            return(account);
        }
Ejemplo n.º 4
0
        public Dictionary <string, List <OutputMsg> > GetTransactionOutputsByAccountId(string accountId)
        {
            var dict = new Dictionary <string, List <OutputMsg> >();

            foreach (var item in this.MainPool)
            {
                var tx = item.Transaction;
                if (!dict.ContainsKey(tx.Hash))
                {
                    dict.Add(tx.Hash, new List <OutputMsg>());
                }

                foreach (var output in tx.Outputs)
                {
                    var publicKeyHash = Script.GetPublicKeyHashFromLockScript(output.LockScript);
                    var id            = AccountIdHelper.CreateAccountAddressByPublicKeyHash(Base16.Decode(publicKeyHash));

                    if (id == accountId)
                    {
                        dict[tx.Hash].Add(output);
                    }
                }
            }

            return(dict);
        }
Ejemplo n.º 5
0
        public Account GenerateWatchOnlyAddress(string publickeyText)
        {
            var dac = AccountDac.Default;

            byte[] publickey = Base16.Decode(publickeyText);
            string id        = AccountIdHelper.CreateAccountAddress(publickey);

            Account account = dac.SelectById(id);

            if (account == null)
            {
                account             = new Account();
                account.Id          = id;
                account.PrivateKey  = "";
                account.PublicKey   = publickeyText;
                account.Balance     = 0;
                account.IsDefault   = false;
                account.WatchedOnly = true;

                AccountDac.Default.Insert(account);
                //UtxoSet.Instance.AddAccountId(account.Id);
            }

            return(account);
        }
Ejemplo n.º 6
0
        public Account ImportAccount(string privateKeyText)
        {
            var dac = AccountDac.Default;

            byte[] privateKey = Base16.Decode(privateKeyText);
            byte[] publicKey;
            using (var dsa = ECDsa.ImportPrivateKey(privateKey))
            {
                publicKey = dsa.PublicKey;
            }

            var     id      = AccountIdHelper.CreateAccountAddress(publicKey);
            Account account = dac.SelectById(id);

            if (account == null)
            {
                account             = new Account();
                account.Id          = AccountIdHelper.CreateAccountAddress(publicKey);
                account.PrivateKey  = Base16.Encode(privateKey);
                account.PublicKey   = Base16.Encode(publicKey);
                account.Balance     = 0;
                account.IsDefault   = false;
                account.WatchedOnly = false;

                AccountDac.Default.Insert(account);
            }

            return(account);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// 存币交易分析处理
        /// </summary>
        /// <param name="successBlock"></param>
        private static void ProcessDepositTx(BlockMsg successBlock)
        {
            if (successBlock == null || successBlock.Transactions == null || !successBlock.Transactions.Any())
            {
                return;
            }
            List <DepositList> toInsert = new List <DepositList>();

            successBlock.Transactions.ForEach(x =>
            {
                if (x.DepositTime > 0 && x.Outputs != null && x.Outputs.Any())
                {
                    x.Outputs.ForEach(o =>
                    {
                        var receiverId = AccountIdHelper.CreateAccountAddressByPublicKeyHash(
                            Base16.Decode(
                                Script.GetPublicKeyHashFromLockScript(o.LockScript)
                                ));
                        var dep = new DepositList()
                        {
                            Address         = receiverId,
                            Amount          = o.Amount,
                            ExpireTime      = x.DepositTime,
                            IsExpired       = x.DepositTime < Time.EpochTime ? 1:0,
                            TransactionHash = x.Hash
                        };
                        toInsert.Add(dep);
                    });
                }
            });
            if (toInsert.Any())
            {
                new RewardListComponent().InsertDeposit(toInsert);
            }
        }
Ejemplo n.º 8
0
        public Account ImportObservedAccount(string publicKeyText)
        {
            var dac = new AccountDac();

            var publicKey = Base16.Decode(publicKeyText);
            var id        = AccountIdHelper.CreateAccountAddress(publicKey);

            Account account = dac.SelectById(id);

            if (account == null)
            {
                account             = new Account();
                account.Id          = AccountIdHelper.CreateAccountAddress(publicKey);
                account.PrivateKey  = null;
                account.PublicKey   = Base16.Encode(publicKey);
                account.Balance     = 0;
                account.IsDefault   = false;
                account.WatchedOnly = true;

                dac.Insert(account);
                UtxoSet.Instance.AddAccountId(account.Id);
            }

            return(account);
        }
Ejemplo n.º 9
0
        public List <TransactionMsg> SearchByAccountId(string accountId)
        {
            var publicKeyText = Base16.Encode(
                AccountIdHelper.GetPublicKeyHash(accountId)
                );

            var result = this.MainPool.Where(t => t.Transaction.Outputs.Where(o => o.LockScript.Contains(publicKeyText)).Count() > 0).
                         Select(t => t.Transaction).ToList();

            return(result);
        }
Ejemplo n.º 10
0
        public IRpcMethodResult ValidateAddress(string address)
        {
            try
            {
                var result           = new ValidateAddressOM();
                var accountComponent = new AccountComponent();

                result.address = address;

                if (AccountIdHelper.AddressVerify(address))
                {
                    result.isValid = true;
                    var account = accountComponent.GetAccountById(address);

                    if (account != null)
                    {
                        result.isMine      = true;
                        result.isWatchOnly = string.IsNullOrWhiteSpace(account.PrivateKey);
                    }
                    else
                    {
                        result.isMine = false;
                    }

                    result.scriptPubKey  = Script.BuildLockScipt(address);
                    result.isScript      = false;
                    result.script        = "P2PKH";
                    result.hex           = null;
                    result.addresses     = null;
                    result.pubKey        = account.PublicKey;
                    result.isCompressed  = false;
                    result.account       = account.Tag;
                    result.hdKeyPath     = null;
                    result.hdMasterKeyId = null;
                }
                else
                {
                    result.isValid = false;
                }

                return(Ok(result));
            }
            catch (CommonException ce)
            {
                return(Error(ce.ErrorCode, ce.Message, ce));
            }
            catch (Exception ex)
            {
                return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
            }
        }
Ejemplo n.º 11
0
        public void Initialize()
        {
            DtoExtensions.GetAccountByLockScript = lockScript => AccountIdHelper.CreateAccountAddressByPublicKeyHash(Base16.Decode(Script.GetPublicKeyHashFromLockScript(lockScript)));

            OmniCoin.Update.StartUp.Start();

            DbDomains.Init();
            RepairBlockData();
            RepairUtxoSet();

            MiningPoolComponent.LoadMiningPools();

            DbDomains.InitData();
            LogHelper.Info("Load Data Completed");
        }
Ejemplo n.º 12
0
        public CommonResponse GetScoopNumber(string address)
        {
            try
            {
                try
                {
                    if (!AccountIdHelper.AddressVerify(address))
                    {
                        return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_IS_INVALID, $"Address {address} is invalid"));
                    }
                }
                catch
                {
                    return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_IS_INVALID, $"Address {address} is invalid"));
                }

                var miner = MinersJob.Current.Pool_Miners.FirstOrDefault(m => m.Address == address);

                if (miner == null)
                {
                    return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_NOT_EXIST, $"Address {address} is not exist"));
                }

                var key         = "Pool:MinerScoopNumber:" + address;
                var scoopNumber = RedisManager.Current.GetDataInRedis <string>(key);
                var ttl         = RedisManager.Current.PTtl(key);

                if (string.IsNullOrWhiteSpace(scoopNumber) || ttl < 10 * 1000)
                {
                    var random = new Random();
                    scoopNumber = random.Next(0, 4096).ToString();
                    RedisManager.Current.SaveDataToRedis(key, scoopNumber.ToString(), ScoopNumberTimeout);
                }

                return(OK(scoopNumber));
            }
            catch (ApiCustomException ce)
            {
                LogHelper.Error(ce.Message, ce);
                return(Error(ce.ErrorCode, ce.ErrorMessage));
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.Message, ex);
                return(Error(ex.HResult, ex.Message));
            }
        }
Ejemplo n.º 13
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);
        }
Ejemplo n.º 14
0
        //result is List<txid + "," + vout>
        public long GetAllUnconfirmedBalance()
        {
            var  accountDac  = new AccountDac();
            long totalAmount = 0;

            foreach (var item in TransactionPool.Instance.MainPool)
            {
                foreach (var output in item.Transaction.Outputs)
                {
                    var address = AccountIdHelper.CreateAccountAddressByPublicKeyHash(
                        Base16.Decode(
                            Script.GetPublicKeyHashFromLockScript(output.LockScript)));

                    if (accountDac.SelectById(address) != null)
                    {
                        totalAmount += output.Amount;
                    }
                }
            }

            return(totalAmount);
        }
Ejemplo n.º 15
0
        public Account GenerateNewAccount()
        {
            var dac = new AccountDac();

            byte[] privateKey;
            byte[] publicKey;
            using (var dsa = ECDsa.GenerateNewKeyPair())
            {
                privateKey = dsa.PrivateKey;
                publicKey  = dsa.PublicKey;
            }

            var id = AccountIdHelper.CreateAccountAddress(publicKey);

            if (dac.IsExisted(id))
            {
                throw new Exception("Account id is existed");
            }

            Account account = new Account();

            account.Id          = id;
            account.PrivateKey  = Base16.Encode(privateKey);
            account.PublicKey   = Base16.Encode(publicKey);
            account.Balance     = 0;
            account.IsDefault   = false;
            account.WatchedOnly = false;

            dac.Insert(account);

            if (UtxoSet.Instance != null)
            {
                UtxoSet.Instance.AddAccountId(account.Id);
            }

            return(account);
        }
Ejemplo n.º 16
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);
        }
Ejemplo n.º 17
0
        public IRpcMethodResult ListUnspent(int minConfirmations, int maxConfirmations = 9999999, string[] addresses = null)
        {
            try
            {
                var result               = new List <ListUnspentOM>();
                var txComponent          = new TransactionComponent();
                var blockComponent       = new BlockComponent();
                var outputComponent      = new UtxoComponent();
                var accountComponent     = new AccountComponent();
                var addressBookComponent = new AddressBookComponent();

                var accounts     = accountComponent.GetAllAccounts();
                var transactions = txComponent.GetTransactionEntitiesContainUnspentUTXO();
                var latestHeight = blockComponent.GetLatestHeight();

                foreach (var tx in transactions)
                {
                    var blockMsg = blockComponent.GetBlockMsgByHash(tx.BlockHash);

                    if (blockMsg != null)
                    {
                        var confirmations = latestHeight - blockMsg.Header.Height;

                        if (confirmations >= minConfirmations && confirmations <= maxConfirmations)
                        {
                            var outputs = txComponent.GetOutputEntitesByTxHash(tx.Hash);

                            foreach (var output in outputs)
                            {
                                var pubKeyHash = Script.GetPublicKeyHashFromLockScript(output.LockScript);
                                var address    = AccountIdHelper.CreateAccountAddressByPublicKeyHash(Base16.Decode(pubKeyHash));

                                var account = accounts.Where(a => a.Id == address).FirstOrDefault();
                                if (account != null)
                                {
                                    if (addresses == null || addresses.Contains(address))
                                    {
                                        result.Add(new ListUnspentOM
                                        {
                                            txid          = output.TransactionHash,
                                            vout          = output.Index,
                                            address       = address,
                                            account       = addressBookComponent.GetTagByAddress(address),
                                            scriptPubKey  = output.LockScript,
                                            redeemScript  = null,
                                            amount        = output.Amount,
                                            confirmations = confirmations,
                                            spendable     = string.IsNullOrWhiteSpace(account.PrivateKey),
                                            solvable      = false
                                        });
                                    }
                                }
                            }
                        }
                    }
                }

                return(Ok(result));
            }
            catch (CommonException ce)
            {
                return(Error(ce.ErrorCode, ce.Message, ce));
            }
            catch (Exception ex)
            {
                return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
            }
        }
Ejemplo n.º 18
0
        public void AddTransactionToPool(TransactionMsg transaction)
        {
            var  accountDac  = new AccountDac();
            var  outputDac   = new OutputDac();
            long feeRate     = 0;
            long totalInput  = 0;
            long totalOutput = 0;

            foreach (var input in transaction.Inputs)
            {
                long   amount;
                string lockCript;
                long   blockHeight;

                if (this.getOutput(input.OutputTransactionHash, input.OutputIndex, out amount, out lockCript, out blockHeight))
                {
                    totalInput += amount;
                }
            }

            foreach (var output in transaction.Outputs)
            {
                totalOutput += output.Amount;
            }

            feeRate = (totalInput - totalOutput) / transaction.Size;

            try
            {
                long fee    = 0;
                var  result = this.VerifyTransaction(transaction, out fee);

                if (result)
                {
                    TransactionPool.Instance.AddNewTransaction(feeRate, transaction);

                    //recheck isolate transactions
                    var txList = TransactionPool.Instance.GetIsolateTransactions();

                    foreach (var tx in txList)
                    {
                        try
                        {
                            if (this.VerifyTransaction(tx, out fee))
                            {
                                TransactionPool.Instance.MoveIsolateTransactionToMainPool(tx.Hash);
                            }
                        }
                        catch
                        {
                        }
                    }
                }
                else
                {
                    TransactionPool.Instance.AddIsolateTransaction(feeRate, transaction);
                }

                foreach (var input in transaction.Inputs)
                {
                    outputDac.UpdateSpentStatus(input.OutputTransactionHash, input.OutputIndex);
                    UtxoSet.Instance.RemoveUtxoRecord(input.OutputTransactionHash, input.OutputIndex);
                }

                foreach (var output in transaction.Outputs)
                {
                    var accountId = AccountIdHelper.CreateAccountAddressByPublicKeyHash(
                        Base16.Decode(
                            Script.GetPublicKeyHashFromLockScript(output.LockScript)
                            )
                        );

                    UtxoSet.Instance.AddUtxoRecord(new UtxoMsg
                    {
                        AccountId       = accountId,
                        BlockHash       = null,
                        TransactionHash = transaction.Hash,
                        OutputIndex     = output.Index,
                        Amount          = output.Amount,
                        IsConfirmed     = false
                    });
                }
            }
            catch (CommonException ex)
            {
                throw ex;
            }
        }
Ejemplo n.º 19
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);
        }
Ejemplo n.º 20
0
 public static bool PoolAccount(string account)
 {
     return(AccountIdHelper.AddressVerify(account));
 }
Ejemplo n.º 21
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));
            }
        }
Ejemplo n.º 22
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));
            }
        }
Ejemplo n.º 23
0
        private Block convertBlockMsgToEntity(BlockMsg blockMsg)
        {
            OutputDac outputDac = new OutputDac();

            var block = new Block();

            block.Hash              = blockMsg.Header.Hash;
            block.Version           = blockMsg.Header.Version;
            block.Height            = blockMsg.Header.Height;
            block.PreviousBlockHash = blockMsg.Header.PreviousBlockHash;
            block.Bits              = blockMsg.Header.Bits;
            block.Nonce             = blockMsg.Header.Nonce;
            block.GeneratorId       = blockMsg.Header.GeneratorId;
            block.Timestamp         = blockMsg.Header.Timestamp;
            block.TotalAmount       = 0;
            block.TotalFee          = 0;

            block.Transactions = new List <Transaction>();

            foreach (var txMsg in blockMsg.Transactions)
            {
                var transaction = new Transaction();

                transaction.Hash      = txMsg.Hash;
                transaction.BlockHash = block.Hash;
                transaction.Version   = txMsg.Version;
                transaction.Timestamp = txMsg.Timestamp;
                transaction.LockTime  = txMsg.Locktime;
                transaction.Inputs    = new List <Input>();
                transaction.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;
                    }

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

                foreach (var outputMsg in txMsg.Outputs)
                {
                    var output = new Output();
                    output.Index           = outputMsg.Index;
                    output.TransactionHash = transaction.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;
                    transaction.Outputs.Add(output);
                    totalOutput += output.Amount;
                }

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

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

                block.Transactions.Add(transaction);
                block.TotalAmount += transaction.TotalOutput;
                block.TotalFee    += transaction.Fee;
            }

            //block.GenerationSignature = blockMsg.Header.GenerationSignature;
            block.BlockSignature = blockMsg.Header.BlockSignature;
            //block.CumulativeDifficulty = blockMsg.Header.CumulativeDifficulty;
            block.PayloadHash = blockMsg.Header.PayloadHash;
            block.IsVerified  = false;
            return(block);
        }
Ejemplo n.º 24
0
        public void SaveBlockIntoDB(BlockMsg msg)
        {
            try
            {
                VerifyBlock(msg);

                Block block = this.convertBlockMsgToEntity(msg);
                block.IsDiscarded = false;
                block.IsVerified  = false;

                var blockDac       = new BlockDac();
                var transactionDac = new TransactionDac();
                var inputDac       = new InputDac();
                var outputDac      = new OutputDac();

                //foreach (var tx in block.Transactions)
                //{
                //    foreach (var input in tx.Inputs)
                //    {
                //        if (input.OutputTransactionHash != Base16.Encode(HashHelper.EmptyHash()))
                //        {
                //            var output = outputDac.SelectByHashAndIndex(input.OutputTransactionHash, input.OutputIndex);

                //            if (output != null)
                //            {
                //                input.AccountId = output.ReceiverId;
                //                outputDac.UpdateSpentStatus(input.OutputTransactionHash, input.OutputIndex);
                //            }
                //        }
                //    }
                //}

                blockDac.Save(block);

                //update nextblock hash
                //blockDac.UpdateNextBlockHash(block.PreviousBlockHash, block.Hash);

                //remove transactions in tx pool
                foreach (var tx in block.Transactions)
                {
                    TransactionPool.Instance.RemoveTransaction(tx.Hash);

                    //save into utxo set
                    foreach (var output in tx.Outputs)
                    {
                        var accountId = AccountIdHelper.CreateAccountAddressByPublicKeyHash(
                            Base16.Decode(
                                Script.GetPublicKeyHashFromLockScript(output.LockScript)
                                )
                            );

                        UtxoSet.Instance.AddUtxoRecord(new UtxoMsg
                        {
                            AccountId       = accountId,
                            BlockHash       = block.Hash,
                            TransactionHash = tx.Hash,
                            OutputIndex     = output.Index,
                            Amount          = output.Amount,
                            IsConfirmed     = true
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.Message, ex);
                throw ex;
            }
        }
Ejemplo n.º 25
0
        public CommonResponse SubmitMaxNonce([FromBody] MaxNonceIM model)
        {
            try
            {
                if (model == null)
                {
                    return(Error(Entities.MiningPoolErrorCode.Miners.COMMON_ERROR, "Posted data error"));
                }

                try
                {
                    LogHelper.Info($"Address is {model.Address}, network is {GlobalParameters.IsTestnet}");
                    if (!AccountIdHelper.AddressVerify(model.Address))
                    {
                        return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_IS_INVALID, $"Address {model.Address}is invalid"));
                    }
                }
                catch
                {
                    return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_IS_INVALID, $"Address {model.Address} is invalid"));
                }

                var miner = MinersJob.Current.Pool_Miners.FirstOrDefault(m => m.Address == model.Address);

                if (miner == null)
                {
                    return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_NOT_EXIST, $"Address {model.Address} not exist"));
                }
                else if (miner.SN != model.SN)
                {
                    return(Error(Entities.MiningPoolErrorCode.Miners.SN_CODE_ERROR, $"SN code {model.SN} with address {model.Address} is error"));
                }

                var scoopNumberKey = "Pool:MinerScoopNumber:" + model.Address;
                var maxNonceKey    = "Pool:MinerMaxNonce:" + model.Address;

                var scoopNumber = RedisManager.Current.GetDataInRedis <string>(scoopNumberKey);

                if (scoopNumber == null || scoopNumber != model.ScoopNumber.ToString())
                {
                    return(Error(Entities.MiningPoolErrorCode.Miners.SCOOPNUMBER_NOT_MATCH, $"Scoop number from address {model.Address} SN {model.SN} is not matched: {scoopNumber}/{model.ScoopNumber}"));
                }

                if (model.MaxNonce > MaxNonceLimit)
                {
                    return(Error(Entities.MiningPoolErrorCode.Miners.MAXNONCE_IS_INVALID, $"Max nonce {model.MaxNonce} from address {model.Address} is invalid"));
                }

                //var data = POC.CalculateScoopData(model.Address, model.MaxNonce, model.ScoopNumber);

                //try
                //{
                //    var scoopData = Convert.FromBase64String(model.ScoopData);

                //    if (Base16.Encode(data) != Base16.Encode(scoopData))
                //    {
                //        return Error(Entities.MiningPoolErrorCode.Miners.SCOOP_DATA_IS_INVALID, "Scoop data is invalid");
                //    }
                //}
                //catch
                //{
                //    return Error(Entities.MiningPoolErrorCode.Miners.SCOOP_DATA_IS_INVALID, "Scoop data is invalid");
                //}

                RedisManager.Current.SaveDataToRedis <string>(maxNonceKey, model.MaxNonce.ToString(), MaxNonceTimeout);
                return(OK(true));
            }
            catch (ApiCustomException ce)
            {
                LogHelper.Error(ce.Message);
                return(Error(ce.ErrorCode, ce.ErrorMessage));
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.Message, ex);
                return(Error(ex.HResult, ex.Message));
            }
        }