2.2.8 Cycle 8 - Node Refactor
Design
Objectives
After beginning to plan out the slightly more advanced inter nodal communication (which should be in a later cycle not too much later than this one) I have come to the realisation that housing the cryptography and configuration module in the same place is probably not a good idea.
This is because after a few experiments I realised that without editing and recompiling it, the V-Web module that I'm using to host the api routes for the nodes currently prevents the loading of custom non-public variables into the web object to be used within those routes. What that means is that I can't setup the node's cryptography keys to be passed around the node whenever it receives a new api request without making them public and accessible by all parts of the program (which isn't great for security) and hence need to find a work around.
There are two main options here:
Reload the configuration object every time the program needs the cryptography keys to do anything.
Store the keys as a separate object and just reload them when they're needed.
Since separating the configuration and key objects helps reduce the amount of data that needs to be loaded and saved per time unit and is better for security, I will be going with the second option.
Usability Features
Keys are stored in a seperate file so that users can copy and paste just their key file to run additional nodes without having to manually enter their key data.
Ensure that all files for this project are stored within one "monochain" folder so as to keep them contained and not overrun the user's file system.
Key Variables
This is the keys object that holds the private and public keys as-well as some functions for using these keys (sign, verify, etc).
This is a string that represents the path of the file where the keys object is stored and loaded from.
Pseudocode
The keys object
This is the object that stores both the private, public key and the two key functions that need access to private key. The first being the sign function which signs data using the private key, and the validate function that ensures the public and private key within the object are matching and work together.
The keys handler
This is what allows the keys to be stored, loaded and generated into the keys object.
Development
The end result for this code involves two files, one of which handles the creation and functions of the keys object, and the other handles the loading, saving and creation of that object.
The benefit of this is that it allows the private key to remain as a private property so that the only functions that can access it are those that are a part of the keys object and used for signing data. Therefore although if part of the program was infected with some kind of malware it would allow that malware to sign data/transactions which is obviously not good, it wouldn't give them access to the keys directly hence making it harder for the bad actor responsible for the malware to copy the keys and gain complete control of the wallet.
Outcome
The keys object.
The keys handler.
Challenges
There were two key challenges to overcome during this development phase, the first one being a challenge I knew I'd have to overcome and the second being a very annoying bug. I've split these challenges into two separate sections for the sake of ease of reading.
Managing the storage of multiple files
Since the configuration settings are already saved in their own file and I am now going to be saving the keys in a separate file and I don't want to keep dumping files into the user's home directory, it's probably a good idea to start storing files within a folder to keep everything in one place.
Hence all files will now be stored within the /monochain/ folder so as to improve organisation. As a byproduct of this, I needed to write some form of script to check if the 'monochain' folder actually exists before anything was saved to it and if not, create the folder and then save a file to it.
This resulted in the adaptation of the current save_file function (which previously just wrapped the os.write_file function so as to reduce error handling) to the following:
This code also allows for the creation of sub-directories within the main folder as it simply loops through all sections of the file path. An example of this would be the creation of a file at path /monochain/subfolder1/subfolder2/file.txt which is supported with this code.
Overcoming a tricky SIGSEGV error
One of the major issues with Vlang that I have been dealing with over the last few development cycles is the SIGSEGV error. This is an error that occurs when a program tries to access a memory address that it has not been given permission to access by the operating system and one that occurs for a variety of different reasons.
The main problem with this error is that because of how the Vlang compiler deals with these errors is to just tell the developer that one has occurred without any hints of why or where it could've happened, meaning that as soon as a SIGSEGV error occurs the developer is completely on their own to solve it.
Although I have encountered a few of these errors before, they have all been after changing only a few lines of code and hence I can simply tweak those few lines of code until the error is fixed. However in this case the error occurred after I had written an entire file of code and included it to be compiled, so I had to spend a few hours checking each line of code individually until eventually I discovered that the error wasn't even directly in that file at all and was instead caused by a type declaration loop across two separate files.
This type declaration loop was caused due to a struct being defined based upon a type, then that type being defined based upon the struct.
This was annoying because in most other languages if this was to occur, the compiler would give you a nice error message due to it being fairly easy to catch prior to compilation, but in Vlang that was not the case.
Solving this error after discovering this was pretty simple, the challenge was just finding out the cause of the error in the first place.
Testing
To assist in the testing of this module I created a batch of automated tests
1
Generate a key pair.
The program not to exit, which will happen if the key pair cannot be generated.
As Expected
2
Generate a key pair and sign some data.
The program not to exit, which will happen if the key pair cannot be generated or sign the data.
As Expected
3
Generate a key pair, sign and then verify some data.
The program not to exit and to verify that the message matches the signature.
As Expected



Last updated