Aetherforge MVP 1
MVP 1
This is MVP 1 implementation of the Aetherforge

Aetherforge MVP 1 Project Review
Overview
Aetherforge is a Solana blockchain project that implements a decentralized consensus mechanism for distributed work validation and reward distribution. The project is designed for a system where:
Miners submit work (possibly computational tasks or AI model training)
Validators score the quality of the miners' work
The system distributes token rewards based on these scores
The project uses the Anchor framework, which is a popular development framework for Solana programs (smart contracts).
Project Structure
The project follows a standard Anchor project structure:
programs/aetherforge-mvp/src/lib.rs
: The main Solana program (smart contract)app/client.ts
: A TypeScript client for interacting with the programprograms/aetherforge-mvp/Cargo.toml
: Rust dependencies for the programprograms/aetherforge-mvp/Xargo.toml
: Configuration for cross-compilation
Detailed Functionality
Solana Program (lib.rs)
The program defines four main instructions:
1. initialize
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
let consensus = &mut ctx.accounts.consensus;
consensus.authority = *ctx.accounts.authority.key;
consensus.round = 0;
Ok(())
}
Creates a new consensus account
Sets the authority (admin) of the consensus
Initializes the round counter to 0
2. submit_work
pub fn submit_work(ctx: Context<SubmitWork>, work_hash: String) -> Result<()> {
let submission = &mut ctx.accounts.submission;
submission.miner = *ctx.accounts.miner.key;
submission.work_hash = work_hash;
submission.round = ctx.accounts.consensus.round;
Ok(())
}
Allows miners to submit their work as a hash
Records the miner's public key, the work hash, and the current round
3. submit_score
pub fn submit_score(ctx: Context<SubmitScore>, miner: Pubkey, score: u8) -> Result<()> {
let score_account = &mut ctx.accounts.score;
score_account.validator = *ctx.accounts.validator.key;
score_account.miner = miner;
score_account.score = score;
score_account.round = ctx.accounts.consensus.round;
Ok(())
}
Allows validators to score a miner's work
Records the validator's public key, the miner being scored, the score (0-255), and the current round
4. finalize_round
pub fn finalize_round(ctx: Context<FinalizeRound>) -> Result<()> {
let consensus = &mut ctx.accounts.consensus;
// For simplicity in this MVP, we'll just reward a fixed amount to the first token account
// In a real implementation, you'd need to properly process submissions and scores
let token_program = &ctx.accounts.token_program;
let authority = &ctx.accounts.authority;
let token_account = &ctx.accounts.token_account;
// Find a token account in the remaining accounts
for miner_account_info in ctx.remaining_accounts.iter() {
// Check if this is a token account (simplified check)
if miner_account_info.owner == &token_program.key() {
// Assume this is a token account and send a reward
let reward = 1000; // Fixed reward for MVP
let cpi_accounts = Transfer {
from: token_account.to_account_info(),
to: miner_account_info.to_account_info(),
authority: authority.to_account_info(),
};
let cpi_program = token_program.to_account_info();
let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
token::transfer(cpi_ctx, reward)?;
// Just reward one account for simplicity
break;
}
}
consensus.round += 1;
Ok(())
}
Finalizes the current round and distributes rewards
In the current simplified MVP implementation, it just sends a fixed reward (1000 tokens) to the first token account in the remaining accounts
Increments the round counter
Account Structures
The program defines three main account structures:
1. Consensus
#[account]
pub struct Consensus {
pub authority: Pubkey,
pub round: u64,
}
Stores the authority (admin) of the consensus
Tracks the current round number
2. Submission
#[account]
pub struct Submission {
pub miner: Pubkey,
pub work_hash: String,
pub round: u64,
}
Stores a work submission from a miner
Contains the miner's public key, the work hash, and the round number
3. Score
#[account]
pub struct Score {
pub validator: Pubkey,
pub miner: Pubkey,
pub score: u8,
pub round: u64,
}
Stores a score given by a validator to a miner
Contains the validator's public key, the miner's public key, the score, and the round number
Client (client.ts)
The TypeScript client demonstrates how to interact with the program:
It initializes the program with a new consensus account
It creates a submission from a miner
It submits a score from a validator
It finalizes the round and distributes rewards
The client uses hardcoded token addresses for demonstration purposes:
const tokenMint = new PublicKey("67mTYzJcDgo72NCnrFRs4fTYYoonL8PLrSUGjB7C1WS2");
const tokenAccount = new PublicKey("6VgvLuaLeM7GLEfss5jHTjSboiZYDEED5Zwuczrj5kcj");
const minerTokenAccount = new PublicKey("6VgvLuaLeM7GLEfss5jHTjSboiZYDEED5Zwuczrj5kcj");
Areas for Improvement
1. Reward Distribution Logic
The current implementation of finalize_round
is highly simplified and just sends a fixed reward to the first token account. A more robust implementation would:
Process all submissions and scores for the current round
Calculate rewards based on the average scores received by each miner
Distribute rewards proportionally to all miners based on their scores
Here's how it can be improved for MVP2:
pub fn finalize_round(ctx: Context<FinalizeRound>) -> Result<()> {
let consensus = &mut ctx.accounts.consensus;
// Clone remaining accounts to avoid lifetime issues
let remaining_accounts = ctx.remaining_accounts.to_vec();
// Create maps to store submissions and scores by miner
let mut miner_submissions: std::collections::HashMap<Pubkey, Vec<Pubkey>> = std::collections::HashMap::new();
let mut miner_scores: std::collections::HashMap<Pubkey, Vec<u8>> = std::collections::HashMap::new();
let mut miner_token_accounts: std::collections::HashMap<Pubkey, Pubkey> = std::collections::HashMap::new();
// Process all accounts
for account_info in remaining_accounts.iter() {
if let Ok(submission) = Account::<Submission>::try_from(account_info) {
if submission.round == consensus.round {
miner_submissions.entry(submission.miner)
.or_insert_with(Vec::new)
.push(account_info.key());
}
} else if let Ok(score) = Account::<Score>::try_from(account_info) {
if score.round == consensus.round {
miner_scores.entry(score.miner)
.or_insert_with(Vec::new)
.push(score.score);
}
} else {
// Assume it's a token account - in a real implementation, you'd need to verify this
// and map it to the correct miner
// This is just a placeholder
if let Some(owner_key) = account_info.owner.key() {
miner_token_accounts.insert(owner_key, account_info.key());
}
}
}
// Calculate rewards
for (miner, scores) in miner_scores.iter() {
if scores.is_empty() {
continue;
}
// Calculate average score
let total_score: u64 = scores.iter().map(|&s| s as u64).sum();
let avg_score = total_score / scores.len() as u64;
// Calculate reward (100 tokens per score point)
let reward = avg_score * 100;
// Find miner's token account
if let Some(token_account_key) = miner_token_accounts.get(miner) {
// Send reward
// ... (token transfer logic)
}
}
consensus.round += 1;
Ok(())
}
2. Security Improvements
The current implementation has several security concerns:
No validation that the authority is the one finalizing the round
No checks to prevent duplicate submissions or scores
No validation of the scores (e.g., ensuring they're within a valid range)
these security checks will be added:
#[derive(Accounts)]
pub struct FinalizeRound<'info> {
#[account(mut, has_one = authority)]
pub consensus: Account<'info, Consensus>,
#[account(mut)]
pub authority: Signer<'info>,
// ... other accounts
}
3. Scalability
The current approach of passing all submissions and scores as remaining accounts won't scale well. We consider:
Using a more efficient data structure to store submissions and scores
Implementing pagination for processing large numbers of submissions and scores
Using Solana's PDAs (Program Derived Addresses) to organize data more efficiently
4. Token Management
The current implementation assumes token accounts are already created. We can improve this by:
Adding instructions to create token accounts for miners
Implementing proper token account validation
Adding support for different token types or NFTs as rewards
5. Validator Reputation
We will add reputation system for validators:
#[account]
pub struct ValidatorReputation {
pub validator: Pubkey,
pub reputation: u64,
pub total_scores: u64,
}
6. Error Handling
We will improve error handling with custom error types:
#[error_code]
pub enum AetherforgeError {
#[msg("Invalid score value")]
InvalidScore,
#[msg("Unauthorized access")]
Unauthorized,
#[msg("Duplicate submission")]
DuplicateSubmission,
// ... other errors
}
7. Testing
We will add comprehensive tests for all functionality:
Unit tests for each instruction
Integration tests for the complete workflow
Stress tests for handling large numbers of submissions and scores
Next Steps for Development (MVP2)
Implement the improved reward distribution logic described above
Add proper validation and security checks for all instructions
Create a more user-friendly client interface with better error handling and documentation
Implement a proper token account creation flow for miners
Add a validator reputation system to incentivize honest validation
Develop a front-end application for easier interaction with the program
Add comprehensive testing to ensure reliability
Document the API and usage patterns for developers
Conclusion
Aetherforge provides a solid foundation for a decentralized work validation and reward system on Solana. The current implementation which is currently at the MVP 1 stage, is simplified but demonstrates the core functionality. With the improvements suggested above, it could be developed into a robust and scalable system for distributed work validation and reward distribution.
The project has potential applications in distributed computing, AI model training, content moderation, or any scenario where work needs to be validated by multiple parties before rewards are distributed.
Last updated