From 90e9501fee6d6298bd84e21dcc73881fc76c29cf Mon Sep 17 00:00:00 2001 From: ghe0 Date: Sun, 29 Sep 2024 00:57:33 +0300 Subject: [PATCH] FUCK YEAH! IT WORKS! FINALLY! Dear Noor, Dear Ram, Please take into consideration I am Co-CEO and I am allowed to use language like this in commits messages. You should normally follow my lead, but not in this case. My advice is to not use language like this in commit messages. Yours trully, The G --- rewrite/Cargo.lock | 247 +++++++++++++++++++++++++++++++++---- rewrite/Cargo.toml | 3 + rewrite/scripts/testnet.sh | 2 + rewrite/src/datastore.rs | 10 +- rewrite/src/grpc/server.rs | 4 +- rewrite/src/http_server.rs | 12 +- rewrite/src/main.rs | 4 +- rewrite/src/solana.rs | 101 ++++++++++++++- 8 files changed, 348 insertions(+), 35 deletions(-) diff --git a/rewrite/Cargo.lock b/rewrite/Cargo.lock index 81c7d1a..8030362 100644 --- a/rewrite/Cargo.lock +++ b/rewrite/Cargo.lock @@ -1739,7 +1739,10 @@ dependencies = [ "rand 0.8.5", "serde", "solana-client", + "solana-program", "solana-sdk", + "spl-associated-token-account 5.0.1", + "spl-token", "tokio", "tokio-stream", "tonic", @@ -3531,9 +3534,9 @@ dependencies = [ "solana-config-program", "solana-sdk", "spl-token", - "spl-token-2022", - "spl-token-group-interface", - "spl-token-metadata-interface", + "spl-token-2022 4.0.0", + "spl-token-group-interface 0.3.0", + "spl-token-metadata-interface 0.4.0", "thiserror", "zstd 0.11.2+zstd.1.5.2", ] @@ -4137,12 +4140,12 @@ dependencies = [ "serde_json", "solana-account-decoder", "solana-sdk", - "spl-associated-token-account", + "spl-associated-token-account 4.0.0", "spl-memo", "spl-token", - "spl-token-2022", - "spl-token-group-interface", - "spl-token-metadata-interface", + "spl-token-2022 4.0.0", + "spl-token-group-interface 0.3.0", + "spl-token-metadata-interface 0.4.0", "thiserror", ] @@ -4220,6 +4223,35 @@ dependencies = [ "thiserror", ] +[[package]] +name = "solana-zk-sdk" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e79f29e79240fd273db888ee2049c17c139f8ab485d3567bbe0bbe7ed42846f" +dependencies = [ + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek", + "itertools 0.12.1", + "lazy_static", + "merlin", + "num-derive", + "num-traits", + "rand 0.7.3", + "serde", + "serde_derive", + "serde_json", + "sha3 0.9.1", + "solana-program", + "solana-sdk", + "subtle", + "thiserror", + "zeroize", +] + [[package]] name = "solana-zk-token-sdk" version = "2.0.11" @@ -4294,10 +4326,35 @@ dependencies = [ "num-traits", "solana-program", "spl-token", - "spl-token-2022", + "spl-token-2022 4.0.0", "thiserror", ] +[[package]] +name = "spl-associated-token-account" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714b53f7312c2802c62f14bc8a07916c2c872761e3d6be97e99fd432be7799ca" +dependencies = [ + "borsh 1.5.1", + "num-derive", + "num-traits", + "solana-program", + "spl-associated-token-account-client", + "spl-token", + "spl-token-2022 5.0.2", + "thiserror", +] + +[[package]] +name = "spl-associated-token-account-client" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c5c1e2d53941ea7ebc4be3f86302a3c6c5178baa932bbc038468429e6900d36" +dependencies = [ + "solana-program", +] + [[package]] name = "spl-discriminator" version = "0.3.0" @@ -4356,6 +4413,20 @@ dependencies = [ "spl-program-error", ] +[[package]] +name = "spl-pod" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e38c99f09d58df06ca9a29fc0211786a4c34f4d099c1df27b1abaa206569a4" +dependencies = [ + "borsh 1.5.1", + "bytemuck", + "bytemuck_derive", + "solana-program", + "solana-zk-sdk", + "spl-program-error", +] + [[package]] name = "spl-program-error" version = "0.5.0" @@ -4390,9 +4461,23 @@ dependencies = [ "bytemuck", "solana-program", "spl-discriminator", - "spl-pod", + "spl-pod 0.3.1", "spl-program-error", - "spl-type-length-value", + "spl-type-length-value 0.5.0", +] + +[[package]] +name = "spl-tlv-account-resolution" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ffc5c76926c1cbc8d92ac1d9341328308d15bae04a67da5a226e36d5bc395a" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod 0.4.0", + "spl-program-error", + "spl-type-length-value 0.6.0", ] [[package]] @@ -4425,12 +4510,74 @@ dependencies = [ "solana-security-txt", "solana-zk-token-sdk", "spl-memo", - "spl-pod", + "spl-pod 0.3.1", "spl-token", - "spl-token-group-interface", - "spl-token-metadata-interface", - "spl-transfer-hook-interface", - "spl-type-length-value", + "spl-token-group-interface 0.3.0", + "spl-token-metadata-interface 0.4.0", + "spl-transfer-hook-interface 0.7.0", + "spl-type-length-value 0.5.0", + "thiserror", +] + +[[package]] +name = "spl-token-2022" +version = "5.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b788a8c34a917b68b4ed2cdec255d03cc09ccba21545dac39c08a97fce640f" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program", + "solana-security-txt", + "solana-zk-sdk", + "spl-memo", + "spl-pod 0.4.0", + "spl-token", + "spl-token-confidential-transfer-ciphertext-arithmetic", + "spl-token-confidential-transfer-proof-extraction", + "spl-token-confidential-transfer-proof-generation", + "spl-token-group-interface 0.4.2", + "spl-token-metadata-interface 0.5.1", + "spl-transfer-hook-interface 0.8.2", + "spl-type-length-value 0.6.0", + "thiserror", +] + +[[package]] +name = "spl-token-confidential-transfer-ciphertext-arithmetic" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48df72fb98b4069979aa4806d4a634ad6f08cb0358e732e6fbac231c5dc075bd" +dependencies = [ + "base64 0.22.1", + "bytemuck", + "solana-curve25519", + "solana-zk-sdk", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-extraction" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae2ce92a0b9673c44207b21d99526b96d557d5a25752f36c38fae37c49129c3b" +dependencies = [ + "bytemuck", + "solana-curve25519", + "solana-zk-sdk", + "thiserror", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-generation" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216517cc8cd26dfe768521542f221f91049be102d1eefd8054cde881d1b5d267" +dependencies = [ + "curve25519-dalek", + "solana-zk-sdk", "thiserror", ] @@ -4443,7 +4590,20 @@ dependencies = [ "bytemuck", "solana-program", "spl-discriminator", - "spl-pod", + "spl-pod 0.3.1", + "spl-program-error", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c54728921a6f180525c4f3a4cc3b231db8da940681c8009259faa65d84c6196" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod 0.4.0", "spl-program-error", ] @@ -4456,9 +4616,23 @@ dependencies = [ "borsh 1.5.1", "solana-program", "spl-discriminator", - "spl-pod", + "spl-pod 0.3.1", "spl-program-error", - "spl-type-length-value", + "spl-type-length-value 0.5.0", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c7a6d2a2a4f23c8f051ba2f7edb5689f1b534b4126bd9b4ae4177685e9a341" +dependencies = [ + "borsh 1.5.1", + "solana-program", + "spl-discriminator", + "spl-pod 0.4.0", + "spl-program-error", + "spl-type-length-value 0.6.0", ] [[package]] @@ -4471,10 +4645,26 @@ dependencies = [ "bytemuck", "solana-program", "spl-discriminator", - "spl-pod", + "spl-pod 0.3.1", "spl-program-error", - "spl-tlv-account-resolution", - "spl-type-length-value", + "spl-tlv-account-resolution 0.7.0", + "spl-type-length-value 0.5.0", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b82e5ad62ad342d8fbb907b2a7aede7a5a258ce16366c26a686acc1df431fc63" +dependencies = [ + "arrayref", + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod 0.4.0", + "spl-program-error", + "spl-tlv-account-resolution 0.8.1", + "spl-type-length-value 0.6.0", ] [[package]] @@ -4486,7 +4676,20 @@ dependencies = [ "bytemuck", "solana-program", "spl-discriminator", - "spl-pod", + "spl-pod 0.3.1", + "spl-program-error", +] + +[[package]] +name = "spl-type-length-value" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69c08deb8332a6c051f6e846b5e9c962695295dd97e0e151dccf3ef85dcf01b4" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod 0.4.0", "spl-program-error", ] diff --git a/rewrite/Cargo.toml b/rewrite/Cargo.toml index 40efbf8..db7e5c4 100644 --- a/rewrite/Cargo.toml +++ b/rewrite/Cargo.toml @@ -13,7 +13,10 @@ prost-types = "0.13.2" rand = "0.8.5" serde = { version = "1.0.210", features = ["derive"] } solana-client = "2.0.11" +solana-program = "2.0.11" solana-sdk = "2.0.10" +spl-associated-token-account = "5.0.1" +spl-token = "6.0.0" tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread", "fs"] } tokio-stream = { version = "0.1.16", features = ["sync"] } tonic = "0.12.1" diff --git a/rewrite/scripts/testnet.sh b/rewrite/scripts/testnet.sh index 9b97e42..7a07118 100755 --- a/rewrite/scripts/testnet.sh +++ b/rewrite/scripts/testnet.sh @@ -16,6 +16,8 @@ docker ps -a | grep 'hacker-challenge' | awk '{ print $NF }' | xargs docker rm - docker run -d --name "hacker-challenge_0" \ hacker-challenge:latest +read -p "Created the first container. Press Enter to continue..." Result> { + use std::str::FromStr; + let recipient = solana_sdk::pubkey::Pubkey::from_str(recipient)?; + let sig = self.sol_client.mint(&recipient)?; + self.increase_mints(); + Ok(sig) + } + pub fn increase_mints(&self) { if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) { localhost_info.mints += 1; diff --git a/rewrite/src/grpc/server.rs b/rewrite/src/grpc/server.rs index 07ae3f8..fb5b52d 100644 --- a/rewrite/src/grpc/server.rs +++ b/rewrite/src/grpc/server.rs @@ -90,9 +90,7 @@ impl Update for MyServer { Ok(Response::new(Box::pin(stream) as Self::GetUpdatesStream)) } - async fn get_keys(&self, request: Request) -> Result, Status> { - println!("Got a request from {:?}", request.remote_addr()); - + async fn get_keys(&self, _request: Request) -> Result, Status> { let reply = Keys { keypair: self.ds.get_keypair_base58(), token_address: self.ds.get_token_address(), diff --git a/rewrite/src/http_server.rs b/rewrite/src/http_server.rs index 1c80cbc..03d71f7 100644 --- a/rewrite/src/http_server.rs +++ b/rewrite/src/http_server.rs @@ -89,10 +89,16 @@ struct MintReq { } #[post("/mint")] -async fn mint(ds: web::Data>, _: web::Json) -> impl Responder { - println!("wat"); +async fn mint(ds: web::Data>, req: web::Json) -> impl Responder { ds.increase_mint_requests(); - HttpResponse::Ok().json({}) + let result = + actix_web::web::block(move || ds.mint(&req.into_inner().wallet).map_err(|e| e.to_string())) + .await + .unwrap(); // TODO: check if this can get a BlockingError + match result { + Ok(s) => HttpResponse::Ok().body(format!(r#"{{ "signature": "{s}"}}"#)), + Err(e) => HttpResponse::InternalServerError().body(format!(r#"{{ "error": "{e}"}}"#)), + } } pub async fn init(ds: Arc) { diff --git a/rewrite/src/main.rs b/rewrite/src/main.rs index 21fa927..a672de4 100644 --- a/rewrite/src/main.rs +++ b/rewrite/src/main.rs @@ -39,10 +39,10 @@ async fn get_sol_client() -> SolClient { match grpc::client::key_grabber(line.unwrap()).await { Ok(bundle) => { println!( - "Got keypair from the network. Joining the network using wallet {}.", + "Got keypair from the network. Joining the network using wallet {}", bundle.0.pubkey() ); - println!("The address of the Token is {}.", bundle.1.to_string()); + println!("The address of the Token is {}", bundle.1.to_string()); return SolClient::from(bundle.0, bundle.1); } Err(e) => { diff --git a/rewrite/src/solana.rs b/rewrite/src/solana.rs index a9c0f75..26b5ca9 100644 --- a/rewrite/src/solana.rs +++ b/rewrite/src/solana.rs @@ -1,8 +1,17 @@ #![allow(dead_code)] use solana_client::rpc_client::RpcClient; +use solana_program::program_pack::Pack; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::keypair::Keypair; use solana_sdk::signer::Signer; +use solana_sdk::system_instruction; +use solana_sdk::transaction::Transaction; +use spl_associated_token_account::{ + get_associated_token_address, instruction::create_associated_token_account, +}; +use spl_token::instruction::{initialize_mint, mint_to}; +use spl_token::state::Mint; +use std::error::Error; use tokio::time::{sleep, Duration}; const RPC_URL: &str = "https://api.devnet.solana.com"; @@ -33,6 +42,48 @@ impl Client { } } + pub fn mint(&self, recipient: &Pubkey) -> Result> { + let associated_token_address = self.create_token_account(recipient)?; + let mint_to_instruction = mint_to( + &spl_token::id(), + &self.token, + &associated_token_address, + &self.keypair.pubkey(), + &[], + 1_000_000_000, + )?; + + let transaction = Transaction::new_signed_with_payer( + &[mint_to_instruction], + Some(&self.keypair.pubkey()), + &[&self.keypair], + self.client.get_latest_blockhash()?, + ); + let signature = self.client.send_and_confirm_transaction(&transaction)?; + Ok(signature.to_string()) + } + + fn create_token_account(&self, recipient: &Pubkey) -> Result> { + let address = get_associated_token_address(&recipient, &self.token); + if self.client.get_account(&address).is_err() { + let create_token_account_instruction = create_associated_token_account( + &self.keypair.pubkey(), + recipient, + &self.token, + &spl_token::id(), + ); + let recent_blockhash = self.client.get_latest_blockhash()?; + let tx = Transaction::new_signed_with_payer( + &[create_token_account_instruction], + Some(&self.keypair.pubkey()), + &[&self.keypair], + recent_blockhash, + ); + self.client.send_and_confirm_transaction(&tx)?; + } + Ok(address) + } + pub fn wallet_address(&self) -> String { self.keypair.pubkey().to_string() } @@ -47,17 +98,59 @@ impl Client { } async fn wait_for_sol(client: &RpcClient, pubkey: &Pubkey) { + println!("Waiting to receive 0.01 SOL in address {pubkey}"); loop { sleep(Duration::from_secs(30)).await; - if let Ok(balance) = client.get_balance(pubkey) { - if balance > 1_000_000_000 { - return; + match client.get_balance(pubkey) { + Ok(balance) => { + println!("Got {balance} lamports."); + if balance > 10_000_000 { + return; + } } + Err(e) => println!("Could not get balance: {e:?}"), } } } async fn create_token(client: &RpcClient, keypair: &Keypair) -> Pubkey { wait_for_sol(client, &keypair.pubkey()).await; - todo!(); + + let mint_keypair = Keypair::new(); + let payer = Keypair::from_base58_string(&keypair.to_base58_string()); + let mint_rent = client + .get_minimum_balance_for_rent_exemption(Mint::LEN) + .unwrap(); + + let create_mint_account_ix = system_instruction::create_account( + &payer.pubkey(), + &mint_keypair.pubkey(), + mint_rent, + Mint::LEN as u64, + &spl_token::id(), + ); + + let init_mint_ix = initialize_mint( + &spl_token::id(), + &mint_keypair.pubkey(), + &payer.pubkey(), + None, + 9, + ) + .unwrap(); + + let recent_blockhash = client.get_latest_blockhash().unwrap(); + let tx = Transaction::new_signed_with_payer( + &[create_mint_account_ix, init_mint_ix], + Some(&payer.pubkey()), + &[&payer, &mint_keypair], + recent_blockhash, + ); + + let signature = client.send_and_confirm_transaction(&tx).unwrap(); + + println!("Mint created: {}", mint_keypair.pubkey()); + println!("Transaction signature: {}", signature); + + mint_keypair.pubkey() }