added skeleton for Solana integration
`
This commit is contained in:
		
							parent
							
								
									3b5b55e44e
								
							
						
					
					
						commit
						118fd077b4
					
				
							
								
								
									
										2533
									
								
								rewrite/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										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
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										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!(); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user