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); }
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); }
//重载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); } }
// 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; }
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() ); }
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")); } }
// 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; }
public BTCPayWallet(ExplorerClient client, TransactionCache cache, BTCPayNetwork network) { if (client == null) { throw new ArgumentNullException(nameof(client)); } _Client = client; _Network = network; _Cache = cache; }
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; }
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()); }
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); }
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; } }
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); } } } }
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); }
// 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); }
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); }
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); }
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) { ; } }
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); }
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); } }
internal double GetTransactionSumTotalByCustomerId(int customerID, DateTime startDate) { return(TransactionCache.GetInstance().GetTransactionSumTotalByCustomerId(customerID, startDate)); }
internal void RefreshCache() { TransactionCache.GetInstance().Clear(); TransactionCache.GetInstance(); }
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); }
// 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; }
// 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()); } }
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); } }
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); }
internal int[] GetTransactionIdsByCustomerId(int customerID) { return(TransactionCache.GetInstance().GetTransactionIdsByCustomerId(customerID)); }
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); }
public Transaction SyncTransaction(Transaction transaction) { return(TransactionCache.GetInstance().SyncTransaction(transaction)); }