public void Unlock() { Debug.Assert(Locked); lock (this) { OwningTransaction = null; LinkedListNode <KeyValuePair <Transaction, ManualResetEvent> > node = null; if (PendingTransactions.Count > 0) { node = PendingTransactions.First; PendingTransactions.RemoveFirst(); } if (node != null) { Transaction transaction = node.Value.Key; ManualResetEvent manualEvent = node.Value.Value; Lock(transaction); lock (manualEvent) { if (!manualEvent.SafeWaitHandle.IsClosed) { manualEvent.Set(); } } } } }
private Block BuildBlock() { var lastBlock = BlockChain.Last().Value; Block tempBlock = Block.BuildBlockForMiner(lastBlock.Index + 1, PendingTransactions.ToList(), lastBlock.BlockHash, Difficulty); return(tempBlock); }
public override bool addTransaction(Transaction tx, bool force_broadcast) { // TODO Send to peer if directly connectable CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.transactionData, tx.getBytes(), null); PendingTransactions.addPendingLocalTransaction(tx); return(true); }
// Broadcasts the solution to the network public void sendSolution(byte[] nonce) { byte[] pubkey = Node.walletStorage.getPrimaryPublicKey(); // Check if this wallet's public key is already in the WalletState Wallet mywallet = Node.walletState.getWallet(Node.walletStorage.getPrimaryAddress()); if (mywallet.publicKey != null && mywallet.publicKey.SequenceEqual(pubkey)) { // Walletstate public key matches, we don't need to send the public key in the transaction pubkey = null; } byte[] data = null; using (MemoryStream mw = new MemoryStream()) { using (BinaryWriter writerw = new BinaryWriter(mw)) { writerw.Write(activeBlock.blockNum); writerw.Write(Crypto.hashToString(nonce)); data = mw.ToArray(); } } Transaction tx = new Transaction((int)Transaction.Type.PoWSolution, new IxiNumber(0), new IxiNumber(0), ConsensusConfig.ixianInfiniMineAddress, Node.walletStorage.getPrimaryAddress(), data, pubkey, Node.blockChain.getLastBlockNum()); if (TransactionPool.addTransaction(tx)) { PendingTransactions.addPendingLocalTransaction(tx); } else { Logging.error("An unknown error occured while sending PoW solution."); } }
private void ValidateTransaction(Transaction transaction) { if (!CryptoUtil.IsAddressValid(transaction.FromAddress)) { throw new AddressNotValidException($"{transaction.FromAddress} is not valid address"); } if (!CryptoUtil.IsAddressValid(transaction.ToAddress)) { throw new AddressNotValidException($"{transaction.ToAddress} is not valid address"); } if (transaction == null) { throw new ArgumentException("'transaction' object cannot be null"); } //check whetehr we know that transaction if (PendingTransactions.FirstOrDefault(t => t.TransactionHash == transaction.TransactionHash) != null) { return; } //check whether transaction is already mined if (BlockChain.Any(b => b.Value.Transactions.Any(t => t.TransactionHash == transaction.TransactionHash))) { return; } if (string.IsNullOrWhiteSpace(transaction.SenderPublicKey)) { throw new TransactionNotValidException("Sender signature cannot be empty"); } bool isHashValid = TransactionValidator.IsValidateHash(transaction); if (!isHashValid) { throw new TransactionNotValidException("Transaction not Valid! Tranascion is chnaged by middle man"); } bool isVerified = TransactionValidator.IsValid(transaction); if (!isVerified) { throw new TransactionNotValidException("Transaction not Valid! Signutre is not valid"); } string address = TransactionValidator.GetAddress(transaction.SenderPublicKey); if (address != transaction.FromAddress) { throw new TransactionNotValidException("Provided address is not valid."); } }
void handleStatus() { Console.WriteLine("Last Block Height: {0}", IxianHandler.getLastBlockHeight()); Console.WriteLine("Network Block Height: {0}", IxianHandler.getHighestKnownNetworkBlockHeight()); int connectionsOut = NetworkClientManager.getConnectedClients(true).Count(); Console.WriteLine("Connections: {0}", connectionsOut); Console.WriteLine("Pending transactions: {0}\n", PendingTransactions.pendingTransactionCount()); }
//Mining of block public void MinePendingTransactions(string miningRewardAddress) { Block block = new Block(DateTime.Now, PendingTransactions, GetLastestBlock.CurrentHash); block.MineBlock(Diffuclty); Console.WriteLine("Block successfully mined!"); Chain.Add(block); PendingTransactions.Add(new Transaction(null, miningRewardAddress, MiningReward)); }
public override void receivedTransactionInclusionVerificationResponse(byte[] txid, bool verified) { string status = "NOT VERIFIED"; if (verified) { status = "VERIFIED"; PendingTransactions.remove(txid); } Console.WriteLine("Transaction {0} is {1}\n", Transaction.txIdV8ToLegacy(txid), status); }
public void CreateTransaction(TransactionInfo transaction) { PendingTransactions.Add(transaction); if (PendingTransactions.Count < TransactionThreshold) { return; } var block = new BlockInfo { PreviousHash = Blocks[^ 1].Hash,
public void AddTransaction(Transaction someTransaction, Hashtable transactions, List <Account> ListOfAllAccounts) { if (IsValidTransaction(someTransaction, transactions, ListOfAllAccounts)) { PendingTransactions.Add(someTransaction); } else { RejectedTransactions.Add(someTransaction); } }
public void ProcessPendingTransactions(DateTime date, string miner) { Block lastBlock = Chain.Last(); Block newBlock = new Block(date, lastBlock, PendingTransactions); newBlock.Transactions.Add(new Transaction(null, miner, Reward, date)); newBlock.Mine(Difficulty); AddUsersOfBlock(newBlock); Chain.Add(newBlock); PendingTransactions.Clear(); }
//CreateTransaction public bool CreateTransaction(Transaction transaction) { if (transaction != null) { PendingTransactions.Add(transaction); return(true); } else { return(false); } }
public void MinePendingTransactions(User miningRewardUser) { PendingTransactions.Add(new Transaction(null, miningRewardUser, 150)); Block block = new Block(DateTime.Now, PendingTransactions, GetLastestBlock.CurrentHash); block.MineBlock(Diffuclty); Console.WriteLine("Block successfully mined!"); Blocks.Add(block); PendingTransactions = new List <Transaction>(); }
public void AddTransaction(Transaction transaction) { if (string.IsNullOrEmpty(transaction.FromAddress) || string.IsNullOrEmpty(transaction.ToAddress)) { throw new Exception("Transaction must include from and to address"); } if (!transaction.IsValid()) { throw new Exception("Cannot add invalid transaction to chain"); } PendingTransactions.Add(transaction); }
public void AttachBroadcastedBlock(BlockSyncApiModel block, string nodeAddress) { bool isPastBlock = block.Index <= LastBlock.Index; if (isPastBlock) { return; } Block minedBlock = Block.ReCreateBlock(block); ValidateBlockHash(minedBlock, minedBlock.Nonce, minedBlock.BlockHash); // replace blockchain if another blockain is longer int nodeDifference = minedBlock.Index - BlockChain.Count; if (nodeDifference >= 6) { int startIndex = minedBlock.Index - nodeDifference; List <Block> forkedBlocks = NodeSynchornizator.GetBlocksForSync(nodeAddress); foreach (var bl in forkedBlocks) { RevalidateBlock(bl); BlockChain.AddOrUpdate(bl.Index, bl, (index, curBlock) => { return(bl); }); } List <string> blockTxs = forkedBlocks.SelectMany(b => b.Transactions).Select(t => t.TransactionHash).ToList(); PendingTransactions = new ConcurrentBag <Transaction>(PendingTransactions. Where(t => !blockTxs.Contains(t.TransactionHash))); } else { bool isFutureBlock = LastBlock.BlockHash != minedBlock.PreviousBlockHash; if (isFutureBlock) { return; } RevalidateBlock(minedBlock); // remove mined transactions from pending transactions List <string> minedTxIds = minedBlock.Transactions.Select(t => t.TransactionHash).ToList(); PendingTransactions = new ConcurrentBag <Transaction>(PendingTransactions.Where(t => !minedTxIds.Contains(t.TransactionHash)).ToList()); BlockChain.TryAdd(minedBlock.Index, minedBlock); } }
void Lock(Transaction transaction) { Monitor.Enter(this); if (OwningTransaction == null) { //Acquire the transaction lock if(transaction != null) OwningTransaction = transaction; Monitor.Exit(this); return; } else //Some transaction owns the lock { //We're done if it's the same one as the method parameter if (OwningTransaction == transaction) { Monitor.Exit(this); return; } //Otherwise, need to acquire the transaction lock else { ManualResetEvent manualEvent = new ManualResetEvent(false); KeyValuePair <Transaction, ManualResetEvent> pair = new KeyValuePair <Transaction, ManualResetEvent>(transaction, manualEvent); PendingTransactions.AddLast(pair); if (transaction != null) { transaction.TransactionCompleted += (sender, e) => { lock (this) { //Pair may have already been removed if unlocked PendingTransactions.Remove(pair); } lock (manualEvent) { if (!manualEvent.SafeWaitHandle.IsClosed) { manualEvent.Set(); } } }; } Monitor.Exit(this); //Block the transaction or the calling thread manualEvent.WaitOne(); lock (manualEvent) manualEvent.Close(); } } }
public override void receivedTransactionInclusionVerificationResponse(byte[] txid, bool verified) { // TODO implement error // TODO implement blocknum ActivityStatus status = ActivityStatus.Pending; if (verified) { status = ActivityStatus.Final; PendingTransactions.remove(txid); } ActivityStorage.updateStatus(txid, status, 0); }
public void MinePendingTransactions(string miningRewardAddress) { if (!isMining) { isMining = true; Transaction rewardTx = new Transaction(null, miningRewardAddress, MiningReward); PendingTransactions.Add(rewardTx); // TO-DO limit amount of transactions Block block = new Block(DateTime.UtcNow.ToString("g"), PendingTransactions, GetLatestBlock().Hash); block.MineBlock(Difficulty); Chain.Add(block); PendingTransactions = new List <Transaction>(); isMining = false; } }
internal ICollection <Transaction> GetTransactions(string address, bool includeUncofirmed = false, bool onlySuccessful = false) { var query = BlockChain.SelectMany(b => b.Value.Transactions).Where(t => t.FromAddress == address || t.ToAddress == address); if (onlySuccessful) { query = query.Where(t => t.TranserSuccessfull); } var result = query.ToList(); if (includeUncofirmed) { result.AddRange(PendingTransactions .Where(t => (t.FromAddress == address || t.ToAddress == address) && (!onlySuccessful || t.TranserSuccessfull)) .ToList()); } return(result); }
public void NonceFound(string minerAddress, int nonce, string hash) { lock (_nonceFoundLock) { Block block = BlocksInProgress[minerAddress]; if (block == null) { return; } if (!CryptoUtil.IsAddressValid(minerAddress)) { throw new AddressNotValidException($"Miner address '{minerAddress}' is not valid"); } if (block.Index != BlockChain.Last().Key + 1) { throw new NonceUselessException(); } ValidateBlockHash(block, nonce, hash); block.BlockMined(nonce, hash, minerAddress); int minedTransactionsCount = block.Transactions.Count; List <Transaction> notMinedTxs = new List <Transaction>(); var allTx = PendingTransactions.ToList(); for (int i = minedTransactionsCount; i < allTx.Count; i++) { notMinedTxs.Add(allTx[i]); } PendingTransactions = new ConcurrentBag <Transaction>(notMinedTxs); BlockChain.TryAdd(block.Index, block); BlocksInProgress[minerAddress] = null; NodeSynchornizator.BroadcastBlock(block); } }
public string MineFirstPendingTransaction(int minerId) { if (this.PendingTransactions.Count < 1) { return("No transactions to mine!"); } List <Transaction> minedTransactions = new List <Transaction>(); minedTransactions.Add(PendingTransactions[0]); Block newBlock = new Block(DateTime.Now, minedTransactions, this.Chain.Last().Hash); newBlock.MineBlock(this.Difficulty); this.Chain.Add(newBlock); Transaction reward = new Transaction(0, minerId, MiningReward); PendingTransactions.Add(reward); return("Transaction Successfully mined!"); }
public override void receivedTransactionInclusionVerificationResponse(byte[] txid, bool verified) { // TODO implement error // TODO implement blocknum ActivityStatus status = ActivityStatus.Pending; if (verified) { status = ActivityStatus.Final; PendingTransaction p_tx = PendingTransactions.getPendingTransaction(txid); if (p_tx != null) { if (p_tx.messageId != null) { StreamProcessor.confirmMessage(p_tx.messageId); } PendingTransactions.remove(txid); } } ActivityStorage.updateStatus(txid, status, 0); }
public void AddTransaction(Transaction transaction, bool broadcast = true) { ValidateTransaction(transaction); ulong senderBalance = CalculateBalance(transaction.FromAddress, true, true); if (senderBalance >= transaction.Fee) { transaction.TranserSuccessfull = senderBalance >= transaction.Amount + transaction.Fee; PendingTransactions.Add(transaction); if (broadcast) { NodeSynchornizator.BroadcastTransaction(transaction); } if (!transaction.TranserSuccessfull) { throw new BalanceNotEnoughException($"Address '{transaction.FromAddress}' trying to send {transaction.Amount.GetFormattedTokens()}, but balance is {senderBalance.GetFormattedTokens()}. Transaction fee will be deducted !!!"); } } else { throw new BalanceNotEnoughException($"Address '{transaction.FromAddress}' does not have enough money even for paying the fee"); } }
// 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: handleHello(data, endpoint); break; case ProtocolMessageCode.helloData: handleHelloData(data, endpoint); break; case ProtocolMessageCode.s2data: StreamProcessor.receiveData(data, endpoint); break; case ProtocolMessageCode.s2failed: Logging.error("Failed to send s2 data"); break; case ProtocolMessageCode.s2signature: StreamProcessor.receivedTransactionSignature(data, endpoint); break; case ProtocolMessageCode.newTransaction: case ProtocolMessageCode.transactionData: { Transaction tx = new Transaction(data, true); if (endpoint.presenceAddress.type == 'M' || endpoint.presenceAddress.type == 'H') { PendingTransactions.increaseReceivedCount(tx.id, endpoint.presence.wallet); } Node.tiv.receivedNewTransaction(tx); Logging.info("Received new transaction {0}", tx.id); Node.addTransactionToActivityStorage(tx); } break; case ProtocolMessageCode.updatePresence: // Parse the data and update entries in the presence list PresenceList.updateFromBytes(data); 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); break; case ProtocolMessageCode.getPresence: handleGetPresence(data, endpoint); break; case ProtocolMessageCode.getPresence2: handleGetPresence2(data, endpoint); break; case ProtocolMessageCode.balance: handleBalance(data, endpoint); break; case ProtocolMessageCode.balance2: handleBalance2(data, endpoint); 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(string.Format("Error parsing network message. Details: {0}", e.ToString())); } }
//Creates a new transaction public void CreateTransaction(Transaction transaction) { PendingTransactions.Add(transaction); }
// 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)) { bool processed = false; processed = CoreProtocolMessage.processHelloMessageV6(endpoint, reader, false); if (!processed || (Config.whiteList.Count > 0 && !Config.whiteList.Contains(endpoint.presence.wallet, new ByteArrayComparer()))) { CoreProtocolMessage.sendBye(endpoint, ProtocolByeCode.bye, string.Format("Access denied."), "", true); return; } endpoint.helloReceived = true; } } break; case ProtocolMessageCode.helloData: using (MemoryStream m = new MemoryStream(data)) { using (BinaryReader reader = new BinaryReader(m)) { if (CoreProtocolMessage.processHelloMessageV6(endpoint, reader)) { char node_type = endpoint.presenceAddress.type; if (node_type != 'M' && node_type != 'H') { CoreProtocolMessage.sendBye(endpoint, ProtocolByeCode.expectingMaster, string.Format("Expecting master node."), "", true); 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(); try { string public_ip = reader.ReadString(); ((NetworkClient)endpoint).myAddress = public_ip; } catch (Exception) { } string address = NetworkClientManager.getMyAddress(); if (address != null) { if (IxianHandler.publicIP != address) { Logging.info("Setting public IP to " + address); IxianHandler.publicIP = address; } } // Process the hello data endpoint.helloReceived = true; NetworkClientManager.recalculateLocalTimeDifference(); Node.setNetworkBlock(last_block_num, block_checksum, block_version); // Get random presences endpoint.sendData(ProtocolMessageCode.getRandomPresences, new byte[1] { (byte)'M' }); endpoint.sendData(ProtocolMessageCode.getRandomPresences, new byte[1] { (byte)'H' }); CoreProtocolMessage.subscribeToEvents(endpoint); } } } break; case ProtocolMessageCode.s2data: { StreamProcessor.receiveData(data, endpoint); } break; case ProtocolMessageCode.s2failed: { using (MemoryStream m = new MemoryStream(data)) { using (BinaryReader reader = new BinaryReader(m)) { Logging.error("Failed to send s2 data"); } } } break; case ProtocolMessageCode.transactionData: { Transaction tx = new Transaction(data, true); if (endpoint.presenceAddress.type == 'M' || endpoint.presenceAddress.type == 'H') { PendingTransactions.increaseReceivedCount(tx.id, endpoint.presence.wallet); } Node.tiv.receivedNewTransaction(tx); Logging.info("Received new transaction {0}", tx.id); Node.addTransactionToActivityStorage(tx); } break; case ProtocolMessageCode.updatePresence: { // Parse the data and update entries in the presence list PresenceList.updateFromBytes(data, 0); } 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); } 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(IxianHandler.getWalletStorage().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.lastUpdate = Clock.getTimestamp(); Node.balance.verified = false; } } } } } 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(IxianHandler.getWalletStorage().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.lastUpdate = Clock.getTimestamp(); Node.balance.verified = false; } } } } } 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(string.Format("Error parsing network message. Details: {0}", e.ToString())); } }
public void BuyCoins(User user, double amount) { //Логика для покупки криптовалюты пока что нету обменников(но есть возможность поменять QIWI,WEBMONEY и другии веб - деньги или настоящие деньги на криптовалюту.) PendingTransactions.Add(new Transaction(null, user, amount)); }
// 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)) { if (CoreProtocolMessage.processHelloMessage(endpoint, reader)) { byte[] challenge_response = null; int challenge_len = reader.ReadInt32(); byte[] challenge = reader.ReadBytes(challenge_len); challenge_response = CryptoManager.lib.getSignature(challenge, Node.walletStorage.getPrimaryPrivateKey()); CoreProtocolMessage.sendHelloMessage(endpoint, true, challenge_response); endpoint.helloReceived = true; return; } } } break; case ProtocolMessageCode.helloData: using (MemoryStream m = new MemoryStream(data)) { using (BinaryReader reader = new BinaryReader(m)) { if (CoreProtocolMessage.processHelloMessage(endpoint, reader)) { char node_type = endpoint.presenceAddress.type; if (node_type != 'M' && node_type != 'H') { CoreProtocolMessage.sendBye(endpoint, ProtocolByeCode.expectingMaster, string.Format("Expecting master node."), "", true); return; } ulong last_block_num = reader.ReadUInt64(); int bcLen = reader.ReadInt32(); byte[] block_checksum = reader.ReadBytes(bcLen); int wsLen = reader.ReadInt32(); byte[] walletstate_checksum = reader.ReadBytes(wsLen); int consensus = reader.ReadInt32(); endpoint.blockHeight = last_block_num; int block_version = reader.ReadInt32(); // Check for legacy level ulong legacy_level = reader.ReadUInt64(); // deprecated int challenge_response_len = reader.ReadInt32(); byte[] challenge_response = reader.ReadBytes(challenge_response_len); if (!CryptoManager.lib.verifySignature(endpoint.challenge, endpoint.serverPubKey, challenge_response)) { CoreProtocolMessage.sendBye(endpoint, ProtocolByeCode.authFailed, string.Format("Invalid challenge response."), "", true); return; } // Process the hello data endpoint.helloReceived = true; NetworkClientManager.recalculateLocalTimeDifference(); if (endpoint.presenceAddress.type == 'M') { Node.setNetworkBlock(last_block_num, block_checksum, block_version); // Get random presences endpoint.sendData(ProtocolMessageCode.getRandomPresences, new byte[1] { (byte)'M' }); CoreProtocolMessage.subscribeToEvents(endpoint); } } } } 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; } } } } } break; case ProtocolMessageCode.updatePresence: { // Parse the data and update entries in the presence list PresenceList.updateFromBytes(data); } break; case ProtocolMessageCode.blockHeaders: { // Forward the block headers to the TIV handler Node.tiv.receivedBlockHeaders(data, endpoint); } break; case ProtocolMessageCode.pitData: { Node.tiv.receivedPIT(data, endpoint); } break; case ProtocolMessageCode.newTransaction: case ProtocolMessageCode.transactionData: { Transaction tx = new Transaction(data, true); PendingTransactions.increaseReceivedCount(tx.id); Node.tiv.receivedNewTransaction(tx); Console.WriteLine("Received new transaction {0}", tx.id); } break; default: break; } } catch (Exception e) { Logging.error(string.Format("Error parsing network message. Details: {0}", e.ToString())); } if (waitingFor == code) { blocked = false; } }
// 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 JsonResponse onStatus(Dictionary <string, object> parameters) { JsonError error = null; Dictionary <string, object> networkArray = new Dictionary <string, object>(); networkArray.Add("Core Version", CoreConfig.version); networkArray.Add("Node Version", CoreConfig.productVersion); string netType = "mainnet"; if (CoreConfig.isTestNet) { netType = "testnet"; } networkArray.Add("Network type", netType); networkArray.Add("My time", Clock.getTimestamp()); networkArray.Add("Network time difference", Core.networkTimeDifference); networkArray.Add("My External IP", IxianHandler.publicIP); //networkArray.Add("Listening interface", context.Request.RemoteEndPoint.Address.ToString()); networkArray.Add("Queues", "Rcv: " + NetworkQueue.getQueuedMessageCount() + ", RcvTx: " + NetworkQueue.getTxQueuedMessageCount() + ", SendClients: " + NetworkServer.getQueuedMessageCount() + ", SendServers: " + NetworkClientManager.getQueuedMessageCount() + ", Storage: " + Storage.getQueuedQueryCount() + ", Logging: " + Logging.getRemainingStatementsCount() + ", Pending Transactions: " + PendingTransactions.pendingTransactionCount()); networkArray.Add("Node Deprecation Block Limit", Config.nodeDeprecationBlock); string dltStatus = "Active"; if (Node.blockSync.synchronizing) { dltStatus = "Synchronizing"; } if (Node.blockChain.getTimeSinceLastBLock() > 1800) // if no block for over 1800 seconds { dltStatus = "ErrorLongTimeNoBlock"; } if (Node.blockProcessor.networkUpgraded) { dltStatus = "ErrorForkedViaUpgrade"; } networkArray.Add("Update", checkUpdate()); networkArray.Add("DLT Status", dltStatus); string bpStatus = "Stopped"; if (Node.blockProcessor.operating) { bpStatus = "Running"; } networkArray.Add("Block Processor Status", bpStatus); networkArray.Add("Block Height", Node.blockChain.getLastBlockNum()); networkArray.Add("Block Version", Node.blockChain.getLastBlockVersion()); networkArray.Add("Network Block Height", IxianHandler.getHighestKnownNetworkBlockHeight()); networkArray.Add("Node Type", PresenceList.myPresenceType); networkArray.Add("Connectable", NetworkServer.isConnectable()); if (parameters.ContainsKey("verbose")) { networkArray.Add("Required Consensus", Node.blockChain.getRequiredConsensus()); networkArray.Add("Wallets", Node.walletState.numWallets); networkArray.Add("Presences", PresenceList.getTotalPresences()); networkArray.Add("Supply", Node.walletState.calculateTotalSupply().ToString()); networkArray.Add("Applied TX Count", TransactionPool.getTransactionCount() - TransactionPool.getUnappliedTransactions().Count()); networkArray.Add("Unapplied TX Count", TransactionPool.getUnappliedTransactions().Count()); networkArray.Add("WS Checksum", Crypto.hashToString(Node.walletState.calculateWalletStateChecksum())); networkArray.Add("WS Delta Checksum", Crypto.hashToString(Node.walletState.calculateWalletStateChecksum(true))); networkArray.Add("Network Clients", NetworkServer.getConnectedClients()); networkArray.Add("Network Servers", NetworkClientManager.getConnectedClients(true)); } networkArray.Add("Masters", PresenceList.countPresences('M')); networkArray.Add("Relays", PresenceList.countPresences('R')); networkArray.Add("Clients", PresenceList.countPresences('C')); networkArray.Add("Workers", PresenceList.countPresences('W')); return(new JsonResponse { result = networkArray, error = error }); }