Greeting BlockDAG Community,

Hope you’ll had a blasting weekend
Building on our BlockDAG Mining Discussion:
Following up on our conversation about mining algorithms last week, let’s delve deeper into the RandomX protocol. It emerged as a promising candidate during our discussions, and we believe it warrants a closer technical examination to understand its suitability for our BlockDAG project.
Key Points:
 

  • We’ll be resuming our exploration of BlockDAG mining implementation.
  • As a reminder, Mondays are typically filled with planning meetings.
  • Building on our initial discussion about mining algorithms, let’s focus on RandomX.
  • We’ll explore the technical aspects of RandomX to assess its viability.

What is RandomX protocol and let’s understand the importance for us

RandomX has become a cornerstone for many blockchain projects prioritizing decentralization and fair mining practices. This Proof-of-Work (PoW) algorithm stands out for its focus on CPU utilization, making it resistant to specialized hardware like ASICs.

There are various reasons why we’re considering it as an optimized algorithm for us:

  • Performance Optimization: While RandomX is CPU-centric, knowledge of its workings can help optimize mining software for better performance on specific CPU architectures. CPU mining allows regular users to participate in the mining process, fostering a more inclusive network.
  • Security Audits: Familiarity with RandomX’s design principles can aid in security audits, allowing you to identify potential vulnerabilities in your own PoW implementation. The algorithm leverages established cryptographic tools like AES, Blake2, and Argon2 to ensure overall security.

As we claim for performance and security this protocol has been our very first choice for the algorithm.

RandomX in BlockDAG: A Technical Deep Dive

RandomX achieves its CPU-friendliness and ASIC resistance through a combination of techniques:

  1. Random Code Execution:
  • Pseudo Code:

function GenerateRandomInstruction():

// Generate random instruction from SRVVM instruction set

// (integer/floating-point arithmetic, conditional branches, memory access)

return instruction

function GenerateProgram():

program = [] for i in range(program_size):

          program.append(GenerateRandomInstruction())

return program

  • The algorithm dynamically generates instructions (code) at runtime using the SRVVM instruction set.
  • This thwarts ASICs, which are designed to excel at executing pre-defined sets of instructions efficiently.
     

Now let’s get into the implementation of RandomX protocol in BlockDAG:
As our blockchain is DAG (Directed Acyclic Graph) based, the mining process and consensus mechanism may differ from a traditional blockchain with a linear structure. In a BlockDAG blockchain, transactions will be represented as vertices in a graph, and blocks are not necessarily organized in a linear sequence.

RandomX algorithm

Here’s how the RandomX algorithm could be adapted for BlockDAG:
 

  1. Transaction Inclusion: Miners select transactions from the DAG to include in the block they are mining. These transactions will be chosen based on factors like transaction fees and priority.
  2. RandomX Initialization: the RandomX algorithm initializes a dataset based on the state of the DAG. However, since the DAG structure may change dynamically with new transactions, the dataset initialization process needs to account for this by incorporating the latest DAG state.
  3. Cache Initialization: Miners create a cache from the RandomX dataset, as before, but they may need to adjust the cache creation process to accommodate the DAG structure. Each mining thread creates its own cache, potentially incorporating different parts of the dataset based on the DAG state.
  4. Mining Process:
  • Miners execute the RandomX hashing function on the cache and the block data, as before.
  • The resulting hash is compared against the target difficulty, and if it meets the criteria, the miner successfully mines a block.
     
  • 5. Verification: Other nodes in the network verify the mined block by independently executing the RandomX hashing function and validating the transactions included in the block. Since the blockchain is DAG-based, nodes may need to traverse the DAG to verify the transactions’ validity.

Here’s a high-level pseudocode representation of the mining process:
 

function RandomX(cache, input):

   // Perform a series of mathematical operations on the cache and input

   // to generate a hash result

   result = ComputeHash(cache, input)

   return result

function MineBlock():

   // Initialize RandomX dataset based on the current state of the DAG

   dataset = InitializeDataset()

   // Create cache for each mining thread

   for thread in mining_threads:

       cache[thread] = CreateCache(dataset)

   // Mining loop

   while true:

       for thread in mining_threads:

           // Select transactions to include in the block from the DAG

           selected_transactions = SelectTransactionsFromDAG()

           // Execute RandomX hashing function on cache and block data

           hash_result = RandomX(cache[thread], selected_transactions)

           // Check if hash result meets difficulty criteria

           if hash_result < target_difficulty:

               // Block successfully mined

               return hash_result

This pseudocode outlines the basic steps involved in mining a block on BlockDAG using the RandomX algorithm.

Detailed pseudo code

Here is the detailed pseudo code our implementation:
 

function GenerateRandomInstruction():

   // Generates a random instruction from the SRVVM instruction set

   // (includes integer/floating-point arithmetic, conditional branches, memory access)

   return instruction

function GenerateProgram():

   program = []

   for i in range(program_size):

       program.append(GenerateRandomInstruction())

   return program

function InitializeRandomXDataset(dag):

   // Initialize RandomX dataset based on the current state of the DAG

   dataset = []    for vertex in dag.vertices:

       dataset.append(Hash(vertex.data))

 // Hashing each vertex’s data for dataset initialization

   return dataset

function CreateCache(dataset):

   // Create cache for RandomX computation

   cache = []

   for i in range(cache_size):

       cache.append(dataset[RandomIndexInRange(0, len(dataset))]) // Randomly select dataset entries for cache    return cache

function RandomX(cache, input):

   // Perform RandomX hashing function on cache and input

   result = ComputeHash(cache, input)

   return result

function MineBlock(dag, mining_threads):

   // Initialize RandomX dataset based on the current state of the DAG

   dataset = InitializeRandomXDataset(dag)

   // Create cache for each mining thread

   for thread in mining_threads:

       cache[thread] = CreateCache(dataset)

   // Mining loop

   while true:

       for thread in mining_threads:

           // Select transactions to include in the block from the DAG

           selected_transactions = SelectTransactionsFromDAG(dag)

           // Execute RandomX hashing function on cache and block data

           hash_result = RandomX(cache[thread], selected_transactions)

           // Check if hash result meets difficulty criteria

           if hash_result < target_difficulty:

               // Block successfully mined

               return hash_result

Stay tuned!

As we move forward towards the core of the technical implementation these algorithms will become more and more meaningful. Stay tuned for further updates!