public LedgerSync(NodeState nodeState, NodeConfig nodeConfig, NetworkPacketSwitch networkPacketSwitch) { this.nodeState = nodeState; this.nodeConfig = nodeConfig; this.networkPacketSwitch = networkPacketSwitch; this.LedgerTree = nodeState.Ledger.LedgerTree; // Just aliasing. LedgerState = LedgerSyncStateTypes.ST_GOOD; this.networkPacketSwitch.LedgerSyncEvent += networkHandler_LedgerSyncEvent; TimerLedgerSync = new System.Timers.Timer(); if (Enable) TimerLedgerSync.Elapsed += TimerLedgerSync_Elapsed; TimerLedgerSync.Enabled = true; TimerLedgerSync.Interval = nodeConfig.UpdateFrequencyLedgerSyncMS; TimerLedgerSync.Start(); TimerLedgerSync_Root = new System.Timers.Timer(); if (Enable) TimerLedgerSync_Root.Elapsed += TimerLedgerSync_Root_Elapsed; TimerLedgerSync_Root.Enabled = true; TimerLedgerSync_Root.Interval = nodeConfig.UpdateFrequencyLedgerSyncMS_Root; TimerLedgerSync_Root.Start(); }
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; }
void TimerLedgerSync_Root_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { lock (LedgerSyncLock) { switch (LedgerState) { case LedgerSyncStateTypes.ST_GOOD: if (PendingNodesToBeFetched.Count == 0) { if(rootBackoff > 0) rootBackoff--; if (rootBackoff <= 0) { handle_ST_ROOT(); } } else { LedgerState = LedgerSyncStateTypes.ST_DATA_FETCH; handle_ST_DATA_FETCH(); } break; } } }
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); } }