num_cpus = “1.0”
fn main() { let num = num_cpus::get(); println!("{}", num); }
随机应变 ABCD: Always Be Coding and … : хороший
num_cpus = “1.0”
fn main() { let num = num_cpus::get(); println!("{}", num); }
存在しうる全ての値を計算する。
桁数が増えれば増えるほど、処理時間がかかる。6桁で約1秒(1000ms)くらいかかる。
use sha2::{Digest, Sha256}; use std::time; fn main() { let password: String = "13225".to_string(); let length = password.chars().count() as u32; let crypto_hash: String = get_crypto_hash(password); crack_password(crypto_hash, length); } fn get_combinations(length: u32) -> Vec<String> { let mut combinations: Vec<String> = Vec::new(); let min_number = 0; let max_number = 10_i32.pow(length); for i in min_number..max_number { let str_num: String = i.to_string(); let zeros: String = "0".repeat((length - str_num.chars().count() as u32).try_into().unwrap()); combinations.push(format!("{}{}", zeros, str_num)); } return combinations; } fn get_crypto_hash(password: String) -> String { let sha = Sha256::digest(password); hex::encode(sha).to_string() } fn check_password(expected_crypto_hash: String, possible_password: String) -> bool { let actual_crypto_hash = get_crypto_hash(possible_password); return expected_crypto_hash == actual_crypto_hash } fn crack_password(crypto_hash: String, length: u32) { println!("Processing number combinations sequentially"); let start_time = time::Instant::now(); let combinations: Vec<String> = get_combinations(length); for combination in combinations { if check_password(crypto_hash.clone(), combination.clone()) { println!("PASSWORD CRACKED:{}", combination); break; } } println!("PROCESS TIME: {:?}", start_time.elapsed()); }
Compiling parallel v0.1.0 (/home/vagrant/dev/rust/parallel)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.16s
Running `target/debug/parallel`
Processing number combinations sequentially
PASSWORD CRACKED:13225
PROCESS TIME: 97.760443ms
println!("{}", power(3)); // fn power(x: u32) -> i32 { 10_i32.pow(x) }
Compiling sample v0.1.0 (/home/vagrant/dev/rust/sample)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.19s
Running `target/debug/sample`
1000
値を整形せずに、そのまま返しています。
async fn handle_service(extract::Json(payload): extract::Json<Service>) -> Json<Service>{ println!("{:?}", payload); Json(payload) }
curl -X POST -H “Content-Type: application/json” -d “{\”version\”:\”1\”,\”nonce\”:\”1482680747\”,\”connections\”:21}” 127.0.0.1:3000/service
{“version”:”1″,”nonce”:”1482680747″,”connections”:21}
なるほどー
IPを返却するサイトからIPアドレスを取得します。
httpbinにreqwest::getすると、String型で返却されるので、serde_jsonを使ってIpの構造体に変換しています。
use reqwest::Client; use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize, Debug)] struct Ip { origin: String, } #[tokio::main] async fn main() { let _ = get_ip().await; } // get ip async fn get_ip() -> Result<(), Box<dyn std::error::Error>> { let ip: Ip = serde_json::from_str(&reqwest::get("https://httpbin.org/ip") .await? .text() .await?)?; println!("ip = {:?}", ip.origin); Ok(()) }
Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.08s
Running `target/debug/sample`
ip = “***.***.*.***”
うーむ、なんだかな〜
UnsignedTransaction, SignedTransactionの構造体に、nft_dataと、nft_originを追加する。
nft_dataは、nftとして保存するデータ。
nft_originはnftを発行したトランザクションのhashデータ。
NFTを譲渡する場合は、nft_dataを空にして、nft_originに値を入れる。
#[derive(Serialize, Deserialize, Clone, Debug)] struct UnsignedTransaction { time: String, sender: String, receiver: String, amount: i32, nft_data: String, nft_origin: String, }
nft_holderというhashmapを作成して、そこにnftを発行したトランザクションのhashデータと、最後にNTFを譲渡されたreceiverの連想配列を入れていく。
誰が何を持っているかは、トランザクションのhashデータをデコードして、nft_dataの値を取り出す。
#[tokio::main] async fn main(){ let mut transaction_pool: Vec<SignedTransaction> = Vec::new(); let transaction1 = UnsignedTransaction {time:Utc::now().to_string(), sender:"047683c00f6z".to_string(), receiver:"DyH5SHvezz".to_string(), amount: 0, nft_data:"hello world".to_string(),nft_origin:"".to_string()}; let transaction2 = UnsignedTransaction {time:Utc::now().to_string(), sender:"DyH5SHvezz".to_string(), receiver:"655EFC80ss".to_string(), amount: 0, nft_data:"".to_string(),nft_origin:"eyJ0aW1lIjoiMjAyNS0wMS0xNyAwODoyOTo0Ni42NzgzNDU3OTQgVVRDIiwic2VuZGVyIjoiMDQ3NjgzYzAwZjZ6IiwicmVjZWl2ZXIiOiJEeUg1U0h2ZXp6IiwiYW1vdW50IjowLCJuZnRfZGF0YSI6ImhlbGxvIHdvcmxkIiwibmZ0X29yaWdpbiI6IiJ9".to_string()}; let transaction3 = UnsignedTransaction {time:Utc::now().to_string(), sender:"047683c00f6z".to_string(), receiver:"DyH5SHvezz".to_string(), amount: 0, nft_data:"Milk Cafe".to_string(),nft_origin:"".to_string()}; let transaction4 = UnsignedTransaction {time:Utc::now().to_string(), sender:"047683c00f6z".to_string(), receiver:"DyH5SHvezz".to_string(), amount: 1000, nft_data:"".to_string(),nft_origin:"".to_string()}; // println!("{}", BASE64_STANDARD.encode(serde_json::to_vec(&transaction1.clone()).unwrap())); // println!("{}", base64_decode(&str)); transaction_pool.push(sign_transaction(&transaction1)); transaction_pool.push(sign_transaction(&transaction2)); transaction_pool.push(sign_transaction(&transaction3)); transaction_pool.push(sign_transaction(&transaction4)); let nft_holder:HashMap<String, String> = nft_calc(transaction_pool); for (k, v) in nft_holder { let transaction_str = base64_decode(&k); let transaction:UnsignedTransaction = serde_json::from_str(&transaction_str).unwrap(); println!("保有者:{}, NFT:{}", v, transaction.nft_data); } } fn nft_calc(transaction_pool: Vec<SignedTransaction>) -> HashMap<String, String> { let mut nft_holder: HashMap<String, String> = HashMap::new(); for transaction in transaction_pool { if transaction.amount == 0 { let transaction_hash: String = BASE64_STANDARD.encode(serde_json::to_vec(&transaction.clone()).unwrap()); if transaction.nft_origin == "" && transaction.nft_data != "" && (nft_holder.get(&transaction_hash) == None) { nft_holder.insert(transaction_hash, transaction.receiver); } else if (nft_holder.get(&transaction_hash) == Some(&transaction.sender)) && transaction.nft_data == "" { nft_holder.insert(transaction.nft_origin, transaction.receiver); } } } return nft_holder }
Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.13s
Running `target/debug/sample`
保有者:DyH5SHvezz, NFT:hello world
保有者:DyH5SHvezz, NFT:Milk Cafe
これは中々凄いな…
map.get(&target) != None でチェックできる。
let mut holder: HashMap<String, String> = HashMap::new(); holder.insert("yamada".to_string(), "A".to_string()); holder.insert("sato".to_string(), "B".to_string()); holder.insert("tanaka".to_string(), "C".to_string()); for (name, item) in &holder { println!("{}:{}", name, item); } let target = "yamada".to_string(); if holder.get(&target) != None { println!("{}", holder["yamada"]); }
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.33s
Running `target/debug/my_web_app`
yamada:A
tanaka:C
sato:B
A
pythonのように target in map ではチェックできない。
なるほど…
hello worldで挙動を確認します。
let str:String = "hello world".to_string();
println!("{}", BASE64_STANDARD.encode(str.clone()));
let b:String = "aGVsbG8gd29ybGQ=".to_string();
println!("{}", base64_decode(&b));
pub fn base64_decode_bytes(b64str: &str) -> Vec
let t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
let mut table: [u8; 256] = [0; 256];
for (i, v) in t.as_bytes().iter().enumerate() {
table[*v as usize] = i as u8;
}
let b64 = String::from(b64str).replace("\r", "").replace("\n", "");
let b64bytes = b64.as_bytes();
let mut result: Vec
let cnt = b64bytes.len() / 4;
for i in 0..cnt {
let i0 = b64bytes[i*4+0];
let i1 = b64bytes[i*4+1];
let i2 = b64bytes[i*4+2];
let i3 = b64bytes[i*4+3];
let c0 = table[i0 as usize] as usize;
let c1 = table[i1 as usize] as usize;
let c2 = table[i2 as usize] as usize;
let c3 = table[i3 as usize] as usize;
let b24 = (c0 << 18) | (c1 << 12) | (c2 << 6) | (c3 << 0);
let b0 = ((b24 >> 16) & 0xFF) as u8;
let b1 = ((b24 >> 8) & 0xFF) as u8;
let b2 = ((b24 >> 0) & 0xFF) as u8;
result.push(b0);
if i2 as char != '=' { result.push(b1); }
if i3 as char != '=' { result.push(b2); }
}
result
}
pub fn base64_decode(b64str: &str) -> String {
String::from_utf8(base64_decode_bytes(b64str)).unwrap()
}
[/cpde]
aGVsbG8gd29ybGQ=
hello world
上手くいっているようです。
これをトランザクションでやります。
let transaction1 = UnsignedTransaction {time:Utc::now().to_string(), sender:"047683c00f6z".to_string(), receiver:"DyH5SHvezz".to_string(), amount: 0, nft_data:"hello world".to_string(),nft_origin:"".to_string()};
println!("{}", BASE64_STANDARD.encode(serde_json::to_vec(&transaction1.clone()).unwrap()));
let str:String = "eyJ0aW1lIjoiMjAyNS0wMS0xNyAwODoyNzo1MS4wNTA0MjYxMDMgVVRDIiwic2VuZGVyIjoiMDQ3NjgzYzAwZjZ6IiwicmVjZWl2ZXIiOiJEeUg1U0h2ZXp6IiwiYW1vdW50IjowLCJuZnRfZGF0YSI6ImhlbGxvIHdvcmxkIiwibmZ0X29yaWdpbiI6IiJ9".to_string();
println!("{}", base64_decode(&str));
[/cpde]
eyJ0aW1lIjoiMjAyNS0wMS0xNyAwODoyOTo0Ni42NzgzNDU3OTQgVVRDIiwic2VuZGVyIjoiMDQ3NjgzYzAwZjZ6IiwicmVjZWl2ZXIiOiJEeUg1U0h2ZXp6IiwiYW1vdW50IjowLCJuZnRfZGF0YSI6ImhlbGxvIHdvcmxkIiwibmZ0X29yaWdpbiI6IiJ9
{"time":"2025-01-17 08:27:51.050426103 UTC","sender":"047683c00f6z","receiver":"DyH5SHvezz","amount":0,"nft_data":"hello world","nft_origin":""}
SignedTransaction { time: "2025-01-17 08:29:46.678345794 UTC", sender: "047683c00f6z", receiver: "DyH5SHvezz", amount: 0, nft_data: "hello world", nft_origin: "", signature: "568082531D765278ACF8999B94BAA7C621C538B00857DAC165208DB8C73FE4D4CB8FDBC742A4A47BC1D0B421A543134D869B2EC1AC8CEA0DDE902D39B034EA84" }
よし、O~K
async fn handle_logout()-> impl IntoResponse{ let tera = tera::Tera::new("templates/*").unwrap(); let mut context = tera::Context::new(); context.insert("title", "Index page"); context.insert("data", "hoge"); let output = tera.render("index.html", &context); let cookie:String = format!("session_token=_"); let headers = AppendHeaders(vec![("Set-Cookie", cookie)]); (headers, axum::response::Html(output.unwrap())) }
特にコメントなし。
さー次行こう^^
cookieを判定するmiddlewareを作成し、privateなページのみミドルウェアをつけて、publicなページにはつけない。
該当のsession_tokenがない場合は、Redirectでpublicのページにリダイレクトさせる。
async fn main() { let public_router = Router::new() .route("/setcookie", get(handle_setcookie)) .route("/public", get(handle_public)); let private_router = Router::new() .route("/test", get(handle_index)) .route("/private", get(handle_private)) .layer(middleware::from_fn(my_middleware)); let app = Router::new() .nest("/", public_router) .nest("/", private_router); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); axum::serve(listener, app).await.unwrap(); } // if session_token == None { Redirect::permanent("/public").into_response() } else { let mut res = next.run(req).await; res }
おおおおおおお、昨日長時間悶絶してただけあって、ここは割と簡単に上手くいった。