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() }