public void networkHandler_PeerDiscoveryEvent(NetworkPacket packet) { switch (packet.Type) { case PacketType.TPT_PEER_DISCOVERY_INIT: respondPeerDiscovery(packet); return; case PacketType.TPT_PEER_DISCOVERY_RESPONSE: processPeerDiscovery(packet); return; } }
public void HandlePacket(NetworkPacket packet) { try { switch (packet.Type) { case PacketType.TPT_TX_SYNC_FETCH_REQUEST: HandleSyncFetchRequest(packet); break; case PacketType.TPT_TX_SYNC_FETCH_RESPONSE: HandleSyncFetchResponse(packet); break; case PacketType.TPT_TX_SYNC_ID_REQUEST: break; case PacketType.TPT_TX_SYNC_ID_RESPONSE: break; case PacketType.TPT_TX_SYNC_QUERY_REQUEST: HandleSyncQueryRequest(packet); break; case PacketType.TPT_TX_SYNC_QUERY_RESPONSE: HandleSyncQueryResponse(packet); break; case PacketType.TPT_TX_SYNC_CLOSEHISTORY_REQUEST: break; case PacketType.TPT_TX_SYNC_CLOSEHISTORY_RESPONSE: break; } } catch (Exception ex) { DisplayUtils.Display("TransactionStreamHandler.HandlePacket", ex); } }
void HandleSyncFetchRequest(NetworkPacket packet) { TransactionSyncRequest TSR = new TransactionSyncRequest(); TSR.Deserialize(packet.Data); if (nodeState.NodeInfo.LastLedgerInfo.SequenceNumber >= (TSR.StartSequenceNumber + TSR.Length)) { TransactionSyncResponse transactionSyncResponse = new TransactionSyncResponse(); if (nodeState.PersistentTransactionStore.FetchBySequenceNumber(out transactionSyncResponse.TransactionContents, TSR.StartSequenceNumber, TSR.Length) == DBResponse.FetchSuccess) { NetworkPacket np = new NetworkPacket(new Hash(nodeState.NodeInfo.PublicKey), PacketType.TPT_TX_SYNC_FETCH_RESPONSE, transactionSyncResponse.Serialize(), packet.Token); network.AddToQueue(new NetworkPacketQueueEntry(packet.PublicKeySource, np)); // Send the reply. } } }
/// <summary> /// Requests system time from all connected peers, collects responses after 5 seconds /// and computes the median /// </summary> /// <returns>Median diff of all responses</returns> public long SyncTime() { // process responses List<long> diffs = new List<long>(); foreach (KeyValuePair<Hash, ResponseStruct> entry in collectedResponses) diffs.Add(entry.Value.diff); diffs.Add(0); collectedResponses = new ConcurrentDictionary<Hash, ResponseStruct>(); long diff = computeDiff(diffs); double display = ((double)diff) / 10000000; DateTime st = DateTime.FromFileTimeUtc(nodeState.SystemTime); DateTime nt = DateTime.FromFileTimeUtc(nodeState.NetworkTime); Print(diffs.Count + " resp; diff " + display/*.ToString("0.000")*/ + "; \tst: " + st.ToLongTimeString() + "; \tnt: " + nt.ToLongTimeString()); //send new requests //Print("start syncing with " + nodeState.ConnectedValidators.Count + " peers"); sentRequests = new ConcurrentDictionary<Hash, RequestStruct>(); foreach (Hash peer in nodeState.ConnectedValidators) { // save locally RequestStruct rs = new RequestStruct(); rs.senderTime = nodeState.SystemTime; rs.token = TNetUtils.GenerateNewToken(); sentRequests.AddOrUpdate(peer, rs, (ok, ov) => rs); // send message TimeSyncRqMsg request = new TimeSyncRqMsg(); request.senderTime = nodeState.SystemTime; byte[] message = request.Serialize(); NetworkPacket packet = new NetworkPacket(nodeConfig.PublicKey, PacketType.TPT_TIMESYNC_REQUEST, message, rs.token); networkPacketSwitch.AddToQueue(peer, packet); } return diff; }
void ProcessPendingRemoteFetches() { long chunk_size = Common.LSYNC_MAX_REQUESTED_NODES / 2; while (NodeFetchQueue.Count > 0) { int count = 0; NodeInfoRequest nir = new NodeInfoRequest(); while ((NodeFetchQueue.Count > 0) && (count++ < chunk_size)) { nir.Add(NodeFetchQueue.Dequeue()); } // Create a packet and send. List<NodeSocketData> nsds; // A single random trusted node is okay for fetching data. if (nodeConfig.GetRandomTrustedNode(out nsds, 1)) { NetworkPacket request = new NetworkPacket(nodeConfig.PublicKey, PacketType.TPT_LSYNC_NODE_REQUEST, nir.Serialize(), TNetUtils.GenerateNewToken()); networkPacketSwitch.AddToQueue(nsds[0].PublicKey, request); //DebugPrint("Requesting " + nir.TotalRequestedNodes + " nodes from, " + nsds[0].PublicKey + " ME: " + nodeConfig.PublicKey, DisplayType.ImportantInfo); } } }
void networkHandler_TimeSyncEvent(NetworkPacket packet) { switch (packet.Type) { case PacketType.TPT_TIMESYNC_REQUEST: requestHandler(packet); break; case PacketType.TPT_TIMESYNC_RESPONSE: responseHandler(packet); break; } }
/// <summary> /// Checks if a packet reply was indeed requested. If not, the packet should be dropped. /// </summary> /// <param name="packet"></param> /// <returns></returns> public bool VerifyPendingPacket(NetworkPacket packet) { bool good = false; if (nodeState.PendingNetworkRequests.ContainsKey(packet.Token)) { PendingNetworkRequest pnr = nodeState.PendingNetworkRequests[packet.Token]; if ((pnr.PublicKey == packet.PublicKeySource) && (pnr.ResponseType == packet.Type)) { good = true; } PendingNetworkRequest tmp; nodeState.PendingNetworkRequests.TryRemove(packet.Token, out tmp); } return good; }
private void processPeerDiscovery(NetworkPacket packet) { if (packet.Token == requestToken) { PeerDiscoveryMsg response = new PeerDiscoveryMsg(); response.Deserialize(packet.Data); processNewPeerList(response.knownPeers); } else { Print("toke mismatch"); } }
void HandleSyncQueryResponse(NetworkPacket packet) { TransactionSyncQueryResponse tsqr = new TransactionSyncQueryResponse(); tsqr.Deserialize(packet.Data); // Well, we have received a response from a node. // CRITICAL: Test if we ordered it. Then check if we are behind, if so, send fetch requests. // if(nodeState.NodeInfo) }
void HandleNodeRequest(NetworkPacket packet) { NodeInfoRequest nir = new NodeInfoRequest(); nir.Deserialize(packet.Data); // DebugPrint("NodeRequest from " + packet.PublicKeySource + " Nodes : " + nir.TotalRequestedNodes, DisplayType.Warning); if ((Common.LSYNC_MAX_REQUESTED_NODES >= nir.TotalRequestedNodes) && (nir.TotalRequestedNodes == nir.RequestedNodesAdresses.Count)) { NodeInfoResponse responseData = new NodeInfoResponse(); foreach (Hash nodeAddress in nir.RequestedNodesAdresses) { ListTreeNode ltn; if (LedgerTree.TraverseToNode(nodeAddress, out ltn) == TraverseResult.Success) { responseData.Add(new NodeDataEntity(ltn)); } } NetworkPacket response = new NetworkPacket(nodeConfig.PublicKey, PacketType.TPT_LSYNC_NODE_RESPONSE, responseData.Serialize(), packet.Token); networkPacketSwitch.AddToQueue(packet.PublicKeySource, response); } }
void HandleLeafResponse(NetworkPacket packet) { // Check that the packet is valid. if (networkPacketSwitch.VerifyPendingPacket(packet)) { LeafAccountDataResponse ladr = new LeafAccountDataResponse(); ladr.Deserialize(packet.Data); if (ladr.Leaves.Count == ladr.LeafCount) { //DebugPrint("YAYY, RECEIVED " + ladr.LeafCount + " LEAVES: " + packet.Data.Length + " Bytes, Adding/Updating to ledger", DisplayType.Warning); foreach (AccountInfo ai in ladr.Leaves) { LedgerTree.AddUpdate(ai); } } else { DebugPrint("Bad Deserialize : HandleLeafResponse().", DisplayType.Warning); } } else { DebugPrint("Packet VER FAILED : HandleLeafResponse().", DisplayType.Warning); } }
void HandleLeafRequestAll(NetworkPacket packet) { AllLeafDataRequest aldr = new AllLeafDataRequest(); aldr.Deserialize(packet.Data); // DebugPrint("LEAF REQUEST All : " + aldr.TotalRequestedLeaves + " NODES : " + packet.Data.Length + " Bytes", DisplayType.ImportantInfo); if (aldr.TotalRequestedLeaves <= Common.LSYNC_MAX_LEAVES_TO_FETCH) { ListTreeNode node; if (LedgerTree.TraverseToNode(aldr.AddressNibbles, out node) == TraverseResult.Success) { List<LeafDataType> leaves = new List<LeafDataType>(); LedgerTree.GetAllLeavesUnderNode(Common.LSYNC_MAX_LEAVES_TO_FETCH, node, ref leaves); LeafAccountDataResponse ladr = new LeafAccountDataResponse(); foreach (LeafDataType ldt in leaves) { AccountInfo ai = (AccountInfo)ldt; ladr.Add(ai); } NetworkPacket response = new NetworkPacket(nodeConfig.PublicKey, PacketType.TPT_LSYNC_LEAF_RESPONSE, ladr.Serialize(), packet.Token); networkPacketSwitch.AddToQueue(packet.PublicKeySource, response); //DebugPrint("SENT LEAF RESPONSE : " + ladr.LeafCount + " Leaves ... " + response.Data.Length + " Bytes", DisplayType.CodeAssertionFailed); } } }
/// <summary> /// Takes one encoded response, computes delay and diff and stores it /// </summary> /// <param name="packet"></param> private void responseHandler(NetworkPacket packet) { // unpacking response TimeSyncRsMsg response = new TimeSyncRsMsg(); response.Deserialize(packet.Data); Hash sender = packet.PublicKeySource; // if never sent request to this peer, drop packet if (!sentRequests.Keys.Contains(sender)) return; // store response and calculated results if (sentRequests[sender].token == packet.Token) { ResponseStruct rs = new ResponseStruct(); rs.sentTime = response.senderTime; rs.token = packet.Token; rs.receivedTime = nodeState.SystemTime; rs.responderTime = response.responderTime; long delay = (rs.receivedTime - rs.sentTime) / 2; rs.diff = rs.responderTime - delay - rs.sentTime; collectedResponses.AddOrUpdate(sender, rs, (ok, ov) => rs); } }
/// <summary> /// Takes one encoded request and sends an encoded response /// </summary> /// <param name="packet"></param> private void requestHandler(NetworkPacket packet) { // unpacking request TimeSyncRqMsg request = new TimeSyncRqMsg(); request.Deserialize(packet.Data); // sending response TimeSyncRsMsg response = new TimeSyncRsMsg(); response.senderTime = request.senderTime; response.responderTime = nodeState.SystemTime; byte[] data = response.Serialize(); Hash token = packet.Token; NetworkPacket respacket = new NetworkPacket(nodeConfig.PublicKey, PacketType.TPT_TIMESYNC_RESPONSE, data, token); networkPacketSwitch.AddToQueue(packet.PublicKeySource, respacket); }
void HandleSyncFetchResponse(NetworkPacket packet) { TransactionSyncResponse transactionSyncResponse = new TransactionSyncResponse(); transactionSyncResponse.Deserialize(packet.Data); // Verify the correctness and push to database. // CRITICAL. THIS VESION TRUSTS THE SERVER (May not be true in practice) nodeState.PersistentTransactionStore.AddUpdateBatch(transactionSyncResponse.TransactionContents); /*foreach (TransactionContentSet transactionContentSet in transactionSyncResponse.TransactionContents) { // CRITICAL: VERIFY that the transactions are actually valid. Or from fully trusted sources. foreach (TransactionContent transactionContent in transactionContentSet.TxContent) { try { } catch (Exception ex) { DisplayUtils.Display("AddUpdateBatch()", ex); } } }*/ }
void HandleSyncQueryRequest(NetworkPacket packet) { TransactionSyncQueryResponse transactionSyncQueryResponse = new TransactionSyncQueryResponse(); transactionSyncQueryResponse.LedgerSequence = nodeState.NodeInfo.LastLedgerInfo.SequenceNumber; NetworkPacket np = new NetworkPacket(new Hash(nodeState.NodeInfo.PublicKey), PacketType.TPT_TX_SYNC_QUERY_RESPONSE, transactionSyncQueryResponse.Serialize(), packet.Token); network.AddToQueue(new NetworkPacketQueueEntry(packet.PublicKeySource, np)); // Send the reply. }
void HandleNodeResponse(NetworkPacket packet) { // Check that the packet is valid. if (networkPacketSwitch.VerifyPendingPacket(packet)) { NodeInfoResponse nir = new NodeInfoResponse(); nir.Deserialize(packet.Data); // DebugPrint("NodeResponse from " + packet.PublicKeySource + " : " + packet.Data.Length + " Bytes, Nodes : " + nir.TotalRequestedNodes, DisplayType.Warning); foreach (NodeDataEntity nde in nir.RequestedNodes) { PendingNodesToBeFetched.Enqueue(nde); } } else { DebugPrint("Packet VER FAILED : HandleNodeResponse().", DisplayType.Warning); } }
void HandleRootRequest(NetworkPacket packet) { DebugPrint("ROOT DATA REQUESTED BY " + packet.PublicKeySource.ToString(), DisplayType.ImportantInfo); LedgerCloseData ledgerCloseData; if (nodeState.PersistentCloseHistory.GetLastRowData(out ledgerCloseData)) { RootDataResponse rdrm = new RootDataResponse(LedgerTree.RootNode, ledgerCloseData); NetworkPacket response = new NetworkPacket(nodeConfig.PublicKey, PacketType.TPT_LSYNC_ROOT_RESPONSE, rdrm.Serialize(), packet.Token); networkPacketSwitch.AddToQueue(packet.PublicKeySource, response); } }
void HandleRootResponse(NetworkPacket packet) { // Check that the packet is valid. if (networkPacketSwitch.VerifyPendingPacket(packet)) { RootDataResponse rdrm = new RootDataResponse(); rdrm.Deserialize(packet.Data); /// Compare with current tree and matchup. if (LedgerTree.RootNode.Hash != rdrm.RootHash) // Need to match up child nodes. { DebugPrint("MISMATCH: RootResponse from " + packet.PublicKeySource + " : " + packet.Data.Length + " Bytes", DisplayType.Warning); LedgerState = LedgerSyncStateTypes.ST_DATA_FETCH; for (int i = 0; i < 16; i++) { NodeDataEntity remoteChild = rdrm.Children[i]; ListTreeNode currentChild = LedgerTree.RootNode.Children[i]; if (PendingNodesToBeFetched.Count > Common.LSYNC_MAX_PENDING_QUEUE_LENGTH) break; if (remoteChild != null) { if (currentChild == null) { // Download all the data below the node. // Needs to be handled properly, as it may have millions of nodes. PendingNodesToBeFetched.Enqueue(remoteChild); } else { if (remoteChild.NodeHash != currentChild.Hash) { PendingNodesToBeFetched.Enqueue(remoteChild); } } } else { // HANDLE CASE FOR THE REMOTE HAVING NO NODE WHEN WE HAVE // VERIFY WITH OTHERS AND DELETE // ONLY NEEDED IF THE TRUSTED NODES ARE SENDING BAD DATA // SHOULD BE IMPLEMENTED BEFORE FINAL NETWORK COMPLETION } } } else { DebugPrint("ROOT IS SYNCHRONZED WITH: " + packet.PublicKeySource, DisplayType.ImportantInfo); } } else { DebugPrint("Packet VER FAILED : HandleRootResponse().", DisplayType.Warning); } }
/// <summary> /// Initiate gossip-style peer-discovery protocol with a node /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void initiatePeerDiscovery(object sender, ElapsedEventArgs e) { int count = nodeState.ConnectedValidators.Count; if (count <= 0) return; int select = rng.Next(count); Print("init: selecting " + select + " of " + count); Hash peer = nodeState.ConnectedValidators.ToArray()[select]; Hash token = TNetUtils.GenerateNewToken(); //save locally requestRecipient = peer; requestToken = token; //send message PeerDiscoveryMsg request = new PeerDiscoveryMsg(); request.knownPeers = KnownPeers; byte[] message = request.Serialize(); NetworkPacket packet = new NetworkPacket(nodeConfig.PublicKey, PacketType.TPT_PEER_DISCOVERY_INIT, message, token); networkPacketSwitch.AddToQueue(peer, packet); }
void handle_ST_DATA_FETCH() { rootBackoff = ROOT_BACKOFF; long totalOrderedNodes = 0; long totalOrderedLeaves = 0; while ((PendingNodesToBeFetched.Count > 0) && (totalOrderedNodes < Common.LSYNC_MAX_ORDERED_NODES) && (totalOrderedLeaves < Common.LSYNC_MAX_ORDERED_LEAVES)) { NodeDataEntity nde = PendingNodesToBeFetched.Dequeue(); if (nde.LeafCount <= Common.LSYNC_MAX_LEAVES_TO_FETCH) { // Fetch all nodes below List<NodeSocketData> nsds; // A single random trusted node is okay for fetching data. if (nodeConfig.GetRandomTrustedNode(out nsds, 1)) { AllLeafDataRequest aldr = new AllLeafDataRequest(nde); NetworkPacket request = new NetworkPacket(nodeConfig.PublicKey, PacketType.TPT_LSYNC_LEAF_REQUEST_ALL, aldr.Serialize(), TNetUtils.GenerateNewToken()); networkPacketSwitch.AddToQueue(nsds[0].PublicKey, request); totalOrderedLeaves += aldr.TotalRequestedLeaves; } // DebugPrint("Fetch Normal All Nodes Below", DisplayType.ImportantInfo); } else { // Fetch selective nodes //DebugPrint("Fetch Selective Nodes", DisplayType.ImportantInfo); ListTreeNode currentNode; if (LedgerTree.TraverseToNode(nde.AddressNibbles, out currentNode) == TraverseResult.Success) { if (currentNode.Hash != nde.NodeHash) { for (int i = 0; i < 16; i++) { Hash remoteChildHash = nde.Children[i]; ListTreeNode currentChild = currentNode.Children[i]; if (NodeFetchQueue.Count > Common.LSYNC_MAX_PENDING_QUEUE_LENGTH) break; if (remoteChildHash != null) { if (currentChild == null) { FetchRemoteNode(nde.AddressNibbles, (byte)i); totalOrderedNodes++; } else { if (remoteChildHash != currentChild.Hash) { FetchRemoteNode(nde.AddressNibbles, (byte)i); totalOrderedNodes++; } } } else { //DebugPrint("REMOTE NULL !!", DisplayType.ImportantInfo); // HANDLE CASE FOR THE REMOTE HAVING NO NODE WHEN WE HAVE // VERIFY WITH OTHERS AND DELETE // ONLY NEEDED IF THE TRUSTED NODES ARE SENDING BAD DATA // SHOULD BE IMPLEMENTED BEFORE FINAL NETWORK COMPLETION } } } } else { // ORDER ALL NODES BELOW. Probably in the initial condition. for (int i = 0; i < 16; i++) { FetchRemoteNode(nde.AddressNibbles, (byte)i); totalOrderedNodes++; } } } } ProcessPendingRemoteFetches(); if (PendingNodesToBeFetched.Count == 0) LedgerState = LedgerSyncStateTypes.ST_GOOD; }
private void respondPeerDiscovery(NetworkPacket packet) { PeerDiscoveryMsg request = new PeerDiscoveryMsg(); request.Deserialize(packet.Data); // process incoming peer list processNewPeerList(request.knownPeers); // send message with own peer list Hash token = packet.Token; Hash peer = packet.PublicKeySource; PeerDiscoveryMsg response = new PeerDiscoveryMsg(); response.knownPeers = KnownPeers; byte[] message = response.Serialize(); NetworkPacket newpacket = new NetworkPacket(nodeConfig.PublicKey, PacketType.TPT_PEER_DISCOVERY_RESPONSE, message, token); networkPacketSwitch.AddToQueue(peer, newpacket); }
/// <summary> /// All is well, let's get a random trusted peer and ask for the current root. /// </summary> void handle_ST_ROOT() { List<NodeSocketData> nsds; // THINK: HOW MANY NODES TO CONNECT TO ?? if (nodeConfig.GetRandomTrustedNode(out nsds, 1)) { foreach (NodeSocketData nsd in nsds) { NetworkPacket request = new NetworkPacket(nodeConfig.PublicKey, PacketType.TPT_LSYNC_ROOT_REQUEST, new byte[0], TNetUtils.GenerateNewToken()); networkPacketSwitch.AddToQueue(nsd.PublicKey, request); } } }
public NetworkResult AddToQueue(Hash publicKeyDestination, NetworkPacket packet) { return network.AddToQueue(publicKeyDestination, packet); }
void networkHandler_LedgerSyncEvent(NetworkPacket packet) { switch (packet.Type) { case PacketType.TPT_LSYNC_ROOT_REQUEST: HandleRootRequest(packet); break; case PacketType.TPT_LSYNC_ROOT_RESPONSE: HandleRootResponse(packet); break; case PacketType.TPT_LSYNC_LEAF_REQUEST_ALL: HandleLeafRequestAll(packet); break; case PacketType.TPT_LSYNC_LEAF_RESPONSE: HandleLeafResponse(packet); break; case PacketType.TPT_LSYNC_NODE_REQUEST: HandleNodeRequest(packet); break; case PacketType.TPT_LSYNC_NODE_RESPONSE: HandleNodeResponse(packet); break; } }
/// <summary> /// This will switch packets whichever it should go. /// </summary> /// <param name="packet"></param> void network_PacketReceived(NetworkPacket packet) { //DisplayUtils.Display(" Packet: " + packet.Type + " | From: " + packet.PublicKeySource + " | Data Length : " + packet.Data.Length); switch (packet.Type) { case PacketType.TPT_CONS_MERGE_REQUEST: case PacketType.TPT_CONS_MERGE_RESPONSE: if (VoteMergeEvent != null) VoteMergeEvent(packet); break; case PacketType.TPT_CONS_STATE: case PacketType.TPT_CONS_BALLOT_REQUEST: case PacketType.TPT_CONS_BALLOT_RESPONSE: case PacketType.TPT_CONS_BALLOT_AGREE_REQUEST: case PacketType.TPT_CONS_BALLOT_AGREE_RESPONSE: if (VoteEvent != null) VoteEvent(packet); break; case PacketType.TPT_LSYNC_ROOT_REQUEST: case PacketType.TPT_LSYNC_ROOT_RESPONSE: case PacketType.TPT_LSYNC_NODE_REQUEST: case PacketType.TPT_LSYNC_NODE_RESPONSE: case PacketType.TPT_LSYNC_LEAF_REQUEST: case PacketType.TPT_LSYNC_LEAF_REQUEST_ALL: case PacketType.TPT_LSYNC_LEAF_RESPONSE: if (LedgerSyncEvent != null) LedgerSyncEvent(packet); break; case PacketType.TPT_TX_SYNC_FETCH_REQUEST: case PacketType.TPT_TX_SYNC_FETCH_RESPONSE: case PacketType.TPT_TX_SYNC_ID_REQUEST: case PacketType.TPT_TX_SYNC_ID_RESPONSE: case PacketType.TPT_TX_SYNC_QUERY_REQUEST: case PacketType.TPT_TX_SYNC_QUERY_RESPONSE: case PacketType.TPT_TX_SYNC_CLOSEHISTORY_REQUEST: case PacketType.TPT_TX_SYNC_CLOSEHISTORY_RESPONSE: break; case PacketType.TPT_TIMESYNC_REQUEST: case PacketType.TPT_TIMESYNC_RESPONSE: if (TimeSyncEvent != null) TimeSyncEvent(packet); break; case PacketType.TPT_PEER_DISCOVERY_INIT: case PacketType.TPT_PEER_DISCOVERY_RESPONSE: if (PeerDiscoveryEvent != null) PeerDiscoveryEvent(packet); break; } }
public NetworkPacketQueueEntry(Hash publicKeyDestination, NetworkPacket packet) { PublicKeyDestination = publicKeyDestination; Packet = packet; TransmitAttempts = 0; }