diff --git a/SPHERE/Blockchain/Block/Block.cs b/SPHERE/Blockchain/Block/Block.cs
index 72c92bf..d3bcdbe 100644
--- a/SPHERE/Blockchain/Block/Block.cs
+++ b/SPHERE/Blockchain/Block/Block.cs
@@ -76,9 +76,6 @@ namespace SPHERE.Blockchain
[JsonPropertyName("LastUpdateTime")]
public required DateTime LastUpdateTime { get; set; } = new(); // Time stamp of last Update to the block by validated user.
- [JsonPropertyName("EncryptionAlgorithm")]
- public required string EncryptionAlgorithm { get; set; } = ""; // Algorithm used for encryption (e.g. AES256, RSA2048, ECDsa)
-
[JsonPropertyName("KeyUsagePolicies")]
public required string? KeyUsagePolicies { get; set; } // Policies for key usage
@@ -100,7 +97,7 @@ namespace SPHERE.Blockchain
// Calculates the hash for the block
public string CalculateBlockHash()
{
- string input = $"{BlockId}{PreviousHash}{BlockCreationTime}{EncryptionAlgorithm}{KeyUsagePolicies}";
+ string input = $"{BlockId}{PreviousHash}{BlockCreationTime}{KeyUsagePolicies}";
using var sha256 = SHA256.Create();
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] hashBytes = sha256.ComputeHash(inputBytes);
@@ -128,41 +125,45 @@ namespace SPHERE.Blockchain
// Creating a Contact Block
- public static Block CreateContactBlock(Node node, string nodeId, string previousHash, string encryptedContactData, EncryptionAlgorithm encryptionAlgorithm)
+ public static Block CreateContactBlock(Node node, string previousHash, Contact contact)
{
//Check to see if Keys exist.
- PrivateKeyManager PrivateKeyManager = new();
+
DateTime creationTime = DateTime.Now;
+ byte[] LSK = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.LocalSymmetricKey);
+ if (LSK == null || LSK.Length == 0)
+ {
+ SystemLogger.Log($"Debug-CreateContactBlock: LocalSymmetricKey is null or empty");
+ return null;
+ }
+
+ byte[] encryptedContactData = Contact.BuildEncryptedContact(contact, LSK);
var header = new BlockHeader
{
- BlockId = BlockHeader.GenerateBlockID(),
+ BlockId = contact.MetaData.ContactID,
BlockType = BlockType.Contact.ToString(),
BlockVersion = "1.0",
PreviousHash = previousHash,
BlockCreationTime = creationTime,
LastUpdateTime = creationTime,
- EncryptionAlgorithm = encryptionAlgorithm.ToString(),
KeyUsagePolicies = "MESSAGE_ENCRYPTION_ONLY",
- PublicSignatureKey = PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
- PublicEncryptionKey = PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalEncryptionKey),
- CreatorNodeId = nodeId,
+ PublicSignatureKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
+ PublicEncryptionKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalEncryptionKey),
+ CreatorNodeId = node.Peer.NodeId,
};
- // Serialize and store contact data
- string serializedContactData = JsonSerializer.Serialize(encryptedContactData);
-
header.BlockHash = header.CalculateBlockHash();
-
-
- return new Block
+ Block block = new Block
{
Header = header,
- EncryptedContact = serializedContactData,
- EncryptedLocalSymmetricKey = PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.EncryptedLocalSymmetricKey),
+ EncryptedContact = Convert.ToBase64String(encryptedContactData),
+ EncryptedLocalSymmetricKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.EncryptedLocalSymmetricKey),
};
+
+ return block;
}
// Checks if a block is a contact block
@@ -186,7 +187,6 @@ namespace SPHERE.Blockchain
PreviousHash = previousHash,
BlockCreationTime = creationTime,
LastUpdateTime = creationTime,
- EncryptionAlgorithm = encryptionAlgorithm.ToString(),
KeyUsagePolicies = "MESSAGE_ENCRYPTION_ONLY",
PublicSignatureKey =PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
PublicEncryptionKey =PrivateKeyManager.UseKeyInStorageContainer(node,KeyGenerator.KeyType.PublicPersonalEncryptionKey),
@@ -227,7 +227,6 @@ namespace SPHERE.Blockchain
PreviousHash = previousHash,
BlockCreationTime = creationTime,
LastUpdateTime = creationTime,
- EncryptionAlgorithm = encryptionAlgorithm.ToString(),
KeyUsagePolicies = "MESSAGE_ENCRYPTION_ONLY",
PublicSignatureKey =PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
PublicEncryptionKey =PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalEncryptionKey),
diff --git a/SPHERE/Blockchain/Block/Contact.cs b/SPHERE/Blockchain/Block/Contact.cs
index 2fd72eb..225cffe 100644
--- a/SPHERE/Blockchain/Block/Contact.cs
+++ b/SPHERE/Blockchain/Block/Contact.cs
@@ -1,22 +1,25 @@
using SPHERE.Configure;
using SPHERE.Security;
+using System.Collections.Generic;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Text.Json;
namespace SPHERE.Blockchain
{
public class Contact
{
- public ContactMetaData MetaData { get; set; } // Contacts needed MetaData.
- public ContactKeys Keys { get; set; } // Contacts needed Encryption keys.
- public EncryptedKeyParts KeySignatureParts { get; set; } // Contacts Private key is encrypted and stored in parts with noise
- public EncryptedKeyParts KeyEncryptionParts { get; set; } // Contacts Private key is encrypted and stored in parts with noise
- public List<(byte[], byte[])> AuthenticationData = new(); // Hashes user for User Authentication and VAlidation for Password reset and recovery.
+ public required ContactMetaData MetaData { get; set; } // Contacts needed MetaData.
+ public required ContactKeys Keys { get; set; } // Contacts needed Encryption keys.
+ public required EncryptedKeyParts KeySignatureParts { get; set; } // Contacts Private key is encrypted and stored in parts with noise
+ public required EncryptedKeyParts KeyEncryptionParts { get; set; } // Contacts Private key is encrypted and stored in parts with noise
+ public required List<(byte[], byte[])> AuthenticationData = new(); // Hashes user for User Authentication and VAlidation for Password reset and recovery.
///
/// !!!
/// To Create a contact and Generate Pairs of needed Private Keys, A password is needed to be passed in. This is a string meeting Requirements. (Needs Upper, Lower, Number, Symbol, and to be between 8-64 characters.)
/// User Password.CreatePasswordFromString(string password) to generate a password from a string or Password.GenerateRandomPassword(int length) defaults to 16char.
- ///
+ ///
///
///
///
@@ -25,60 +28,81 @@ namespace SPHERE.Blockchain
/// !!!
///
///
- public static Contact CreateNewContact(Node node, string displayName, string name, string blockId, string? avatarURL, string? description, Password privateKeyPassword)
+ public static Contact CreateNewContact(Node node, string contactId, string alias, string name, Password privateKeyPassword, string pin)
{
- PrivateKeyManager PrivateKeyManager = new();
+ PrivateKeyManager privateKeyManager = node.KeyManager;
//Generate the set or Key Pairs needed (Signature and Communication pair)
- KeyGenerator.GeneratePersonalKeyPairSets(privateKeyPassword);
+ KeyGenerator.GeneratePersonalKeyPairSets(node);
var semiPublicKey = KeyGenerator.GenerateSymmetricKey();
- PrivateKeyManager.SetPrivatePersonalKey(semiPublicKey, KeyGenerator.KeyType.SemiPublicKey);
+ privateKeyManager.SetPrivatePersonalKey(node, semiPublicKey, KeyGenerator.KeyType.SemiPublicKey);
//used to encrypt the contact
var localSymmetricKey = KeyGenerator.GenerateSymmetricKey();
- PrivateKeyManager.SetPrivatePersonalKey(localSymmetricKey, KeyGenerator.KeyType.LocalSymmetricKey);
+ privateKeyManager.SetPrivatePersonalKey(node, localSymmetricKey, KeyGenerator.KeyType.LocalSymmetricKey);
//the LocalSymmetricKey is Encrypted with the SemiPublicKey and attached to the block so only approved people with the semiPublicKey can decrypt the EncryptedLocalSymetricKey and then decrypt the contact.
var encryptedLocalSymmetricKey = Encryption.EncryptLocalSymmetricKey(localSymmetricKey, semiPublicKey);
- PrivateKeyManager.SetPrivatePersonalKey(encryptedLocalSymmetricKey, KeyGenerator.KeyType.EncryptedLocalSymmetricKey);
-
+
+ privateKeyManager.SetPrivatePersonalKey(node, encryptedLocalSymmetricKey, KeyGenerator.KeyType.EncryptedLocalSymmetricKey);
+
ContactKeys keys = new ContactKeys
{
- PublicPersonalEncryptionKey = PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalEncryptionKey),
- PublicPersonalSignatureKey = PrivateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
+ PublicPersonalEncryptionKey = privateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalEncryptionKey),
+ PublicPersonalSignatureKey = privateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey),
SemiPublicKey = semiPublicKey,
- LocalSymmetricKey = localSymmetricKey
+ EncryptedLocalSymmetricKey = encryptedLocalSymmetricKey
+
};
ContactMetaData metaData = new ContactMetaData
{
- DisplayName = displayName,
+ DisplayName = alias,
Name = name,
- AvatarURLHash = avatarURL,
- Description = description,
-
+ ContactID = contactId,
+ ContactVersion="V1.0"
};
+
+
+ EncryptedKeyParts encryptedSignatureKeyParts = node.KeyManager.EncryptPersonalKeyParts(node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PrivatePersonalSignatureKey), privateKeyPassword.ToString(), pin);
+ EncryptedKeyParts encryptedEncryptionKeyParts = node.KeyManager.EncryptPersonalKeyParts(node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PrivatePersonalEncryptionKey), privateKeyPassword.ToString(), pin);
Contact contact = new Contact
{
MetaData = metaData,
Keys = keys,
-
+ KeySignatureParts = encryptedSignatureKeyParts,
+ KeyEncryptionParts = encryptedEncryptionKeyParts,
+ AuthenticationData = CredentialManager.GenerateStoredHashes(privateKeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicPersonalSignatureKey), privateKeyPassword.ToString(), pin, contactId),
};
+
+
+
return contact;
}
- public static byte[] BuildEncryptedContact(Contact contact)
+ public static byte[] BuildEncryptedContact(Contact contact, byte[] localSymmetricKey)
{
-
- var encryptedContact = Encryption.EncryptWithSymmetric(contact, contact.Keys.LocalSymmetricKey);
+
+ // Encrypt the serialized data
+ byte[] encryptedContact = Encryption.EncryptContactWithSymmetric(contact, localSymmetricKey);
return encryptedContact;
-
}
+ public static Contact DecryptAndBuildContact(string encryptedContact, byte[] localSymmetricKey)
+ {
+ // Decode the Base64 data directly
+
+ //byte[] decryptedBytes = Encryption.DecryptContactWithSymmetricKey(encryptedContact, localSymmetricKey);
+
+ // Deserialize the Contact object
+ Contact contact = Encryption.DecryptContactWithSymmetricKey(encryptedContact, localSymmetricKey); ;
+
+ return contact;
+ }
///
/// The contact is intended to be the core of a block. It will be encrypted with a Local Symmetric Key before it is placed on the block.
/// The purpose is to allow for users to control their data, but also gain the security and decentralization of a p2p DHT.
@@ -101,9 +125,10 @@ namespace SPHERE.Blockchain
///
public class ContactMetaData()
{
- public string DisplayName { get; set; } // User's display name
- public string Name { get; set; } // Users Name
- public string ContactVersion { get; set; } // Contact versions would allow for deserialization of different contact styles as the platform evolves.
+ public required string DisplayName { get; set; } // User's display name
+ public required string Name { get; set; } // Users Name
+ public required string ContactID { get; set; } // Contacts User ID (BLOCK ID)
+ public required string ContactVersion { get; set; } // Contact versions would allow for deserialization of different contact styles as the platform evolves.
public string? HashedSSN { get; set; } // Users can provide a salted Hash of their SSN and this can be used later by applications to comparir it against the a hash of the ssn and key provided by the user. (Optional)
public string? HashedCardNumber { get; set; } // Users can provide a salted Hash of their Card Number, this will by used by verification server when provided the cc and key by the user, if it can verify the hash it creates a 1 way payment tunnel from there to the merchants account. the merchant never sees the data (optional)
public string? HashedAccountNumber { get; set; } // Users can provide a salted Hash of their Recount, this will by used by verification server when provided the account number and key by the user, if it can verify the hash it creates a 1 way payment tunnel from there to the merchants account.(optional)
@@ -117,10 +142,10 @@ namespace SPHERE.Blockchain
public class ContactKeys()
{
- public byte[] SemiPublicKey { get; set; } // Semi-public key
- public byte[] LocalSymmetricKey { get; set; } // Unencrypted Local Symmetric code used to encrypt the Contact.
- public byte[] PublicPersonalEncryptionKey { get; set; } // Personal Communication key for encrypting messages only the user can decrypt
- public byte[] PublicPersonalSignatureKey { get; set; } // Used to verify signatures created with the PrivateSignatureKey
+ public required byte[] SemiPublicKey { get; set; } // Semi-public key
+ public required byte[] EncryptedLocalSymmetricKey { get; set; } // Unencrypted Local Symmetric code used to encrypt the Contact.
+ public required byte[] PublicPersonalEncryptionKey { get; set; } // Personal Communication key for encrypting messages only the user can decrypt
+ public required byte[] PublicPersonalSignatureKey { get; set; } // Used to verify signatures created with the PrivateSignatureKey
}
}
diff --git a/SPHERE/Blockchain/Block/Node.cs b/SPHERE/Blockchain/Block/Node.cs
index 93a0d7e..d94f48f 100644
--- a/SPHERE/Blockchain/Block/Node.cs
+++ b/SPHERE/Blockchain/Block/Node.cs
@@ -102,7 +102,7 @@ namespace SPHERE.Blockchain
//create a node.
Node node = new Node();
string nodeId = GenerateKademliaId();
- //Create a client for the node using STUN.
+
try
{
@@ -153,9 +153,27 @@ namespace SPHERE.Blockchain
try
{
// Load DHT state (internal locking already handled by LoadState)
- if (File.Exists(DHT.GetAppDataPath("DHT")))
+ if (File.Exists(DHT.GetAppDataPath(node, "ContactDHT")))
{
- node.ContactDHT.LoadState();
+ node.ContactDHT.LoadState(node,"ContactDHT");
+ }
+ else
+ {
+ SystemLogger.Log("DHT state file not found. Starting with a fresh state.");
+ }
+
+ if (File.Exists(DHT.GetAppDataPath(node, "TransactionDHT")))
+ {
+ node.TransactionDHT.LoadState(node, "TransactionDHT");
+ }
+ else
+ {
+ SystemLogger.Log("DHT state file not found. Starting with a fresh state.");
+ }
+
+ if (File.Exists(DHT.GetAppDataPath(node, "ReputationDHT")))
+ {
+ node.ReputationDHT.LoadState(node, "ReputationDHT");
}
else
{
@@ -174,9 +192,9 @@ namespace SPHERE.Blockchain
try
{
// Load RoutingTable state (internal locking already handled by LoadState)
- if (File.Exists(DHT.GetAppDataPath("RT")))
+ if (File.Exists(DHT.GetAppDataPath(node, "RT")))
{
- node.RoutingTable.LoadRoutingTable();
+ node.RoutingTable.LoadRoutingTable(node, "RT");
}
else
{
@@ -190,29 +208,23 @@ namespace SPHERE.Blockchain
{
SystemLogger.Log($"Error loading RoutingTable state: {ex.Message}");
SystemLogger.Log("Starting with a fresh state.");
- node.RoutingTable = new RoutingTable(); // Reinitialize
+ node.RoutingTable = new RoutingTable();
}
+
node.RoutingTable.node = node;
return node;
}
//This is used to Create the Node and Listener or Load one if it exists.
- public static Node CreateNodeWithClientListenerUsingSTUN(NodeType nodeType)
+ public static Node CreateNodeUsingSTUN(NodeType nodeType)
{
-
-
- //create a node.
+ SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Creating Node with STUN");
Node node = new Node();
node.Peer.NodeId = Node.GenerateKademliaId();
node.KeyManager = new();
node.KeyManager.SetNodeEncryptionFilePath(node);
- //Create a client get listeners using STUN.
-
- Client client = new Client();
-
-
- // Thread-safe key generation
- lock (stateLock)
+ node.Client = new Client();
+ try
{
try
{
@@ -225,78 +237,129 @@ namespace SPHERE.Blockchain
Console.WriteLine($"Error-CreateTestNodeWithFakeSTUNAsync: Generating Key pairs. Reason: {ex.Message}");
throw;
}
- }
- client.StartClientListenerWithSTUNSync(node, client);
- node.Client = client;
- try
- {
- // Initialize PeerHeader
- Peer peer = new Peer
+ var stun = new STUN();
+ var (PublicIP, PublicPort) = stun.GetPublicEndpoint();
+ SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: STUN Returned an IP of: {PublicIP}.");
+ SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: STUN Returned a Port of: {PublicPort}.");
+
+ string testModeEnv = Environment.GetEnvironmentVariable("SPHERE_TEST_MODE");
+ SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Test mode: {testModeEnv}.");
+ node.Client.clientIP = node.Client.GetLocalIPAddress();
+ if (testModeEnv!="true")
{
- Node_Type = nodeType,
- NodeIP = client.clientIP.ToString(),
- NodePort = client.clientListenerPort,
- PreviousNodesHash = DefaultPreviousHash, // Placeholder value
- PublicSignatureKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicNodeSignatureKey),
- PublicEncryptKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicNodeEncryptionKey),
- };
+ node.Client.clientIP = PublicIP;
+ }
+ node.Client.clientListenerPort = PublicPort;
+
+
+ try
+ {
+ Console.WriteLine("Initializing Peer Header...");
+ Peer peer = new Peer
+ {
+ Node_Type = nodeType,
+ NodeId = node.Peer.NodeId,
+ NodeIP = node.Client.clientIP.ToString(),
+ NodePort = PublicPort,
+ PreviousNodesHash = Node.DefaultPreviousHash,
+ PublicSignatureKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicNodeSignatureKey),
+ PublicEncryptKey = node.KeyManager.UseKeyInStorageContainer(node, KeyGenerator.KeyType.PublicNodeEncryptionKey),
+ };
+ node.Peer = peer;
+ SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Node Client IP of: {node.Client.clientIP.ToString()}.");
+ SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Node Client Port of: {node.Client.clientListenerPort}.");
+
+ SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Peer IP of: {node.Peer.NodeIP}.");
+ SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Peer Port of: {node.Peer.NodePort}.");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error Creating Peer Header: {ex.Message}");
+ throw;
+ }
+
+ try
+ {
+ // Load DHT state (internal locking already handled by LoadState)
+ if (File.Exists(DHT.GetAppDataPath(node, "ContactDHT")))
+ {
+ node.ContactDHT.LoadState(node, "ContactDHT");
+ }
+ else
+ {
+ SystemLogger.Log("ContactDHT state file not found. Starting with a fresh state.");
+ node.ContactDHT = new DHT();
+ }
+
+ if (File.Exists(DHT.GetAppDataPath(node, "ReputationDHT")))
+ {
+ node.ReputationDHT.LoadState(node, "ReputationDHT");
+ }
+ else
+ {
+ SystemLogger.Log("ReputationDHT state file not found. Starting with a fresh state.");
+ node.ReputationDHT = new DHT();
+ }
+
+ if (File.Exists(DHT.GetAppDataPath(node, "TransactionDHT")))
+ {
+ node.TransactionDHT.LoadState(node, "TransactionDHT");
+ }
+ else
+ {
+ SystemLogger.Log("TransactionDHT state file not found. Starting with a fresh state.");
+ node.TransactionDHT = new DHT();
+ }
+
+
+ }
+ catch (Exception ex)
+ {
+ SystemLogger.Log($"Error loading DHT state: {ex.Message}");
+
+
+ }
+
+ try
+ {
+ // Load RoutingTable state (internal locking already handled by LoadState)
+ if (File.Exists(DHT.GetAppDataPath(node, "RT")))
+ {
+ node.RoutingTable.LoadRoutingTable(node, "RT");
+ }
+ else
+ {
+ SystemLogger.Log("Routing Table state file not found. Starting with a fresh state.");
+ node.RoutingTable = new RoutingTable();
+ }
+
+
+ }
+ catch (Exception ex)
+ {
+ SystemLogger.Log($"Error loading RoutingTable state: {ex.Message}");
+ }
+
+ if (node != null)
+ {
+ SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Node is build returning Node.");
+ node.Client.StartClientListenerAsync(node);
+ return node;
+ }
+ else
+ {
+ SystemLogger.Log($"Debug-CreateNodeWithClientUsingSTUN: Node was returned null.");
+ return null;
+ }
+
- // Assign header to node
- node.Peer = peer;
}
catch (Exception ex)
{
- SystemLogger.Log($"Error retrieving or creating keys: {ex.Message}");
+ Console.WriteLine($"Error CreatingNodeWithClientUsingStun: EndFail{ex.Message}");
throw;
}
-
- // Initialize DHT
- node.ContactDHT = new DHT();
-
- try
- {
- // Load DHT state (internal locking already handled by LoadState)
- if (File.Exists(DHT.GetAppDataPath("DHT")))
- {
- node.ContactDHT.LoadState();
- }
- else
- {
- SystemLogger.Log("DHT state file not found. Starting with a fresh state.");
- }
-
-
- }
- catch (Exception ex)
- {
- SystemLogger.Log($"Error loading DHT state: {ex.Message}");
- SystemLogger.Log("Starting with a fresh state.");
- node.ContactDHT = new DHT(); // Reinitialize
- }
-
- try
- {
- // Load RoutingTable state (internal locking already handled by LoadState)
- if (File.Exists(DHT.GetAppDataPath("RT")))
- {
- node.RoutingTable.LoadRoutingTable();
- }
- else
- {
- SystemLogger.Log("Routing Table state file not found. Starting with a fresh state.");
- }
-
-
- }
- catch (Exception ex)
- {
- SystemLogger.Log($"Error loading RoutingTable state: {ex.Message}");
- SystemLogger.Log("Starting with a fresh state.");
- node.RoutingTable = new RoutingTable(); // Reinitialize
- }
-
- return node;
}
//Once the Node has a Routing Table it can get the Previous Hash and update the Previous Hash
@@ -382,7 +445,7 @@ namespace SPHERE.Blockchain
//Generate Node and Block Id's
internal static string GenerateKademliaId()
{
- byte[] randomBytes = new byte[32]; // 256 bits = 32 bytes
+ byte[] randomBytes = new byte[32];
// Use the modern RandomNumberGenerator.Fill method
System.Security.Cryptography.RandomNumberGenerator.Fill(randomBytes);
diff --git a/SPHERE/Blockchain/Chain/DHT/DHT.cs b/SPHERE/Blockchain/Chain/DHT/DHT.cs
index 2a86e4e..d1244fd 100644
--- a/SPHERE/Blockchain/Chain/DHT/DHT.cs
+++ b/SPHERE/Blockchain/Chain/DHT/DHT.cs
@@ -143,11 +143,12 @@ namespace SPHERE.Blockchain
}
}
- public static string GetAppDataPath(string fileName)
+ public static string GetAppDataPath(Node node, string fileName)
{
string appDataDir;
+ string firstSix = node.Peer.NodeId.Length >= 6 ? node.Peer.NodeId.Substring(0, 6) : node.Peer.NodeId;
appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
- return Path.Combine(appDataDir, $"{AppIdentifier.GetOrCreateServiceName()}{fileName}.state");
+ return Path.Combine(appDataDir, $"{AppIdentifier.GetOrCreateServiceName()}{firstSix}{fileName}.state");
}
///
@@ -206,23 +207,18 @@ namespace SPHERE.Blockchain
return false;
}
- // Optionally validate encryption algorithm, signature, or other policies
- if (block.Header.EncryptionAlgorithm != "AES256" && block.Header.EncryptionAlgorithm != "RSA2048")
- {
- SystemLogger.Log($"Unsupported encryption algorithm: {block.Header.EncryptionAlgorithm}");
- return false;
- }
return true;
}
- public void SaveState()
+ public void SaveState(Node node, string _filePast)
{
lock (stateLock) // Ensure thread safety
{
try
{
- string filePath = GetAppDataPath("DHT");
+ // SaveContactDHT
+ string filePath = GetAppDataPath(node, _filePast);
// Ensure the directory exists
string directoryPath = Path.GetDirectoryName(filePath);
@@ -256,13 +252,13 @@ namespace SPHERE.Blockchain
}
// Load DHT state from a file
- public void LoadState()
+ public void LoadState(Node node, string _filePath)
{
lock (stateLock) // Ensure thread safety
{
try
{
- string filePath = GetAppDataPath("DHT");
+ string filePath = GetAppDataPath(node, _filePath);
if (!File.Exists(filePath))
{
diff --git a/SPHERE/Blockchain/Chain/DHT/DHTManagement.cs b/SPHERE/Blockchain/Chain/DHT/DHTManagement.cs
index 3595c98..4b597f1 100644
--- a/SPHERE/Blockchain/Chain/DHT/DHTManagement.cs
+++ b/SPHERE/Blockchain/Chain/DHT/DHTManagement.cs
@@ -102,7 +102,7 @@ namespace SPHERE.Blockchain
- Packet responsePacket = Packet.PacketBuilder.BuildPacket(responseHeader, JsonSerializer.Serialize(block));
+ Packet responsePacket = Packet.PacketBuilder.BuildPacket(node, responseHeader, JsonSerializer.Serialize(block));
byte[] serializedResponse = Packet.PacketBuilder.SerializePacket(responsePacket);
// Encrypt with the requester's public key
@@ -192,7 +192,7 @@ namespace SPHERE.Blockchain
15
);
- Packet requestPacket = Packet.PacketBuilder.BuildPacket(header, blockType.ToString());
+ Packet requestPacket = Packet.PacketBuilder.BuildPacket(node, header, blockType.ToString());
byte[] serializedPacket = Packet.PacketBuilder.SerializePacket(requestPacket);
// Encrypt the packet with the peer's public key
diff --git a/SPHERE/Blockchain/Chain/DHT/RoutingTable.cs b/SPHERE/Blockchain/Chain/DHT/RoutingTable.cs
index 10a361d..e4b30dd 100644
--- a/SPHERE/Blockchain/Chain/DHT/RoutingTable.cs
+++ b/SPHERE/Blockchain/Chain/DHT/RoutingTable.cs
@@ -233,13 +233,13 @@ public class RoutingTable
}
}
- public void SaveRoutingTable()
+ public void SaveRoutingTable(Node node, string _filePath)
{
lock (_lock)
{
try
{
- string filePath = DHT.GetAppDataPath("RT");
+ string filePath = DHT.GetAppDataPath(node, _filePath);
string directoryPath = Path.GetDirectoryName(filePath);
if (!Directory.Exists(directoryPath))
@@ -280,13 +280,13 @@ public class RoutingTable
}
}
- public void LoadRoutingTable()
+ public void LoadRoutingTable(Node node, string _filePath)
{
lock (_lock)
{
try
{
- string filePath = DHT.GetAppDataPath("RT");
+ string filePath = DHT.GetAppDataPath(node, _filePath);
if (!File.Exists(filePath))
{
diff --git a/SPHERE/Blockchain/Chain/Networking/Bootstrap.cs b/SPHERE/Blockchain/Chain/Networking/Bootstrap.cs
index e40443f..499f41f 100644
--- a/SPHERE/Blockchain/Chain/Networking/Bootstrap.cs
+++ b/SPHERE/Blockchain/Chain/Networking/Bootstrap.cs
@@ -56,12 +56,12 @@ namespace SPHERE.Networking
node.Peer.Node_Type.ToString(),
node.Peer.PublicSignatureKey,
node.Peer.PublicEncryptKey,
- node.Client.clientListenerPort,
- node.Client.clientIP.ToString(),
+ node.Peer.NodePort,
+ node.Peer.NodeIP,
25
);
- Packet packet = Packet.PacketBuilder.BuildPacket(header, Packet.PacketBuilder.PacketType.BootstrapRequest.ToString());
+ Packet packet = Packet.PacketBuilder.BuildPacket(node, header, Packet.PacketBuilder.PacketType.BootstrapRequest.ToString());
SystemLogger.Log($"Debug-SendBootstrapRequest: Packet built with NodeId: {node.Peer.NodeId}, IP: {node.Client.clientIP}, Port: {node.Client.clientListenerPort}");
// Serialize the packet into a byte array
@@ -374,7 +374,7 @@ namespace SPHERE.Networking
var SerializedPayload = JsonSerializer.Serialize(responsePayload);
- Packet responsePacket = Packet.PacketBuilder.BuildPacket(header, SerializedPayload);
+ Packet responsePacket = Packet.PacketBuilder.BuildPacket(node, header, SerializedPayload);
byte[] serializedPacket = Packet.PacketBuilder.SerializePacket(responsePacket);
diff --git a/SPHERE/Blockchain/Chain/Networking/Client.cs b/SPHERE/Blockchain/Chain/Networking/Client.cs
index 4779daf..f47e9d8 100644
--- a/SPHERE/Blockchain/Chain/Networking/Client.cs
+++ b/SPHERE/Blockchain/Chain/Networking/Client.cs
@@ -15,6 +15,8 @@ using System;
using System.Security.Cryptography;
using System.Text.Json;
using static SPHERE.Networking.Packet;
+using System.Reflection.PortableExecutable;
+using System.IO;
namespace SPHERE.Networking
@@ -67,6 +69,7 @@ namespace SPHERE.Networking
{ PacketBuilder.PacketType.Ping, (node, packet) => node.NetworkManager.PongPeerAsync(node, packet) },
{ PacketBuilder.PacketType.Pong, (node, packet) => node.NetworkManager.ProcessPongAsync(node, packet) },
{ PacketBuilder.PacketType.GetRequest, (node, packet) => node.NetworkManager.RespondToGetRequest(node, packet) },
+ { PacketBuilder.PacketType.GetResponse, (node, packet) => node.NetworkManager.ProcessGetResponse(node, packet) },
{ PacketBuilder.PacketType.BrodcastConnection, (node, packet) => node.NetworkManager.PeerListResponse(node, packet) },
{ PacketBuilder.PacketType.PeerUpdate, (node, packet) => node.Peer.ProcessPeerListResponse(node, packet) },
{ PacketBuilder.PacketType.SyncDHTRequest, (node, packet) => DHTManagement.ProcessSyncDHTRequest(node, packet) },
@@ -355,37 +358,38 @@ namespace SPHERE.Networking
}
- public async Task StartClientListenerAsync(Node node, Client client)
+ public async Task StartClientListenerAsync(Node node)
{
try
{
- // Ensure we have a valid listener port
- if (client.clientListenerPort == 0)
- {
- client.clientListenerPort = FindAvailablePort();
- }
- client.Listener = new TcpListener(client.clientIP, client.clientListenerPort);
- client.Listener.Start();
- SystemLogger.Log($"Async server is listening on port {client.clientListenerPort}");
+ // Ensure we have a valid listener port
+ if (node.Client.clientListenerPort == 0)
+ {
+ SystemLogger.Log($"Error-StartClientListenerAsync: Port was 0.");
+ return;
+ }
+ node.Client.Listener = new TcpListener(node.Client.clientIP, node.Client.clientListenerPort);
+ node.Client.Listener.Start();
+ //SystemLogger.Log($"Async server is listening on port {node.Client.clientListenerPort}");
while (true)
{
try
{
- client.client = await client.Listener.AcceptTcpClientAsync();
- SystemLogger.Log($"Connection established with {client.client.Client.RemoteEndPoint}");
+ node.Client.client = await node.Client.Listener.AcceptTcpClientAsync();
+ //SystemLogger.Log($"Connection established with {node.Client.client.Client.RemoteEndPoint}");
- _ = HandleClientAsync(node, client.client);
+ _ = HandleClientAsync(node, node.Client.client);
}
catch (Exception ex)
{
- SystemLogger.Log($"Server error: {ex.Message}");
+ // SystemLogger.Log($"Server error: {ex.Message}");
}
}
}
catch (Exception ex)
{
- SystemLogger.Log($"Error starting listener: {ex.Message}");
+ //SystemLogger.Log($"Error starting listener: {ex.Message}");
return;
}
}
@@ -400,11 +404,11 @@ namespace SPHERE.Networking
if (PublicIP == null || PublicPort == 0)
{
- SystemLogger.Log("StartClientListenerWithSTUNAsync: Failed to retrieve public endpoint. Trying once more.");
+ //SystemLogger.Log("StartClientListenerWithSTUNAsync: Failed to retrieve public endpoint. Trying once more.");
var (PublicIP1, PublicPort1) = stun.GetPublicEndpoint();
if (PublicIP1 == null || PublicPort1 == 0)
{
- SystemLogger.Log("StartClientListenerWithSTUNAsync: Failed to retrieve public endpoint again. Exiting.");
+ //SystemLogger.Log("StartClientListenerWithSTUNAsync: Failed to retrieve public endpoint again. Exiting.");
return;
}
@@ -443,9 +447,13 @@ namespace SPHERE.Networking
// Synchronous method to start the client listener using STUN
public void StartClientListenerWithSTUNSync(Node node, Client client)
{
+ SystemLogger.Log($"Debug-StartClientListenerWithSTUNSync: Starting Stun search");
try
{
- // Step 1: Retrieve public IP and port using STUN
+ // Retrieve public IP and port using STUN
+
+
+
var stun = new STUN();
var (PublicIP, PublicPort) = stun.GetPublicEndpoint();
@@ -561,6 +569,7 @@ namespace SPHERE.Networking
}
finally
{
+ await client.GetStream().FlushAsync();
client.Close();
}
}
@@ -605,9 +614,35 @@ namespace SPHERE.Networking
try
{
+ string normalizedContent = "empty";
+ string packetHash = "";
//Store a Hash of the Packet Content to check and prevent processing duplicate packets.
- string normalizedContent = JsonSerializer.Serialize(JsonSerializer.Deserialize