added skeleton for Solana integration

`
This commit is contained in:
ghe0 2024-09-28 20:09:05 +03:00
parent 3b5b55e44e
commit 118fd077b4
Signed by: ghe0
GPG Key ID: 451028EE56A0FBB4
9 changed files with 2591 additions and 78 deletions

2533
rewrite/Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -12,6 +12,7 @@ prost = "0.13.2"
prost-types = "0.13.2"
rand = "0.8.5"
serde = { version = "1.0.210", features = ["derive"] }
solana-client = "2.0.11"
solana-sdk = "2.0.10"
tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread", "fs"] }
tokio-stream = { version = "0.1.16", features = ["sync"] }

@ -14,13 +14,14 @@ message NodeUpdate {
bool public = 8;
}
message Keypair {
message Keys {
string keypair = 1;
string token_address = 2;
}
message Empty {}
service Update {
rpc GetKeypair (Empty) returns (Keypair);
rpc GetKeys (Empty) returns (Keys);
rpc GetUpdates (stream NodeUpdate) returns (stream NodeUpdate);
}

@ -1,9 +1,9 @@
#![allow(dead_code)]
use dashmap::DashMap;
use dashmap::DashSet;
use solana_sdk::signature::keypair::Keypair;
use std::time::Duration;
use std::time::SystemTime;
use crate::solana::Client as SolClient;
type IP = String;
pub const LOCALHOST: &str = "localhost";
@ -38,7 +38,7 @@ impl NodeInfo {
/// This means the first node of the network creates the key
/// Second node will grab the key from the first node
pub struct Store {
key: Keypair,
sol_client: SolClient,
nodes: DashMap<IP, NodeInfo>,
conns: DashSet<IP>,
// TODO: write persistence
@ -46,9 +46,9 @@ pub struct Store {
}
impl Store {
pub fn init(key: Keypair) -> Self {
pub fn init(sol_client: SolClient) -> Self {
let store = Self {
key,
sol_client,
nodes: DashMap::new(),
conns: DashSet::new(),
};
@ -67,8 +67,12 @@ impl Store {
store
}
pub fn get_token_address(&self) -> String {
self.sol_client.token_address()
}
pub fn get_keypair_base58(&self) -> String {
self.key.to_base58_string()
self.sol_client.get_keypair_base58()
}
pub fn add_conn(&self, ip: &str) {

@ -1,15 +1,17 @@
#![allow(dead_code)]
use super::challenge::NodeUpdate;
use crate::datastore::Store;
use crate::datastore::LOCALHOST;
use crate::grpc::challenge::update_client::UpdateClient;
use crate::grpc::challenge::Empty;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::keypair::Keypair;
use std::str::FromStr;
use std::sync::Arc;
use tokio::sync::broadcast::Sender;
use tokio::time::{sleep, Duration};
use tokio_stream::wrappers::BroadcastStream;
use tokio_stream::StreamExt;
use crate::datastore::LOCALHOST;
#[derive(Clone)]
pub struct ConnManager {
@ -55,7 +57,9 @@ impl ConnManager {
let response = client.get_updates(rx_stream).await?;
let mut resp_stream = response.into_inner();
let _ = self.tx.send((LOCALHOST.to_string(), self.ds.get_localhost()).into());
let _ = self
.tx
.send((LOCALHOST.to_string(), self.ds.get_localhost()).into());
while let Some(mut update) = resp_stream.message().await? {
// "localhost" IPs need to be changed to the real IP of the counterpart
@ -78,13 +82,16 @@ impl ConnManager {
}
}
pub async fn key_grabber(node_ip: String) -> Result<Keypair, Box<dyn std::error::Error>> {
pub async fn key_grabber(node_ip: String) -> Result<(Keypair, Pubkey), Box<dyn std::error::Error>> {
let mut client = UpdateClient::connect(format!("http://{node_ip}:31373")).await?;
let response = client.get_keypair(tonic::Request::new(Empty {})).await?;
let response = &response.into_inner().keypair;
let keypair = match std::panic::catch_unwind(|| Keypair::from_base58_string(&response)) {
let response = client.get_keys(tonic::Request::new(Empty {})).await?;
let response = &response.into_inner();
let keypair = response.keypair.clone();
let keypair = match std::panic::catch_unwind(|| Keypair::from_base58_string(&keypair)) {
Ok(k) => k,
Err(_) => return Err("Could not parse key".into()),
Err(_) => return Err("Could not parse keypair.".into()),
};
Ok(keypair)
let token_address = Pubkey::from_str(&response.token_address)
.map_err(|_| "Could not parse wallet address.".to_string())?;
Ok((keypair, token_address))
}

@ -1,7 +1,7 @@
#![allow(dead_code)]
use super::challenge::update_server::UpdateServer;
use super::challenge::{Empty, Keypair, NodeUpdate};
use super::challenge::{Empty, Keys, NodeUpdate};
use crate::datastore::Store;
use crate::grpc::challenge::update_server::Update;
use std::pin::Pin;
@ -90,11 +90,12 @@ impl Update for MyServer {
Ok(Response::new(Box::pin(stream) as Self::GetUpdatesStream))
}
async fn get_keypair(&self, request: Request<Empty>) -> Result<Response<Keypair>, Status> {
async fn get_keys(&self, request: Request<Empty>) -> Result<Response<Keys>, Status> {
println!("Got a request from {:?}", request.remote_addr());
let reply = Keypair {
let reply = Keys {
keypair: self.ds.get_keypair_base58(),
token_address: self.ds.get_token_address(),
};
Ok(Response::new(reply))
}

@ -50,7 +50,7 @@ pub struct NodesResp {
pub mint_requests: u64,
pub mints: u64,
pub ratls_attacks: u64,
pub ratls_connections: u64,
pub total_ratls_conns: u64,
pub public: bool,
}
@ -65,7 +65,7 @@ impl From<(String, datastore::NodeInfo)> for NodesResp {
joined_at,
last_keepalive,
mints: node_info.mints,
ratls_connections: node_info.ratls_conns,
total_ratls_conns: node_info.ratls_conns,
ratls_attacks: node_info.ratls_attacks,
public: node_info.public,
mint_requests: node_info.mint_requests,

@ -1,10 +1,10 @@
mod datastore;
mod grpc;
mod http_server;
mod solana;
use crate::datastore::LOCALHOST;
use crate::grpc::challenge::NodeUpdate;
use datastore::Store;
use solana_sdk::signature::keypair::Keypair;
use solana_sdk::signer::Signer;
use std::fs::File;
use std::io::{BufRead, BufReader};
@ -12,8 +12,8 @@ use std::sync::Arc;
use tokio::sync::broadcast;
use tokio::sync::broadcast::Sender;
use tokio::time::{sleep, Duration};
use tokio::task::JoinSet;
use crate::solana::Client as SolClient;
const INIT_NODES: &str = "detee_challenge_nodes";
@ -25,24 +25,25 @@ pub async fn localhost_cron(ds: Arc<Store>, tx: Sender<NodeUpdate>) {
}
}
async fn get_keypair() -> Keypair {
async fn get_sol_client() -> SolClient {
let input = match File::open(INIT_NODES) {
Ok(i) => i,
Err(_) => {
println!("Could not find remote nodes in the file {INIT_NODES}");
println!("Starting a new network with a new key...");
return Keypair::new();
return SolClient::new().await;
}
};
let buffered = BufReader::new(input);
for line in buffered.lines() {
match grpc::client::key_grabber(line.unwrap()).await {
Ok(keypair) => {
Ok(bundle) => {
println!(
"Got keypair from the network. Joining the network using wallet {}.",
keypair.pubkey()
bundle.0.pubkey()
);
return keypair;
println!("The address of the Token is {}.", bundle.1.to_string());
return SolClient::from(bundle.0, bundle.1);
}
Err(e) => {
println!("Could not get keypair: {e:?}");
@ -54,8 +55,8 @@ async fn get_keypair() -> Keypair {
#[tokio::main]
async fn main() {
let keypair = get_keypair().await;
let ds = Arc::new(Store::init(keypair));
let sol_client = get_sol_client().await;
let ds = Arc::new(Store::init(sol_client));
let (tx, mut _rx) = broadcast::channel(500);

63
rewrite/src/solana.rs Normal file

@ -0,0 +1,63 @@
#![allow(dead_code)]
use solana_client::rpc_client::RpcClient;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::keypair::Keypair;
use solana_sdk::signer::Signer;
use tokio::time::{sleep, Duration};
const RPC_URL: &str = "https://api.devnet.solana.com";
pub struct Client {
client: RpcClient,
keypair: Keypair,
token: Pubkey,
}
impl Client {
pub async fn new() -> Self {
let client = RpcClient::new(RPC_URL);
let keypair = Keypair::new();
let token = create_token(&client, &keypair).await;
Self {
client,
keypair,
token,
}
}
pub fn from(keypair: Keypair, token: Pubkey) -> Self {
Self {
client: RpcClient::new(RPC_URL),
keypair,
token,
}
}
pub fn wallet_address(&self) -> String {
self.keypair.pubkey().to_string()
}
pub fn token_address(&self) -> String {
self.token.to_string()
}
pub fn get_keypair_base58(&self) -> String {
self.keypair.to_base58_string()
}
}
async fn wait_for_sol(client: &RpcClient, pubkey: &Pubkey) {
loop {
sleep(Duration::from_secs(30)).await;
if let Ok(balance) = client.get_balance(pubkey) {
if balance > 1_000_000_000 {
return;
}
}
}
}
async fn create_token(client: &RpcClient, keypair: &Keypair) -> Pubkey {
wait_for_sol(client, &keypair.pubkey()).await;
todo!();
}