Ejemplo n.º 1
0
        public void DeleteTransaction(int transactionId, bool updateStock)
        {
            SaleManager         sm    = new SaleManager();
            List <SalePurchase> sales = sm.GetSalesByTransactionID(transactionId);

            foreach (SalePurchase s in sales)
            {
                sm.DeleteSale(s.ID, updateStock);
            }
            sales.Clear();
            sm = null;

            PaymentManager pm = new PaymentManager();
            Payment        p  = pm.GetPaymentByTransactionID(transactionId);

            if (p == null)
            {
                p    = new Payment();
                p.ID = -1;
            }
            pm.DeletePayment(p.ID);
            p  = null;
            pm = null;

            TransactionCache.GetInstance().DeleteTransaction(transactionId);
        }
Ejemplo n.º 2
0
        private void sendPayment(string txfee)
        {
            Logging.info("Preparing to send payment");
            //Navigation.PopAsync(Config.defaultXamarinAnimations);

            // Create an ixian transaction and send it to the dlt network
            IxiNumber fee = CoreConfig.transactionPrice;

            byte[] from   = Node.walletStorage.getPrimaryAddress();
            byte[] pubKey = Node.walletStorage.getPrimaryPublicKey();
            Logging.info("Preparing tx");

            Transaction transaction = new Transaction((int)Transaction.Type.Normal, fee, to_list, from, null, pubKey, Node.getLastBlockHeight());

            Logging.info("Broadcasting tx");

            NetworkClientManager.broadcastData(new char[] { 'M' }, ProtocolMessageCode.newTransaction, transaction.getBytes(), null);
            Logging.info("Adding to cache");

            // Add the unconfirmed transaction the the cache
            TransactionCache.addUnconfirmedTransaction(transaction);
            Logging.info("Showing payment details");

            // Show the payment details
            Navigation.PushAsync(new WalletSentPage(transaction), Config.defaultXamarinAnimations);
        }
Ejemplo n.º 3
0
 //重载OnRecvDataMsg方法,接收行情数据
 // 请注意:
 //  1. 不要在这个函数里做耗时操作
 //  2. 只在这个函数里做数据获取工作 -- 将数据复制到其它数据缓存区,由其它线程做业务逻辑处理
 public override void OnRecvDataMsg(TDFMSG msg)
 {
     if (msg.MsgID == TDFMSGID.MSG_DATA_MARKET)
     {
         //行情消息
         TDFMarketData[] marketDataArr = msg.Data as TDFMarketData[];
         MarketDataCache.Enqueue(marketDataArr);
     }
     else if (msg.MsgID == TDFMSGID.MSG_DATA_TRANSACTION)
     {
         //逐笔成交
         TDFTransaction[] transactionDataArr = msg.Data as TDFTransaction[];
         TransactionCache.Enqueue(transactionDataArr);
     }
     else if (msg.MsgID == TDFMSGID.MSG_DATA_ORDER)
     {
         //逐笔委托
         TDFOrder[] orderDataArr = msg.Data as TDFOrder[];
         OrderCache.Enqueue(orderDataArr);
     }
     else if (msg.MsgID == TDFMSGID.MSG_DATA_ORDERQUEUE)
     {
         //委托队列
         TDFOrderQueue[] orderQueueDataArr = msg.Data as TDFOrderQueue[];
         OrderQueueCache.Enqueue(orderQueueDataArr);
     }
 }
Ejemplo n.º 4
0
        // Retrieve the transaction from local cache storage
        private void checkTransaction()
        {
            string      confirmed_text = SpixiLocalization._SL("wallet-sent-confirmed");
            Transaction ctransaction   = TransactionCache.getTransaction(transaction.id);

            if (ctransaction == null || ctransaction.applied == 0)
            {
                ctransaction   = transaction;
                confirmed_text = SpixiLocalization._SL("wallet-sent-unconfirmed");
            }

            IxiNumber amount = ctransaction.amount;

            // Convert unix timestamp
            string time = Utils.UnixTimeStampToString(Convert.ToDouble(ctransaction.timeStamp));

            byte[] addr = new Address(ctransaction.pubKey).address;
            if (addr.SequenceEqual(IxianHandler.getWalletStorage().getPrimaryAddress()))
            {
                // this is a sent payment

                foreach (var entry in ctransaction.toList)
                {
                    //Utils.sendUiCommand(webView, "addSender", Base58Check.Base58CheckEncoding.EncodePlain(entry.Key) + ": " + entry.Value.ToString(), time);
                    Utils.sendUiCommand(webView, "addSender", Encoding.ASCII.GetString(ctransaction.data) + ": " + entry.Value.ToString(), time);
                }
            }

            Utils.sendUiCommand(webView, "setData", amount.ToString(), ctransaction.fee.ToString(),
                                time, confirmed_text, (ctransaction.fee / ctransaction.amount).ToString() + "%", Transaction.txIdV8ToLegacy(transaction.id));
            return;
        }
Ejemplo n.º 5
0
        public CacheContext(IStorageContext storageContext)
        {
            this._storageContext = storageContext;

            this._blockStorage = new BlockStorage(this);
            this._blockCache = new BlockCache
            (
                cacheContext: this,
                maxFlushMemorySize: 10.MILLION(),
                maxCacheMemorySize: 1.MILLION()
            );

            this._blockHeaderCache = new BlockHeaderCache
            (
                cacheContext: this,
                maxFlushMemorySize: 10.MILLION(),
                maxCacheMemorySize: 1.MILLION()
            );

            this._chainedBlockCache = new ChainedBlockCache
            (
                cacheContext: this,
                maxFlushMemorySize: 1.MILLION(),
                maxCacheMemorySize: 100.MILLION()
            );

            this._transactionCache = new TransactionCache
            (
                cacheContext: this,
                maxCacheMemorySize: 1.MILLION()
            );
        }
Ejemplo n.º 6
0
        public void onDeleteWallet(object sender, EventArgs e)
        {
            if (Node.walletStorage.deleteWallet())
            {
                Node.walletStorage = new WalletStorage(Path.Combine(Config.spixiUserFolder, Config.walletFile));

                // Also delete the account
                onDeleteAccount();

                // Stop network activity
                Node.stop();

                Application.Current.Properties.Remove("onboardingComplete");
                Application.Current.SavePropertiesAsync();  // Force-save properties for compatibility with WPF

                SpixiLocalization.addCustomString("OnboardingComplete", "false");

                Node.localStorage.deleteTransactionCacheFile();
                TransactionCache.clearAllTransactions();
                Node.tiv.clearCache();

                // Show the launch page
                Navigation.PushAsync(new LaunchPage(), Config.defaultXamarinAnimations);

                // Remove the settings page
                Navigation.RemovePage(this);

                // Todo: also remove the parent page without causing memory leaks
            }
            else
            {
                displaySpixiAlert(SpixiLocalization._SL("settings-deletew-error-title"), SpixiLocalization._SL("settings-deletew-error-text"), SpixiLocalization._SL("global-dialog-ok"));
            }
        }
Ejemplo n.º 7
0
        // Retrieve the transaction from local cache storage
        private void checkTransaction()
        {
            string      confirmed_text = "CONFIRMED";
            Transaction ctransaction   = TransactionCache.getTransaction(transaction.id);

            if (ctransaction == null || ctransaction.applied == 0)
            {
                requestTransactionData();
                ctransaction   = transaction;
                confirmed_text = "UNCONFIRMED";
            }

            IxiNumber amount = ctransaction.amount;

            string addresses = "";

            byte[] addr = new Address(ctransaction.pubKey).address;
            if (addr.SequenceEqual(Node.walletStorage.getPrimaryAddress()))
            {
                // this is a sent payment

                foreach (var entry in ctransaction.toList)
                {
                    Friend friend = FriendList.getFriend(entry.Key);
                    if (friend != null)
                    {
                        addresses += friend.nickname + ": " + entry.Value.ToString() + "|";
                    }
                    else
                    {
                        addresses += Base58Check.Base58CheckEncoding.EncodePlain(entry.Key) + ": " + entry.Value.ToString() + "|";
                    }
                }
            }
            else
            {
                // this is a received payment

                amount = 0;

                Utils.sendUiCommand(webView, "setReceivedMode");
                foreach (var entry in ctransaction.toList)
                {
                    if (entry.Key.SequenceEqual(Node.walletStorage.getPrimaryAddress()))
                    {
                        addresses += Base58Check.Base58CheckEncoding.EncodePlain(entry.Key) + ": " + entry.Value.ToString() + "|";
                        amount    += entry.Value;
                    }
                }
            }

            // Convert unix timestamp
            string time = Utils.UnixTimeStampToString(Convert.ToDouble(ctransaction.timeStamp));

            Utils.sendUiCommand(webView, "setData", amount.ToString(), ctransaction.fee.ToString(),
                                addresses, time, confirmed_text, (ctransaction.fee / amount).ToString() + "%");
            return;
        }
Ejemplo n.º 8
0
 public BTCPayWallet(ExplorerClient client, TransactionCache cache, BTCPayNetwork network)
 {
     if (client == null)
     {
         throw new ArgumentNullException(nameof(client));
     }
     _Client  = client;
     _Network = network;
     _Cache   = cache;
 }
Ejemplo n.º 9
0
        public PruningWorker(WorkerConfig workerConfig, Func <ChainStateBuilder> getChainStateBuilder, Logger logger, IBlockchainRules rules, BlockTxHashesCache blockTxHashesCache, TransactionCache transactionCache, SpentTransactionsCache spentTransactionsCache, SpentOutputsCache spentOutputsCache)
            : base("PruningWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger)
        {
            this.getChainStateBuilder = getChainStateBuilder;
            this.rules = rules;
            this.blockTxHashesCache     = blockTxHashesCache;
            this.transactionCache       = transactionCache;
            this.spentTransactionsCache = spentTransactionsCache;
            this.spentOutputsCache      = spentOutputsCache;

            this.Mode = PruningMode.SpentOnly;
        }
Ejemplo n.º 10
0
        public async Task <IEnumerable <Transaction> > GetTransactionsAsync(Network network, IEnumerable <uint256> txHashes, CancellationToken cancel)
        {
            var allTxs          = new List <Transaction>();
            var txHashesToQuery = new List <uint256>();

            lock (TransactionCacheLock)
            {
                var cachedTxs = TransactionCache.Where(x => txHashes.Contains(x.Key));
                allTxs.AddRange(cachedTxs.Select(x => x.Value));
                txHashesToQuery.AddRange(txHashes.Except(cachedTxs.Select(x => x.Key)));
            }

            foreach (IEnumerable <uint256> chunk in txHashesToQuery.ChunkBy(10))
            {
                cancel.ThrowIfCancellationRequested();

                using var response = await TorClient.SendAndRetryAsync(
                          HttpMethod.Get,
                          HttpStatusCode.OK,
                          $"/api/v{Constants.BackendMajorVersion}/btc/blockchain/transaction-hexes?&transactionIds={string.Join("&transactionIds=", chunk.Select(x => x.ToString()))}",
                          cancel : cancel);

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    await response.ThrowRequestExceptionFromContentAsync();
                }

                using HttpContent content = response.Content;
                var retString = await content.ReadAsJsonAsync <IEnumerable <string> >();

                var ret = retString.Select(x => Transaction.Parse(x, network)).ToList();

                lock (TransactionCacheLock)
                {
                    foreach (var tx in ret)
                    {
                        tx.PrecomputeHash(false, true);
                        if (TransactionCache.TryAdd(tx.GetHash(), tx))
                        {
                            TransactionIdQueue.Enqueue(tx.GetHash());
                            if (TransactionCache.Count > 1000)                             // No more than 1000 txs in cache
                            {
                                var toRemove = TransactionIdQueue.Dequeue();
                                TransactionCache.Remove(toRemove);
                            }
                        }
                    }
                }
                allTxs.AddRange(ret);
            }

            return(allTxs.ToDependencyGraph().OrderByDependency());
        }
Ejemplo n.º 11
0
        private void sendPayment(string txfee)
        {
            Logging.info("Preparing to send payment");
            //Navigation.PopAsync(Config.defaultXamarinAnimations);

            // Create an ixian transaction and send it to the dlt network
            IxiNumber fee = ConsensusConfig.transactionPrice;

            byte[] from   = Node.walletStorage.getPrimaryAddress();
            byte[] pubKey = Node.walletStorage.getPrimaryPublicKey();
            Logging.info("Preparing tx");

            Transaction transaction = new Transaction((int)Transaction.Type.Normal, fee, to_list, from, null, pubKey, IxianHandler.getHighestKnownNetworkBlockHeight());

            Logging.info("Broadcasting tx");

            IxianHandler.addTransaction(transaction);
            Logging.info("Adding to cache");

            // Add the unconfirmed transaction to the cache
            TransactionCache.addUnconfirmedTransaction(transaction);
            Logging.info("Showing payment details");

            // Send message to recipients
            foreach (var entry in to_list)
            {
                Friend friend = FriendList.getFriend(entry.Key);

                if (friend != null)
                {
                    FriendMessage friend_message = FriendList.addMessageWithType(null, FriendMessageType.sentFunds, entry.Key, transaction.id, true);

                    SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.sentFunds, Encoding.UTF8.GetBytes(transaction.id));

                    StreamMessage message = new StreamMessage();
                    message.type        = StreamMessageCode.info;
                    message.recipient   = friend.walletAddress;
                    message.sender      = Node.walletStorage.getPrimaryAddress();
                    message.transaction = new byte[1];
                    message.sigdata     = new byte[1];
                    message.data        = spixi_message.getBytes();
                    message.id          = friend_message.id;

                    StreamProcessor.sendMessage(friend, message);
                }
            }

            // Show the payment details
            Navigation.PushAsync(new WalletSentPage(transaction, false), Config.defaultXamarinAnimations);
        }
Ejemplo n.º 12
0
        public LocalClient(Logger logger, RulesEnum type, IKernel kernel, IBlockchainRules rules, CoreDaemon blockchainDaemon, BlockHeaderCache blockHeaderCache, ChainedHeaderCache chainedHeaderCache, TransactionCache transactionCache, BlockCache blockCache, NetworkPeerCache networkPeerCache)
        {
            this.shutdownToken = new CancellationTokenSource();

            this.logger             = logger;
            this.type               = type;
            this.kernel             = kernel;
            this.rules              = rules;
            this.blockchainDaemon   = blockchainDaemon;
            this.blockHeaderCache   = blockHeaderCache;
            this.chainedHeaderCache = chainedHeaderCache;
            this.transactionCache   = transactionCache;
            this.blockCache         = blockCache;
            this.networkPeerCache   = networkPeerCache;

            this.messageRateMeasure = new RateMeasure();

            this.connectWorker        = new WorkerMethod("LocalClient.ConnectWorker", ConnectWorker, true, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), this.logger);
            this.headersRequestWorker = kernel.Get <HeadersRequestWorker>(
                new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(50), maxIdleTime: TimeSpan.FromSeconds(30))),
                new ConstructorArgument("localClient", this));
            this.blockRequestWorker = kernel.Get <BlockRequestWorker>(
                new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(50), maxIdleTime: TimeSpan.FromSeconds(30))),
                new ConstructorArgument("localClient", this));
            this.statsWorker = new WorkerMethod("LocalClient.StatsWorker", StatsWorker, true, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(30), this.logger);

            switch (this.Type)
            {
            case RulesEnum.MainNet:
                Messaging.Port  = 8333;
                Messaging.Magic = Messaging.MAGIC_MAIN;
                break;

            case RulesEnum.TestNet3:
                Messaging.Port  = 18333;
                Messaging.Magic = Messaging.MAGIC_TESTNET3;
                break;

            case RulesEnum.ComparisonToolTestNet:
                Messaging.Port  = 18444;
                Messaging.Magic = Messaging.MAGIC_COMPARISON_TOOL;
                break;
            }
        }
Ejemplo n.º 13
0
        public override void receivedTransactionInclusionVerificationResponse(string txid, bool verified)
        {
            // TODO implement error
            // TODO implement blocknum

            if (verified)
            {
                Transaction tx = TransactionCache.getUnconfirmedTransaction(txid);
                if (tx != null)
                {
                    TransactionCache.addTransaction(tx);
                    Page p = App.Current.MainPage.Navigation.NavigationStack.Last();
                    if (p.GetType() == typeof(SingleChatPage))
                    {
                        ((SingleChatPage)p).updateTransactionStatus(txid, verified);
                    }
                }
            }
        }
Ejemplo n.º 14
0
        public List <Transaction> GetTransactionsByItem(int itemId)
        {
            List <Transaction> transactionsWithGivenItem;

            try
            {
                transactionsWithGivenItem = TransactionCache.GetInstance().GetTransactionsByItem(itemId);
            }
            catch (Exception)
            {
                //in case of errors, return empty array of transactions
                transactionsWithGivenItem = new List <Transaction>();
            }
            //if (transactionsWithGivenItem.Count == 0)
            //{

            //}
            return(transactionsWithGivenItem);
        }
        private void onSend()
        {
            // Create an ixian transaction and send it to the dlt network
            byte[] to = friend.walletAddress;

            IxiNumber amounti = new IxiNumber(amount);
            IxiNumber fee     = CoreConfig.transactionPrice;

            byte[] from   = Node.walletStorage.getPrimaryAddress();
            byte[] pubKey = Node.walletStorage.getPrimaryPublicKey();

            Transaction transaction = new Transaction((int)Transaction.Type.Normal, amount, fee, to, from, null, pubKey, Node.getLastBlockHeight());

            NetworkClientManager.broadcastData(new char[] { 'M' }, ProtocolMessageCode.newTransaction, transaction.getBytes(), null);

            // Add the unconfirmed transaction the the cache
            TransactionCache.addUnconfirmedTransaction(transaction);
            FriendList.addMessageWithType(FriendMessageType.sentFunds, friend.walletAddress, transaction.id);
            Navigation.PopAsync(Config.defaultXamarinAnimations);
        }
Ejemplo n.º 16
0
        // Retrieve the transaction from local cache storage
        private bool checkTransaction()
        {
            Transaction ctransaction = TransactionCache.getTransaction(transaction.id);

            if (ctransaction == null)
            {
                requestTransactionData();
                return(true);
            }

            string nickname = "Unknown";
            Friend friend   = null;

            byte[] addr = ctransaction.toList.Keys.First();
            // Check if this is a received payment
            if (addr.SequenceEqual(Node.walletStorage.getPrimaryAddress()))
            {
                // TODO FIXME

                /*      webView.Eval("setReceivedMode()");
                 *    friend = FriendList.getFriend(transaction.from);
                 *    addr = ctransaction.from;*/
            }
            else
            {
                // This is a sent payment
                friend = FriendList.getFriend(addr);
            }

            if (friend != null)
            {
                nickname = friend.nickname;
            }

            // Convert unix timestamp
            string time = Utils.UnixTimeStampToString(Convert.ToDouble(ctransaction.timeStamp));

            webView.Eval(string.Format("setConfirmedData('{0}', '{1}', '{2}', '{3}', '{4}')", ctransaction.amount.ToString(), ctransaction.fee.ToString(),
                                       Base58Check.Base58CheckEncoding.EncodePlain(addr), nickname, time));
            return(false);
        }
Ejemplo n.º 17
0
        private void sendPayment(string txfee)
        {
            Logging.info("Preparing to send payment");
            //Navigation.PopAsync(Config.defaultXamarinAnimations);

            Logging.info("Broadcasting tx");

            IxianHandler.addTransaction(transaction);
            Logging.info("Adding to cache");

            // Add the unconfirmed transaction to the cache
            TransactionCache.addUnconfirmedTransaction(transaction);
            Logging.info("Showing payment details");

            // Send message to recipients
            foreach (var entry in to_list)
            {
                Friend friend = FriendList.getFriend(entry.Key);

                if (friend != null)
                {
                    FriendMessage friend_message = FriendList.addMessageWithType(null, FriendMessageType.sentFunds, entry.Key, transaction.id, true);

                    SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.sentFunds, Encoding.UTF8.GetBytes(transaction.id));

                    StreamMessage message = new StreamMessage();
                    message.type        = StreamMessageCode.info;
                    message.recipient   = friend.walletAddress;
                    message.sender      = Node.walletStorage.getPrimaryAddress();
                    message.transaction = new byte[1];
                    message.sigdata     = new byte[1];
                    message.data        = spixi_message.getBytes();
                    message.id          = friend_message.id;

                    StreamProcessor.sendMessage(friend, message);
                }
            }

            // Show the payment details
            Navigation.PushAsync(new WalletSentPage(transaction, false), Config.defaultXamarinAnimations);
        }
Ejemplo n.º 18
0
        public void DeleteTransaction(int transactionId)
        {
            SaleManager sm    = new SaleManager();
            List <Sale> sales = sm.GetSalesByTransactionID(transactionId);

            foreach (Sale s in sales)
            {
                sm.DeleteSale(s.ID);
            }
            sales.Clear();
            sm = null;

            PaymentManager pm = new PaymentManager();
            Payment        p  = pm.GetPaymentByTransactionID(transactionId);

            pm.DeletePayment(p.ID);
            p  = null;
            pm = null;

            TransactionCache.GetInstance().DeleteTransaction(transactionId);
        }
Ejemplo n.º 19
0
 public void ClearCache()
 {
     TDFMarketData[] tmp;
     while (MarketDataCache.TryDequeue(out tmp) == true)
     {
         ;
     }
     TDFTransaction[] tmp2;
     while (TransactionCache.TryDequeue(out tmp2) == true)
     {
         ;
     }
     TDFOrder[] tmp3;
     while (OrderCache.TryDequeue(out tmp3) == true)
     {
         ;
     }
     TDFOrderQueue[] tmp4;
     while (OrderQueueCache.TryDequeue(out tmp4) == true)
     {
         ;
     }
 }
Ejemplo n.º 20
0
        private void sendPayment(string ethaddress, IxiNumber amount)
        {
            IxiNumber fee = ConsensusConfig.transactionPrice;

            byte[] from   = IxianHandler.getWalletStorage().getPrimaryAddress();
            byte[] pubKey = IxianHandler.getWalletStorage().getPrimaryPublicKey();


            byte[] _address = Base58Check.Base58CheckEncoding.DecodePlain(Config.bridgeAddress);
            to_list.AddOrReplace(_address, amount);

            byte[] _txdata = Encoding.ASCII.GetBytes(ethaddress);

            transaction = new Transaction((int)Transaction.Type.Normal, fee, to_list, from, _txdata, pubKey, IxianHandler.getHighestKnownNetworkBlockHeight());

            IxiNumber total_amount = transaction.amount + transaction.fee;

            if (Node.balance.balance < total_amount)
            {
                displaySpixiAlert(SpixiLocalization._SL("wallet-error-balance-title"), string.Format(SpixiLocalization._SL("wallet-error-balance-text"), total_amount.ToString(), Node.balance.balance.ToString()), SpixiLocalization._SL("global-dialog-ok"));
                Navigation.PopAsync(Config.defaultXamarinAnimations);
                return;
            }

            Logging.info("Preparing to send payment");

            Logging.info("Broadcasting tx");

            IxianHandler.addTransaction(transaction, true);
            Logging.info("Adding to cache");

            // Add the unconfirmed transaction to the cache
            TransactionCache.addUnconfirmedTransaction(transaction);


            Navigation.PushAsync(new WIXISentPage(transaction), Config.defaultXamarinAnimations);
        }
Ejemplo n.º 21
0
        public override void receivedTransactionInclusionVerificationResponse(byte[] txid, bool verified)
        {
            // TODO implement error
            // TODO implement blocknum
            Transaction tx = TransactionCache.getUnconfirmedTransaction(txid);

            if (tx == null)
            {
                return;
            }

            if (!verified)
            {
                tx.applied = 0;
            }

            TransactionCache.addTransaction(tx);
            Page p = App.Current.MainPage.Navigation.NavigationStack.Last();

            if (p.GetType() == typeof(SingleChatPage))
            {
                ((SingleChatPage)p).updateTransactionStatus(Transaction.txIdV8ToLegacy(txid), verified);
            }
        }
Ejemplo n.º 22
0
 internal double GetTransactionSumTotalByCustomerId(int customerID, DateTime startDate)
 {
     return(TransactionCache.GetInstance().GetTransactionSumTotalByCustomerId(customerID, startDate));
 }
Ejemplo n.º 23
0
 internal void RefreshCache()
 {
     TransactionCache.GetInstance().Clear();
     TransactionCache.GetInstance();
 }
Ejemplo n.º 24
0
        public void insertMessage(FriendMessage message)
        {
            if (friend.approved == false)
            {
                if (message.type == FriendMessageType.requestAdd)
                {
                    // Call webview methods on the main UI thread only
                    Utils.sendUiCommand(webView, "showContactRequest", "1");
                    message.read = true;
                    return;
                }
            }
            else
            {
                // Don't show if the friend is already approved
                if (message.type == FriendMessageType.requestAdd)
                {
                    return;
                }
            }

            string prefix  = "addMe";
            string avatar  = "";
            string address = "";
            string nick    = "";

            if (!message.localSender)
            {
                if (friend.bot)
                {
                    if (message.senderAddress != null)
                    {
                        address = Base58Check.Base58CheckEncoding.EncodePlain(message.senderAddress);
                    }

                    nick = message.senderNick;
                    if (nick == "")
                    {
                        if (message.senderAddress != null && friend.contacts.ContainsKey(message.senderAddress))
                        {
                            nick = friend.contacts[message.senderAddress].nick;
                        }
                    }

                    if (nick == "")
                    {
                        nick = address;
                    }
                }

                prefix = "addThem";
                if (message.senderAddress != null)
                {
                    avatar = Node.localStorage.getAvatarPath(Base58Check.Base58CheckEncoding.EncodePlain(message.senderAddress));
                }
                else
                {
                    avatar = Node.localStorage.getAvatarPath(Base58Check.Base58CheckEncoding.EncodePlain(friend.walletAddress));
                }
                if (avatar == null)
                {
                    avatar = "img/spixiavatar.png";
                }
            }

            if (message.type == FriendMessageType.requestFunds)
            {
                string status      = "WAITING CONFIRMATION";
                string status_icon = "fa-clock";

                string amount = message.message;

                string txid = "";

                bool enableView = false;

                if (!message.localSender)
                {
                    enableView = true;
                }

                if (message.message.StartsWith("::"))
                {
                    status      = "DECLINED";
                    status_icon = "fa-exclamation-circle";
                    amount      = message.message.Substring(2);
                    txid        = Crypto.hashToString(message.id);
                    enableView  = false;
                }
                else if (message.message.StartsWith(":"))
                {
                    status = "PENDING";
                    txid   = message.message.Substring(1);

                    bool        confirmed   = true;
                    Transaction transaction = TransactionCache.getTransaction(txid);
                    if (transaction == null)
                    {
                        transaction = TransactionCache.getUnconfirmedTransaction(txid);
                        confirmed   = false;
                    }

                    amount = "?";

                    if (transaction != null)
                    {
                        amount = transaction.amount.ToString();

                        if (confirmed)
                        {
                            status      = "CONFIRMED";
                            status_icon = "fa-check-circle";
                        }
                    }
                    else
                    {
                        // TODO think about how to make this more private
                        CoreProtocolMessage.broadcastGetTransaction(txid, 0, null);
                    }
                    enableView = true;
                }


                if (message.localSender)
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), txid, address, nick, avatar, "Payment request SENT", amount, status, status_icon, message.timestamp.ToString(), message.localSender.ToString(), message.confirmed.ToString(), message.read.ToString(), enableView.ToString());
                }
                else
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), txid, address, nick, avatar, "Payment request RECEIVED", amount, status, status_icon, message.timestamp.ToString(), "", message.confirmed.ToString(), message.read.ToString(), enableView.ToString());
                }
            }

            if (message.type == FriendMessageType.sentFunds)
            {
                bool        confirmed   = true;
                Transaction transaction = TransactionCache.getTransaction(message.message);
                if (transaction == null)
                {
                    transaction = TransactionCache.getUnconfirmedTransaction(message.message);
                    confirmed   = false;
                }

                string status      = "PENDING";
                string status_icon = "fa-clock";

                string amount = "?";

                if (transaction != null)
                {
                    if (confirmed)
                    {
                        status      = "CONFIRMED";
                        status_icon = "fa-check-circle";
                    }
                    if (message.localSender)
                    {
                        amount = transaction.amount.ToString();
                    }
                    else
                    {
                        amount = HomePage.calculateReceivedAmount(transaction).ToString();
                    }
                }
                else
                {
                    // TODO think about how to make this more private
                    CoreProtocolMessage.broadcastGetTransaction(message.message, 0, null);
                }

                // Call webview methods on the main UI thread only
                if (message.localSender)
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), message.message, address, nick, avatar, "Payment SENT", amount, status, status_icon, message.timestamp.ToString(), message.localSender.ToString(), message.confirmed.ToString(), message.read.ToString(), "True");
                }
                else
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), message.message, address, nick, avatar, "Payment RECEIVED", amount, status, status_icon, message.timestamp.ToString(), "", message.confirmed.ToString(), message.read.ToString(), "True");
                }
            }


            if (message.type == FriendMessageType.fileHeader)
            {
                string[] split = message.message.Split(new string[] { ":" }, StringSplitOptions.None);
                if (split != null && split.Length > 1)
                {
                    string uid  = split[0];
                    string name = split[1];

                    string progress = "0";
                    if (message.completed)
                    {
                        progress = "100";
                    }
                    Utils.sendUiCommand(webView, "addFile", Crypto.hashToString(message.id), address, nick, avatar, uid, name, message.timestamp.ToString(), message.localSender.ToString(), message.confirmed.ToString(), message.read.ToString(), progress, message.completed.ToString());
                }
            }

            if (message.type == FriendMessageType.standard)
            {
                // Normal chat message
                // Call webview methods on the main UI thread only
                Utils.sendUiCommand(webView, prefix, Crypto.hashToString(message.id), address, nick, avatar, message.message, message.timestamp.ToString(), message.confirmed.ToString(), message.read.ToString());
            }
            updateMessageReadStatus(message);
        }
Ejemplo n.º 25
0
        // Retrieve the transaction from local cache storage
        private void checkTransaction()
        {
            string      confirmed_text = SpixiLocalization._SL("wallet-sent-confirmed");
            Transaction ctransaction   = TransactionCache.getTransaction(transaction.id);

            if (ctransaction == null || ctransaction.applied == 0)
            {
                ctransaction   = transaction;
                confirmed_text = SpixiLocalization._SL("wallet-sent-unconfirmed");
            }

            IxiNumber amount = ctransaction.amount;

            // Convert unix timestamp
            string time = Utils.UnixTimeStampToString(Convert.ToDouble(ctransaction.timeStamp));

            byte[] addr = new Address(ctransaction.pubKey).address;
            if (addr.SequenceEqual(Node.walletStorage.getPrimaryAddress()))
            {
                // this is a sent payment

                foreach (var entry in ctransaction.toList)
                {
                    Friend friend = FriendList.getFriend(entry.Key);
                    if (friend != null)
                    {
                        Utils.sendUiCommand(webView, "addSender", friend.nickname + ": " + entry.Value.ToString(), time);
                    }
                    else
                    {
                        Utils.sendUiCommand(webView, "addSender", Base58Check.Base58CheckEncoding.EncodePlain(entry.Key) + ": " + entry.Value.ToString(), time);
                    }
                }
            }
            else
            {
                // this is a received payment

                amount = 0;

                Utils.sendUiCommand(webView, "setReceivedMode");
                byte[] sender_address = new Address(ctransaction.pubKey).address;
                Friend friend         = FriendList.getFriend(sender_address);
                if (friend != null)
                {
                    Utils.sendUiCommand(webView, "addSender", friend.nickname, time);
                }
                else
                {
                    Utils.sendUiCommand(webView, "addSender", Base58Check.Base58CheckEncoding.EncodePlain(sender_address), time);
                }
                foreach (var entry in ctransaction.toList)
                {
                    if (IxianHandler.getWalletStorage().isMyAddress(entry.Key))
                    {
                        // TODO show this as well under sent to; also do the reverse for sent payment
                        //addresses += Base58Check.Base58CheckEncoding.EncodePlain(entry.Key) + ": " + entry.Value.ToString() + "|";
                        amount += entry.Value;
                    }
                }
            }

            Utils.sendUiCommand(webView, "setData", amount.ToString(), ctransaction.fee.ToString(),
                                time, confirmed_text, (ctransaction.fee / ctransaction.amount).ToString() + "%", Transaction.txIdV8ToLegacy(transaction.id));
            return;
        }
Ejemplo n.º 26
0
        // Unified protocol message parsing
        public static void parseProtocolMessage(ProtocolMessageCode code, byte[] data, RemoteEndpoint endpoint)
        {
            if (endpoint == null)
            {
                Logging.error("Endpoint was null. parseProtocolMessage");
                return;
            }
            try
            {
                switch (code)
                {
                case ProtocolMessageCode.hello:
                {
                    using (MemoryStream m = new MemoryStream(data))
                    {
                        using (BinaryReader reader = new BinaryReader(m))
                        {
                            CoreProtocolMessage.processHelloMessageV6(endpoint, reader);
                        }
                    }
                }
                break;


                case ProtocolMessageCode.helloData:
                    using (MemoryStream m = new MemoryStream(data))
                    {
                        using (BinaryReader reader = new BinaryReader(m))
                        {
                            if (!CoreProtocolMessage.processHelloMessageV6(endpoint, reader))
                            {
                                return;
                            }

                            ulong  last_block_num = reader.ReadIxiVarUInt();
                            int    bcLen          = (int)reader.ReadIxiVarUInt();
                            byte[] block_checksum = reader.ReadBytes(bcLen);

                            endpoint.blockHeight = last_block_num;

                            int block_version = (int)reader.ReadIxiVarUInt();

                            if (endpoint.presenceAddress.type != 'C')
                            {
                                ulong highest_block_height = IxianHandler.getHighestKnownNetworkBlockHeight();
                                if (last_block_num + 10 < highest_block_height)
                                {
                                    CoreProtocolMessage.sendBye(endpoint, ProtocolByeCode.tooFarBehind, string.Format("Your node is too far behind, your block height is {0}, highest network block height is {1}.", last_block_num, highest_block_height), highest_block_height.ToString(), true);
                                    return;
                                }
                            }

                            // Process the hello data
                            endpoint.helloReceived = true;
                            NetworkClientManager.recalculateLocalTimeDifference();

                            if (endpoint.presenceAddress.type == 'R')
                            {
                                string[] connected_servers = StreamClientManager.getConnectedClients(true);
                                if (connected_servers.Count() == 1 || !connected_servers.Contains(StreamClientManager.primaryS2Address))
                                {
                                    if (StreamClientManager.primaryS2Address == "")
                                    {
                                        FriendList.requestAllFriendsPresences();
                                    }
                                    // TODO set the primary s2 host more efficiently, perhaps allow for multiple s2 primary hosts
                                    StreamClientManager.primaryS2Address = endpoint.getFullAddress(true);
                                    // TODO TODO do not set if directly connectable
                                    IxianHandler.publicIP           = endpoint.address;
                                    IxianHandler.publicPort         = endpoint.incomingPort;
                                    PresenceList.forceSendKeepAlive = true;
                                    Logging.info("Forcing KA from networkprotocol");
                                }
                            }
                            else if (endpoint.presenceAddress.type == 'C')
                            {
                                Friend f = FriendList.getFriend(endpoint.presence.wallet);
                                if (f != null && f.bot)
                                {
                                    StreamProcessor.sendGetBotInfo(f);
                                }
                            }

                            if (endpoint.presenceAddress.type == 'M' || endpoint.presenceAddress.type == 'H')
                            {
                                Node.setNetworkBlock(last_block_num, block_checksum, block_version);

                                // Get random presences
                                endpoint.sendData(ProtocolMessageCode.getRandomPresences, new byte[1] {
                                    (byte)'R'
                                });
                                endpoint.sendData(ProtocolMessageCode.getRandomPresences, new byte[1] {
                                    (byte)'M'
                                });
                                endpoint.sendData(ProtocolMessageCode.getRandomPresences, new byte[1] {
                                    (byte)'H'
                                });

                                subscribeToEvents(endpoint);
                            }
                        }
                    }
                    break;

                case ProtocolMessageCode.s2data:
                {
                    StreamProcessor.receiveData(data, endpoint);
                }
                break;

                case ProtocolMessageCode.updatePresence:
                {
                    Logging.info("NET: Receiving presence list update");
                    // Parse the data and update entries in the presence list
                    Presence p = PresenceList.updateFromBytes(data);
                    if (p == null)
                    {
                        return;
                    }

                    Friend f = FriendList.getFriend(p.wallet);
                    if (f != null)
                    {
                        f.relayIP = p.addresses[0].address;
                    }
                }
                break;

                case ProtocolMessageCode.keepAlivePresence:
                {
                    byte[]   address   = null;
                    long     last_seen = 0;
                    byte[]   device_id = null;
                    bool     updated   = PresenceList.receiveKeepAlive(data, out address, out last_seen, out device_id, endpoint);
                    Presence p         = PresenceList.getPresenceByAddress(address);
                    if (p == null)
                    {
                        return;
                    }

                    Friend f = FriendList.getFriend(p.wallet);
                    if (f != null)
                    {
                        f.relayIP = p.addresses[0].address;
                    }
                }
                break;

                case ProtocolMessageCode.getPresence:
                {
                    using (MemoryStream m = new MemoryStream(data))
                    {
                        using (BinaryReader reader = new BinaryReader(m))
                        {
                            int    walletLen = reader.ReadInt32();
                            byte[] wallet    = reader.ReadBytes(walletLen);

                            Presence p = PresenceList.getPresenceByAddress(wallet);
                            if (p != null)
                            {
                                lock (p)
                                {
                                    byte[][] presence_chunks = p.getByteChunks();
                                    foreach (byte[] presence_chunk in presence_chunks)
                                    {
                                        endpoint.sendData(ProtocolMessageCode.updatePresence, presence_chunk, null);
                                    }
                                }
                            }
                            else
                            {
                                // TODO blacklisting point
                                Logging.warn(string.Format("Node has requested presence information about {0} that is not in our PL.", Base58Check.Base58CheckEncoding.EncodePlain(wallet)));
                            }
                        }
                    }
                }
                break;

                case ProtocolMessageCode.getPresence2:
                {
                    using (MemoryStream m = new MemoryStream(data))
                    {
                        using (BinaryReader reader = new BinaryReader(m))
                        {
                            int    walletLen = (int)reader.ReadIxiVarUInt();
                            byte[] wallet    = reader.ReadBytes(walletLen);

                            Presence p = PresenceList.getPresenceByAddress(wallet);
                            if (p != null)
                            {
                                lock (p)
                                {
                                    byte[][] presence_chunks = p.getByteChunks();
                                    foreach (byte[] presence_chunk in presence_chunks)
                                    {
                                        endpoint.sendData(ProtocolMessageCode.updatePresence, presence_chunk, null);
                                    }
                                }
                            }
                            else
                            {
                                // TODO blacklisting point
                                Logging.warn(string.Format("Node has requested presence information about {0} that is not in our PL.", Base58Check.Base58CheckEncoding.EncodePlain(wallet)));
                            }
                        }
                    }
                }
                break;

                case ProtocolMessageCode.balance:
                {
                    using (MemoryStream m = new MemoryStream(data))
                    {
                        using (BinaryReader reader = new BinaryReader(m))
                        {
                            int    address_length = reader.ReadInt32();
                            byte[] address        = reader.ReadBytes(address_length);

                            // Retrieve the latest balance
                            IxiNumber balance = reader.ReadString();

                            if (address.SequenceEqual(Node.walletStorage.getPrimaryAddress()))
                            {
                                // Retrieve the blockheight for the balance
                                ulong block_height = reader.ReadUInt64();

                                if (block_height > Node.balance.blockHeight && (Node.balance.balance != balance || Node.balance.blockHeight == 0))
                                {
                                    byte[] block_checksum = reader.ReadBytes(reader.ReadInt32());

                                    Node.balance.address       = address;
                                    Node.balance.balance       = balance;
                                    Node.balance.blockHeight   = block_height;
                                    Node.balance.blockChecksum = block_checksum;
                                    Node.balance.verified      = false;
                                }
                                Node.balance.lastUpdate = Clock.getTimestamp();
                            }
                        }
                    }
                }
                break;

                case ProtocolMessageCode.balance2:
                {
                    using (MemoryStream m = new MemoryStream(data))
                    {
                        using (BinaryReader reader = new BinaryReader(m))
                        {
                            int    address_length = (int)reader.ReadIxiVarUInt();
                            byte[] address        = reader.ReadBytes(address_length);

                            // Retrieve the latest balance
                            IxiNumber balance = new IxiNumber(new BigInteger(reader.ReadBytes((int)reader.ReadIxiVarUInt())));

                            if (address.SequenceEqual(Node.walletStorage.getPrimaryAddress()))
                            {
                                // Retrieve the blockheight for the balance
                                ulong block_height = reader.ReadIxiVarUInt();

                                if (block_height > Node.balance.blockHeight && (Node.balance.balance != balance || Node.balance.blockHeight == 0))
                                {
                                    byte[] block_checksum = reader.ReadBytes((int)reader.ReadIxiVarUInt());

                                    Node.balance.address       = address;
                                    Node.balance.balance       = balance;
                                    Node.balance.blockHeight   = block_height;
                                    Node.balance.blockChecksum = block_checksum;
                                    Node.balance.verified      = false;
                                }
                                Node.balance.lastUpdate = Clock.getTimestamp();
                            }
                        }
                    }
                }
                break;

                case ProtocolMessageCode.newTransaction:
                case ProtocolMessageCode.transactionData:
                {
                    // TODO: check for errors/exceptions
                    Transaction transaction = new Transaction(data, true);

                    if (endpoint.presenceAddress.type == 'M' || endpoint.presenceAddress.type == 'H')
                    {
                        PendingTransactions.increaseReceivedCount(transaction.id, endpoint.presence.wallet);
                    }

                    TransactionCache.addUnconfirmedTransaction(transaction);

                    Node.tiv.receivedNewTransaction(transaction);
                }
                break;

                case ProtocolMessageCode.bye:
                    CoreProtocolMessage.processBye(data, endpoint);
                    break;

                case ProtocolMessageCode.blockHeaders2:
                {
                    // Forward the block headers to the TIV handler
                    Node.tiv.receivedBlockHeaders2(data, endpoint);
                }
                break;

                case ProtocolMessageCode.pitData2:
                {
                    Node.tiv.receivedPIT2(data, endpoint);
                }
                break;

                default:
                    break;
                }
            }
            catch (Exception e)
            {
                Logging.error("Error parsing network message. Details: {0}", e.ToString());
            }
        }
Ejemplo n.º 27
0
        public void insertMessage(FriendMessage message)
        {
            if (friend.approved == false)
            {
                if (message.type == FriendMessageType.requestAdd)
                {
                    // Call webview methods on the main UI thread only
                    Utils.sendUiCommand(webView, "showContactRequest", "1");
                    message.read = true;
                    return;
                }
            }
            else
            {
                // Don't show if the friend is already approved
                if (message.type == FriendMessageType.requestAdd)
                {
                    return;
                }
            }

            string prefix  = "addMe";
            string avatar  = "";//Node.localStorage.getOwnAvatarPath();
            string address = "";
            string nick    = "";

            if (friend.bot)
            {
                if (message.senderAddress != null)
                {
                    address = Base58Check.Base58CheckEncoding.EncodePlain(message.senderAddress);
                }

                nick = message.senderNick;
                if (nick == "")
                {
                    nick = address;
                }
            }
            if (!message.localSender)
            {
                prefix = "addThem";
                avatar = "img/spixiavatar.png";
            }

            if (message.type == FriendMessageType.requestFunds)
            {
                string status      = "PENDING";
                string status_icon = "fa-clock";

                string amount = message.message;

                if (message.message.StartsWith("::"))
                {
                    status      = "DECLINED";
                    status_icon = "fa-exclamation-circle";
                    amount      = message.message.Substring(2);
                }
                else if (message.message.StartsWith(":"))
                {
                    Transaction transaction = TransactionCache.getTransaction(message.message.Substring(1));
                    if (transaction == null)
                    {
                        transaction = TransactionCache.getUnconfirmedTransaction(message.message.Substring(1));
                    }

                    amount = "?";

                    if (transaction != null)
                    {
                        amount = transaction.amount.ToString();

                        if (transaction.applied > 0)
                        {
                            status      = "CONFIRMED";
                            status_icon = "fa-check-circle";
                        }
                    }
                }


                if (message.localSender)
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), address, nick, avatar, "Payment request SENT", amount, status, status_icon, Clock.getRelativeTime(message.timestamp), message.localSender.ToString());
                }
                else
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), address, nick, avatar, "Payment request RECEIVED", amount, status, status_icon, Clock.getRelativeTime(message.timestamp));
                }
                message.read = true;
                return;
            }

            if (message.type == FriendMessageType.sentFunds)
            {
                message.read = true;
                Transaction transaction = TransactionCache.getTransaction(message.message);
                if (transaction == null)
                {
                    transaction = TransactionCache.getUnconfirmedTransaction(message.message);
                }

                string status      = "PENDING";
                string status_icon = "fa-clock";

                string amount = "?";

                if (transaction != null)
                {
                    if (transaction.applied > 0)
                    {
                        status      = "CONFIRMED";
                        status_icon = "fa-check-circle";
                    }
                    amount = transaction.amount.ToString();
                }

                // Call webview methods on the main UI thread only
                if (message.localSender)
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), address, nick, avatar, "Payment SENT", amount, status, status_icon, Clock.getRelativeTime(message.timestamp), message.localSender.ToString());
                }
                else
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), address, nick, avatar, "Payment RECEIVED", amount, status, status_icon, Clock.getRelativeTime(message.timestamp));
                }

                return;
            }


            if (message.type == FriendMessageType.fileHeader)
            {
                string[] split = message.message.Split(new string[] { ":" }, StringSplitOptions.None);
                if (split != null && split.Length > 1)
                {
                    string uid  = split[0];
                    string name = split[1];

                    Utils.sendUiCommand(webView, "addFile", Crypto.hashToString(message.id), address, nick, avatar, uid, name, Clock.getRelativeTime(message.timestamp), message.localSender.ToString(), message.confirmed.ToString(), message.read.ToString());
                }
            }
            else
            {
                // Normal chat message
                // Call webview methods on the main UI thread only
                Utils.sendUiCommand(webView, prefix, Crypto.hashToString(message.id), address, nick, avatar, message.message, Clock.getRelativeTime(message.timestamp), message.confirmed.ToString(), message.read.ToString());
            }

            if (!message.read && !message.localSender)
            {
                message.read = true;
                Node.localStorage.writeMessagesFile(friend.walletAddress, friend.messages);

                // Send read confirmation
                StreamMessage msg_received = new StreamMessage();
                msg_received.type           = StreamMessageCode.info;
                msg_received.sender         = IxianHandler.getWalletStorage().getPrimaryAddress();
                msg_received.recipient      = friend.walletAddress;
                msg_received.data           = new SpixiMessage(message.id, SpixiMessageCode.msgRead, null).getBytes();
                msg_received.transaction    = new byte[1];
                msg_received.sigdata        = new byte[1];
                msg_received.encryptionType = StreamMessageEncryptionCode.none;

                StreamProcessor.sendMessage(friend, msg_received, true);
            }
        }
Ejemplo n.º 28
0
        public bool Process(SmartTransaction tx)
        {
            uint256 txId           = tx.GetHash();
            var     walletRelevant = false;

            bool justUpdate = false;

            if (tx.Confirmed)
            {
                TransactionHashes.TryRemove(txId);                 // If we have in mempool, remove.
                if (!tx.Transaction.PossiblyP2WPKHInvolved())
                {
                    return(false);                    // We do not care about non-witness transactions for other than mempool cleanup.
                }

                bool isFoundTx = TransactionCache.Contains(tx);                 // If we have in cache, update height.
                if (isFoundTx)
                {
                    SmartTransaction foundTx = TransactionCache.FirstOrDefault(x => x == tx);
                    if (foundTx != default(SmartTransaction))                     // Must check again, because it's a concurrent collection!
                    {
                        foundTx.SetHeight(tx.Height, tx.BlockHash, tx.BlockIndex);
                        walletRelevant = true;
                        justUpdate     = true;                     // No need to check for double spend, we already processed this transaction, just update it.
                    }
                }
            }
            else if (!tx.Transaction.PossiblyP2WPKHInvolved())
            {
                return(false);                // We do not care about non-witness transactions for other than mempool cleanup.
            }

            if (!justUpdate && !tx.Transaction.IsCoinBase)             // Transactions we already have and processed would be "double spends" but they shouldn't.
            {
                var doubleSpends = new List <SmartCoin>();
                foreach (SmartCoin coin in Coins)
                {
                    var spent = false;
                    foreach (TxoRef spentOutput in coin.SpentOutputs)
                    {
                        foreach (TxIn txIn in tx.Transaction.Inputs)
                        {
                            if (spentOutput.TransactionId == txIn.PrevOut.Hash && spentOutput.Index == txIn.PrevOut.N)                             // Do not do (spentOutput == txIn.PrevOut), it's faster this way, because it won't check for null.
                            {
                                doubleSpends.Add(coin);
                                spent          = true;
                                walletRelevant = true;
                                break;
                            }
                        }
                        if (spent)
                        {
                            break;
                        }
                    }
                }

                if (doubleSpends.Any())
                {
                    if (tx.Height == Height.Mempool)
                    {
                        // if the received transaction is spending at least one input already
                        // spent by a previous unconfirmed transaction signaling RBF then it is not a double
                        // spanding transaction but a replacement transaction.
                        if (doubleSpends.Any(x => x.IsReplaceable))
                        {
                            // remove double spent coins (if other coin spends it, remove that too and so on)
                            // will add later if they came to our keys
                            foreach (SmartCoin doubleSpentCoin in doubleSpends.Where(x => !x.Confirmed))
                            {
                                Coins.TryRemove(doubleSpentCoin);
                            }
                            tx.SetReplacement();
                            walletRelevant = true;
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else                     // new confirmation always enjoys priority
                    {
                        // remove double spent coins recursively (if other coin spends it, remove that too and so on), will add later if they came to our keys
                        foreach (SmartCoin doubleSpentCoin in doubleSpends)
                        {
                            Coins.TryRemove(doubleSpentCoin);
                        }
                        walletRelevant = true;
                    }
                }
            }

            var  isLikelyCoinJoinOutput = false;
            bool hasEqualOutputs        = tx.Transaction.GetIndistinguishableOutputs(includeSingle: false).FirstOrDefault() != default;

            if (hasEqualOutputs)
            {
                var  receiveKeys         = KeyManager.GetKeys(x => tx.Transaction.Outputs.Any(y => y.ScriptPubKey == x.P2wpkhScript));
                bool allReceivedInternal = receiveKeys.All(x => x.IsInternal);
                if (allReceivedInternal)
                {
                    // It is likely a coinjoin if the diff between receive and sent amount is small and have at least 2 equal outputs.
                    Money spentAmount    = Coins.Where(x => tx.Transaction.Inputs.Any(y => y.PrevOut.Hash == x.TransactionId && y.PrevOut.N == x.Index)).Sum(x => x.Amount);
                    Money receivedAmount = tx.Transaction.Outputs.Where(x => receiveKeys.Any(y => y.P2wpkhScript == x.ScriptPubKey)).Sum(x => x.Value);
                    bool  receivedAlmostAsMuchAsSpent = spentAmount.Almost(receivedAmount, Money.Coins(0.005m));

                    if (receivedAlmostAsMuchAsSpent)
                    {
                        isLikelyCoinJoinOutput = true;
                    }
                }
            }

            List <SmartCoin> spentOwnCoins = null;

            for (var i = 0U; i < tx.Transaction.Outputs.Count; i++)
            {
                // If transaction received to any of the wallet keys:
                var      output   = tx.Transaction.Outputs[i];
                HdPubKey foundKey = KeyManager.GetKeyForScriptPubKey(output.ScriptPubKey);
                if (foundKey != default)
                {
                    walletRelevant = true;

                    if (output.Value <= DustThreshold)
                    {
                        continue;
                    }

                    foundKey.SetKeyState(KeyState.Used, KeyManager);
                    spentOwnCoins = spentOwnCoins ?? Coins.Where(x => tx.Transaction.Inputs.Any(y => y.PrevOut.Hash == x.TransactionId && y.PrevOut.N == x.Index)).ToList();
                    var anonset = tx.Transaction.GetAnonymitySet(i);
                    if (spentOwnCoins.Count != 0)
                    {
                        anonset += spentOwnCoins.Min(x => x.AnonymitySet) - 1;                         // Minus 1, because do not count own.
                    }

                    SmartCoin newCoin = new SmartCoin(txId, i, output.ScriptPubKey, output.Value, tx.Transaction.Inputs.ToTxoRefs().ToArray(), tx.Height, tx.IsRBF, anonset, isLikelyCoinJoinOutput, foundKey.Label, spenderTransactionId: null, false, pubKey: foundKey);                     // Do not inherit locked status from key, that's different.
                    // If we did not have it.
                    if (Coins.TryAdd(newCoin))
                    {
                        TransactionCache.TryAdd(tx);
                        CoinReceived?.Invoke(this, newCoin);

                        // Make sure there's always 21 clean keys generated and indexed.
                        KeyManager.AssertCleanKeysIndexed(isInternal: foundKey.IsInternal);

                        if (foundKey.IsInternal)
                        {
                            // Make sure there's always 14 internal locked keys generated and indexed.
                            KeyManager.AssertLockedInternalKeysIndexed(14);
                        }
                    }
                    else                                      // If we had this coin already.
                    {
                        if (newCoin.Height != Height.Mempool) // Update the height of this old coin we already had.
                        {
                            SmartCoin oldCoin = Coins.FirstOrDefault(x => x.TransactionId == txId && x.Index == i);
                            if (oldCoin != null)                             // Just to be sure, it is a concurrent collection.
                            {
                                oldCoin.Height = newCoin.Height;
                            }
                        }
                    }
                }
            }

            // If spends any of our coin
            for (var i = 0; i < tx.Transaction.Inputs.Count; i++)
            {
                var input = tx.Transaction.Inputs[i];

                var foundCoin = Coins.FirstOrDefault(x => x.TransactionId == input.PrevOut.Hash && x.Index == input.PrevOut.N);
                if (foundCoin != null)
                {
                    walletRelevant = true;
                    var alreadyKnown = foundCoin.SpenderTransactionId == txId;
                    foundCoin.SpenderTransactionId = txId;
                    TransactionCache.TryAdd(tx);

                    if (!alreadyKnown)
                    {
                        CoinSpent?.Invoke(this, foundCoin);
                    }

                    if (tx.Confirmed)
                    {
                        SpenderConfirmed?.Invoke(this, foundCoin);
                    }
                }
            }

            return(walletRelevant);
        }
Ejemplo n.º 29
0
 internal int[] GetTransactionIdsByCustomerId(int customerID)
 {
     return(TransactionCache.GetInstance().GetTransactionIdsByCustomerId(customerID));
 }
Ejemplo n.º 30
0
        public CoreDaemon(Logger logger, IKernel kernel, IBlockchainRules rules, BlockHeaderCache blockHeaderCache, ChainedHeaderCache chainedHeaderCache, BlockTxHashesCache blockTxHashesCache, TransactionCache transactionCache, BlockCache blockCache)
        {
            this.logger        = logger;
            this.shutdownToken = new CancellationTokenSource();

            this.kernel             = kernel;
            this.rules              = rules;
            this.blockHeaderCache   = blockHeaderCache;
            this.chainedHeaderCache = chainedHeaderCache;
            this.blockTxHashesCache = blockTxHashesCache;
            this.transactionCache   = transactionCache;
            this.blockCache         = blockCache;

            // write genesis block out to storage
            this.blockHeaderCache[this.rules.GenesisBlock.Hash]           = this.rules.GenesisBlock.Header;
            this.blockCache[this.rules.GenesisBlock.Hash]                 = this.rules.GenesisBlock;
            this.chainedHeaderCache[this.rules.GenesisChainedHeader.Hash] = this.rules.GenesisChainedHeader;

            // wire up cache events
            this.blockHeaderCache.OnAddition       += OnBlockHeaderAddition;
            this.blockHeaderCache.OnModification   += OnBlockHeaderModification;
            this.blockCache.OnAddition             += OnBlockAddition;
            this.blockCache.OnModification         += OnBlockModification;
            this.blockTxHashesCache.OnAddition     += OnBlockTxHashesAddition;
            this.blockTxHashesCache.OnModification += OnBlockTxHashesModification;
            this.chainedHeaderCache.OnAddition     += OnChainedHeaderAddition;
            this.chainedHeaderCache.OnModification += OnChainedHeaderModification;

            // create chain state builder
            this.chainStateBuilder =
                this.kernel.Get <ChainStateBuilder>(
                    new ConstructorArgument("chain", Chain.CreateForGenesisBlock(this.rules.GenesisChainedHeader).ToBuilder()),
                    new ConstructorArgument("parentUtxo", Utxo.CreateForGenesisBlock(this.rules.GenesisBlock.Hash)));

            this.chainStateLock = new ReaderWriterLockSlim();

            // create workers
            this.chainingWorker = kernel.Get <ChainingWorker>(
                new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromSeconds(0), maxIdleTime: TimeSpan.FromSeconds(30))));

            this.targetChainWorker = kernel.Get <TargetChainWorker>(
                new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromSeconds(0), maxIdleTime: TimeSpan.FromSeconds(30))));

            this.chainStateWorker = kernel.Get <ChainStateWorker>(
                new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.FromSeconds(5))),
                new ConstructorArgument("getTargetChain", (Func <Chain>)(() => this.targetChainWorker.TargetChain)),
                new ConstructorArgument("targetChainWorker", this.targetChainWorker),
                new ConstructorArgument("chainStateBuilder", this.chainStateBuilder));

            this.targetChainWorker.OnTargetBlockChanged +=
                () =>
            {
                var handler = this.OnTargetBlockChanged;
                if (handler != null)
                {
                    handler(this, EventArgs.Empty);
                }
            };

            this.targetChainWorker.OnTargetChainChanged +=
                () =>
            {
                this.chainStateWorker.NotifyWork();

                var handler = this.OnTargetChainChanged;
                if (handler != null)
                {
                    handler(this, EventArgs.Empty);
                }
            };

            this.chainStateWorker.OnChainStateChanged +=
                () =>
            {
                this.utxoScanWorker.NotifyWork();

                //TODO once fully synced, this should save off the immutable snapshot immediately
                //TODO this will allow there to always be an active chain state once synced
                this.chainStateLock.DoWrite(() =>
                                            this.chainState = null);

                var handler = this.OnChainStateChanged;
                if (handler != null)
                {
                    handler(this, EventArgs.Empty);
                }
            };

            this.gcWorker = new WorkerMethod("GC Worker",
                                             () =>
            {
                this.logger.Info(
                    string.Join("\n",
                                new string('-', 80),
                                "GC Memory:      {0,10:#,##0.00} MB",
                                "Process Memory: {1,10:#,##0.00} MB",
                                new string('-', 80)
                                )
                    .Format2
                    (
                        /*0*/ (float)GC.GetTotalMemory(false) / 1.MILLION(),
                        /*1*/ (float)Process.GetCurrentProcess().PrivateMemorySize64 / 1.MILLION()
                    ));
            }, initialNotify: true, minIdleTime: TimeSpan.FromSeconds(30), maxIdleTime: TimeSpan.FromSeconds(30), logger: this.logger);

            this.utxoScanWorker = new WorkerMethod("UTXO Scan Worker",
                                                   () =>
            {
                var chainStateLocal = this.GetChainState();
                if (chainStateLocal == null)
                {
                    return;
                }

                new MethodTimer().Time("Full UTXO Scan: {0:#,##0}".Format2(chainStateLocal.Utxo.OutputCount), () =>
                {
                    var sha256 = new SHA256Managed();
                    foreach (var output in chainStateLocal.Utxo.GetUnspentOutputs())
                    {
                        if (new UInt256(sha256.ComputeDoubleHash(output.Value.ScriptPublicKey.ToArray())) == UInt256.Zero)
                        {
                        }
                    }
                });
            }, initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue, logger: this.logger);
        }
Ejemplo n.º 31
0
 public Transaction SyncTransaction(Transaction transaction)
 {
     return(TransactionCache.GetInstance().SyncTransaction(transaction));
 }