// Initializes a new incoming packet internal Packet(PacketHeader Header, PortableStorage Body) { Type = (PacketType)Header.CommandCode; Flag = (PacketFlag)Header.Flag; this.Header = Header; this.Body = Body; }
// Processes our packet reading buffer to deserialize it into a usable packet internal void ProcessBuffer(byte[] Data) { // Add this data to our working byte buffer Buffer = Buffer.AppendBytes(Data); // Header deserialization if (State == ReadState.Header) { // Check if we have enough data for a packet header if (Buffer.Length < 33) { return; } // Attempt to deserialize our packet header try { // Store header data and set our read state to body Header = new PacketHeader(Buffer); State = ReadState.Body; } catch { } // Remove the bytes we read from our buffer Buffer = Buffer.SubBytes(33, Buffer.Length - 33); } // Body deserialization if (State == ReadState.Body) { // Check whether our buffer is the correct size if ((ulong)Buffer.LongLength < Header.PayloadSize) { return; } // Attempt to deserialize our packet body try { // Get body bytes var BodyBytes = Buffer.SubBytes(0, (int)Header.PayloadSize); // Store deserialized body object var Body = new PortableStorage(BodyBytes, out _); // Invoke our packet received handler Node.HandlePacket(this, new Packet(Header, Body)); } catch { } // Remove the bytes we read from our buffer Buffer = Buffer.SubBytes((int)Header.PayloadSize, Buffer.Length - (int)Header.PayloadSize); // Reset our read state back to header State = ReadState.Header; } }
// Handles core sync data sent by peers private void AddSyncData(Peer Peer, PortableStorage SyncData) { // TODO - handle syncing // TODO - queue sync data? // TODO - compare heights and top block ids of peers? if (SyncData["current_height"] > Blockchain.KnownHeight) { Blockchain.KnownHeight = SyncData["current_height"]; } }
// Serializes request data into a byte array public byte[] Serialize() { // Create a portable storage PortableStorage Storage = new PortableStorage(); // Add entries Storage.AddEntryAsBinary("txs", Txs); // Return serialized byte array return(Storage.Serialize()); }
// Serializes request data into a byte array public byte[] Serialize() { // Create a portable storage PortableStorage Storage = new PortableStorage(); // Add entries Storage.AddEntry("payload_data", PayloadData); // Return serialized byte array return(Storage.Serialize()); }
// Deseriaizes response data public static Request Deserialize(byte[] Data) { // Deserialize data PortableStorage Storage = new PortableStorage(); Storage.Deserialize(Data); // Populate and return new response return(new Request { Txs = Hashing.DeserializeHashArray((string)Storage.GetEntry("txs")) }); }
// Serializes response data public byte[] Serialize() { // Create a portable storage PortableStorage Storage = new PortableStorage(); // Add entries Storage.AddEntry("local_time", LocalTime); Storage.AddEntry("payload_data", PayloadData); Storage.AddEntryAsBinary("local_peerlist", LocalPeerlist); // Return serialized byte array return(Storage.Serialize()); }
// Deseriaizes response data public static Request Deserialize(byte[] Data) { // Deserialize data PortableStorage Storage = new PortableStorage(); Storage.Deserialize(Data); // Populate and return new response return(new Request { PayloadData = CoreSyncData.Deserialize(Storage.GetEntry("payload_data")) }); }
// Deseriaizes response data public static Response Deserialize(byte[] Data) { // Deserialize data PortableStorage Storage = new PortableStorage(); Storage.Deserialize(Data); // Populate and return new response return(new Response { Status = (string)Storage.GetEntry("status"), PeerId = (ulong)Storage.GetEntry("peer_id") }); }
// Deseriaizes response data public static Response Deserialize(byte[] Data) { // Deserialize data PortableStorage Storage = new PortableStorage(); Storage.Deserialize(Data); // Populate and return new response return(new Response { LocalTime = (ulong)Storage.GetEntry("local_time"), PayloadData = CoreSyncData.Deserialize(Storage.GetEntry("payload_data")), LocalPeerlist = Storage.DeserializeArrayFromBinary <PeerlistEntry>("local_peerlist") }); }
// Initializes a new outgoing packet internal Packet(PacketType Type, PacketFlag Flag, bool ResponseRequired, bool Success = true) { this.Type = Type; this.Flag = Flag; Body = new PortableStorage(); Header = new PacketHeader() { Signature = 0x0101010101012101UL, ProtocolVersion = 1, CommandCode = (uint)Type, ResponseRequired = ResponseRequired, ReturnCode = (uint)(Success ? 0 : 1), // 0 = success Flag = (uint)Flag }; }
// Handles core sync data sent by peers private void HandleSyncData(Peer Peer, PortableStorage SyncData) { // Update peer height Peer.Height = SyncData["current_height"]; // Check if peer is syncing if (Peer.State == PeerState.SYNCHRONIZING) { return; } // Check if we have this block stored if (Blockchain.IsBlockStored(SyncData["top_id"])) { Peer.State = PeerState.NORMAL; return; } // Update observed height UpdateObservedHeight(Peer.Height); // Get the height difference between the local cache and remote node int Diff = (int)Blockchain.KnownHeight - (int)Blockchain.Height; int Days = Math.Abs(Diff) / (86_400 / Globals.CURRENCY_DIFFICULTY_TARGET); // Print how for behind/ahead we are StringBuilder Output = new StringBuilder($"[{Peer.Address}:{Peer.Port} {Peer.P2pPeer.Direction}] "); Output.Append($"Your {Globals.CURRENCY_NAME} node is syncing with the network"); if (Diff >= 0) { Output.Append($" ({Math.Round((decimal)Blockchain.Height / Peer.Height * 100, 2)}% complete)"); Output.Append($". You are {Diff} blocks ({Days} days) behind "); } else { Output.Append($". You are {Math.Abs(Diff)} blocks ({Days} days) ahead of "); } Output.Append("the current peer you're connected to. Please be patient while we synchronise with the network!"); // If peer isn't validated, this is first contact if (!Peer.Validated) { Logger.Important(Output); } else { Logger.Debug(Output); } // Log debug message Logger.Debug($"Remote top block height: {Peer.Height}, id: {SyncData["top_id"]}"); // TODO - this is just test code /*Blockchain.StoreBlock(new Block() * { * Height = Peer.Height, * Hash = SyncData["top_id"] * });*/ // Set new peer state Peer.State = PeerState.SYNC_REQUIRED; // Construct a response packet var Request = new Packet(PacketType.NOTIFY_CHAIN_REQUEST, PacketFlag.REQUEST, true) { ["block_ids"] = GetSparseChain() }; // Send our request Peer.SendMessage(Request); // TODO - handle syncing Peer.State = PeerState.SYNCHRONIZING; }