use std::{error::Error, str::FromStr};
use alloy_primitives::{Address, U256};
use onemoney_protocol::{
Signable, TokenMintPayload,
crypto::{private_key_to_address, sign_transaction_payload},
};
#[test]
fn test_address_derivation_integration() -> Result<(), Box<dyn Error>> {
let private_key = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
let address1 = private_key_to_address(private_key)?;
assert_eq!(address1.len(), 20);
let address2 = private_key_to_address(private_key)?;
assert_eq!(address1, address2);
println!("Derived address: {}", address1);
Ok(())
}
#[test]
fn test_multiple_private_keys_produce_unique_addresses() -> Result<(), Box<dyn Error>> {
let private_keys = [
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
"1111111111111111111111111111111111111111111111111111111111111111",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
];
let mut addresses = Vec::new();
for private_key in &private_keys {
let address = private_key_to_address(private_key)?;
addresses.push(address);
}
for i in 0..addresses.len() {
for j in (i + 1)..addresses.len() {
assert_ne!(
addresses[i], addresses[j],
"Private keys {} and {} produced the same address: {}",
private_keys[i], private_keys[j], addresses[i]
);
}
}
println!(
"Generated {} unique addresses from {} private keys",
addresses.len(),
private_keys.len()
);
Ok(())
}
#[test]
fn test_address_derivation_error_cases() {
let invalid_keys = [
"", "123", "xyz", "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef123", "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0", "gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg", ];
for invalid_key in &invalid_keys {
let result = private_key_to_address(invalid_key);
assert!(
result.is_err(),
"Invalid private key '{}' should produce an error, but got: {:?}",
invalid_key,
result
);
}
}
#[test]
fn test_token_mint_payload_signing_integration() -> Result<(), Box<dyn Error>> {
let token_address = Address::from_str("0x1234567890abcdef1234567890abcdef12345678")?;
let to_address = Address::from_str("0xabcdefabcdefabcdefabcdefabcdefabcdefabcd")?;
let amount = U256::from(1000000000000000000u64);
let payload = TokenMintPayload {
chain_id: 1,
nonce: 1,
token: token_address,
recipient: to_address,
value: amount,
};
let hash = payload.signature_hash();
assert_eq!(hash.len(), 32);
let hash2 = payload.signature_hash();
assert_eq!(hash, hash2);
let payload2 = TokenMintPayload {
chain_id: 1,
nonce: 2,
token: token_address,
recipient: to_address,
value: U256::from(2000000000000000000u64), };
let hash3 = payload2.signature_hash();
assert_ne!(hash, hash3);
println!("Token mint payload hash: {:?}", hash);
Ok(())
}
#[test]
fn test_end_to_end_transaction_signing() -> Result<(), Box<dyn Error>> {
let private_key = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
let token_address = Address::from_str("0x1234567890abcdef1234567890abcdef12345678")?;
let to_address = Address::from_str("0xabcdefabcdefabcdefabcdefabcdefabcdefabcd")?;
let amount = U256::from(1000000000000000000u64);
let payload = TokenMintPayload {
chain_id: 1,
nonce: 1,
token: token_address,
recipient: to_address,
value: amount,
};
let signature = sign_transaction_payload(&payload, private_key)?;
assert_ne!(signature.r, U256::ZERO);
assert_ne!(signature.s, U256::ZERO);
assert!(signature.v == 27 || signature.v == 28 || signature.v == 0 || signature.v == 1);
let signature2 = sign_transaction_payload(&payload, private_key)?;
assert_eq!(signature.r, signature2.r);
assert_eq!(signature.s, signature2.s);
assert_eq!(signature.v, signature2.v);
let payload2 = TokenMintPayload {
chain_id: 1,
nonce: 2,
token: token_address,
recipient: to_address,
value: U256::from(2000000000000000000u64), };
let signature3 = sign_transaction_payload(&payload2, private_key)?;
assert!(signature.r != signature3.r || signature.s != signature3.s);
println!(
"Transaction signature: r={}, s={}, v={}",
signature.r, signature.s, signature.v
);
Ok(())
}
#[test]
fn test_signature_determinism_across_restarts() -> Result<(), Box<dyn Error>> {
let private_key = "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210";
let token_address = Address::from_str("0x9999999999999999999999999999999999999999")?;
let to_address = Address::from_str("0x8888888888888888888888888888888888888888")?;
let amount = U256::from(5000000000000000000u64);
let payload = TokenMintPayload {
chain_id: 1,
nonce: 1,
token: token_address,
recipient: to_address,
value: amount,
};
let signatures: Vec<_> = (0..5)
.map(|_| sign_transaction_payload(&payload, private_key))
.collect::<Result<Vec<_>, _>>()?;
for i in 1..signatures.len() {
assert_eq!(signatures[0].r, signatures[i].r);
assert_eq!(signatures[0].s, signatures[i].s);
assert_eq!(signatures[0].v, signatures[i].v);
}
Ok(())
}
#[test]
fn test_complete_key_to_signature_workflow() -> Result<(), Box<dyn Error>> {
let private_key = "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890";
let derived_address = private_key_to_address(private_key)?;
let token_address = Address::from_str("0x1111111111111111111111111111111111111111")?;
let amount = U256::from(1500000000000000000u64);
let payload = TokenMintPayload {
chain_id: 1,
nonce: 3,
token: token_address,
recipient: derived_address, value: amount,
};
let signature = sign_transaction_payload(&payload, private_key)?;
assert_ne!(signature.r, U256::ZERO);
assert_ne!(signature.s, U256::ZERO);
let payload_hash = payload.signature_hash();
assert_eq!(payload_hash.len(), 32);
println!(
"Complete workflow: key={} -> address={} -> signature=(r={}, s={}, v={})",
&private_key[..8], derived_address,
signature.r,
signature.s,
signature.v
);
Ok(())
}
#[test]
fn test_multiple_transaction_types_signing() -> Result<(), Box<dyn Error>> {
let private_key = "5555555555555555555555555555555555555555555555555555555555555555";
let token1 = Address::from_str("0x1111111111111111111111111111111111111111")?;
let token2 = Address::from_str("0x2222222222222222222222222222222222222222")?;
let recipient1 = Address::from_str("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")?;
let recipient2 = Address::from_str("0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")?;
let payloads = [
TokenMintPayload {
chain_id: 1,
nonce: 1,
token: token1,
recipient: recipient1,
value: U256::from(1000u64),
},
TokenMintPayload {
chain_id: 1,
nonce: 1,
token: token1,
recipient: recipient2,
value: U256::from(2000u64),
},
TokenMintPayload {
chain_id: 1,
nonce: 1,
token: token2,
recipient: recipient1,
value: U256::from(3000u64),
},
TokenMintPayload {
chain_id: 1,
nonce: 1,
token: token2,
recipient: recipient2,
value: U256::from(4000u64),
},
];
let mut signatures = Vec::new();
let mut hashes = Vec::new();
for payload in &payloads {
let signature = sign_transaction_payload(payload, private_key)?;
let hash = payload.signature_hash();
signatures.push(signature);
hashes.push(hash);
}
for i in 0..signatures.len() {
for j in (i + 1)..signatures.len() {
assert!(
signatures[i].r != signatures[j].r || signatures[i].s != signatures[j].s,
"Signatures {} and {} should be different but are the same",
i,
j
);
}
}
for i in 0..hashes.len() {
for j in (i + 1)..hashes.len() {
assert_ne!(
hashes[i], hashes[j],
"Hashes {} and {} should be different but are the same",
i, j
);
}
}
println!("Successfully signed {} different payloads", payloads.len());
Ok(())
}
#[test]
fn test_signing_with_invalid_private_keys() {
let invalid_keys = [
"", "123", "xyz", "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef123", ];
let token_address = Address::from_str("0x1234567890abcdef1234567890abcdef12345678").unwrap();
let to_address = Address::from_str("0xabcdefabcdefabcdefabcdefabcdefabcdefabcd").unwrap();
let amount = U256::from(1000u64);
let payload = TokenMintPayload {
chain_id: 1,
nonce: 1,
token: token_address,
recipient: to_address,
value: amount,
};
for invalid_key in &invalid_keys {
let result = sign_transaction_payload(&payload, invalid_key);
assert!(
result.is_err(),
"Invalid private key '{}' should produce an error, but signing succeeded",
invalid_key
);
}
}
#[test]
fn test_extreme_value_handling() -> Result<(), Box<dyn Error>> {
let private_key = "7777777777777777777777777777777777777777777777777777777777777777";
let zero_address = Address::ZERO;
let max_address = Address::from([0xFF; 20]);
let payloads = [
TokenMintPayload {
chain_id: 1,
nonce: 1,
token: zero_address,
recipient: zero_address,
value: U256::ZERO,
},
TokenMintPayload {
chain_id: 1,
nonce: 1,
token: max_address,
recipient: max_address,
value: U256::MAX,
},
TokenMintPayload {
chain_id: 1,
nonce: 1,
token: zero_address,
recipient: max_address,
value: U256::from(1u64),
},
];
for (i, payload) in payloads.iter().enumerate() {
let signature = sign_transaction_payload(payload, private_key)?;
assert_ne!(signature.r, U256::ZERO, "Signature {} has zero r component", i);
assert_ne!(signature.s, U256::ZERO, "Signature {} has zero s component", i);
let hash = payload.signature_hash();
assert_eq!(hash.len(), 32, "Payload {} hash should be 32 bytes", i);
}
Ok(())
}
#[test]
fn test_concurrent_signing_consistency() -> Result<(), Box<dyn Error>> {
use std::{
sync::{Arc, Mutex},
thread,
};
let private_key = "8888888888888888888888888888888888888888888888888888888888888888";
let token_address = Address::from_str("0x3333333333333333333333333333333333333333")?;
let to_address = Address::from_str("0x4444444444444444444444444444444444444444")?;
let amount = U256::from(7777777777777777777u64);
let payload = TokenMintPayload {
chain_id: 1,
nonce: 1,
token: token_address,
recipient: to_address,
value: amount,
};
let signatures = Arc::new(Mutex::new(Vec::new()));
let mut handles = Vec::new();
for _ in 0..5 {
let payload_clone = payload.clone();
let signatures_clone = Arc::clone(&signatures);
let private_key_str = private_key.to_string();
let handle = thread::spawn(move || {
let signature = sign_transaction_payload(&payload_clone, &private_key_str).unwrap();
signatures_clone.lock().unwrap().push(signature);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let signatures = signatures.lock().unwrap();
assert_eq!(signatures.len(), 5);
for i in 1..signatures.len() {
assert_eq!(signatures[0].r, signatures[i].r);
assert_eq!(signatures[0].s, signatures[i].s);
assert_eq!(signatures[0].v, signatures[i].v);
}
Ok(())
}
#[test]
fn test_signing_performance_baseline() -> Result<(), Box<dyn Error>> {
use std::time::Instant;
let private_key = "9999999999999999999999999999999999999999999999999999999999999999";
let token_address = Address::from_str("0x5555555555555555555555555555555555555555")?;
let to_address = Address::from_str("0x6666666666666666666666666666666666666666")?;
let amount = U256::from(12345678901234567890u64);
let _payload = TokenMintPayload {
chain_id: 1,
nonce: 1,
token: token_address,
recipient: to_address,
value: amount,
};
let iterations = 100;
let start = Instant::now();
for i in 0..iterations {
let test_payload = TokenMintPayload {
chain_id: 1,
nonce: 1,
token: token_address,
recipient: to_address,
value: amount + U256::from(i), };
let _signature = sign_transaction_payload(&test_payload, private_key)?;
}
let duration = start.elapsed();
let avg_time_per_signature = duration / iterations;
println!(
"Signed {} transactions in {:?} (avg: {:?} per signature)",
iterations, duration, avg_time_per_signature
);
assert!(
avg_time_per_signature.as_millis() < 100,
"Average signing time {} ms is too slow",
avg_time_per_signature.as_millis()
);
Ok(())
}