use alloy::{
hex::{self},
primitives::U256,
};
use crate::{
error::AuthError,
middleware::{
payment_channel::{
channel::ChannelState,
types::{PaymentChannel, PaymentChannelConfig, SignedRequest},
utils::create_channel_message,
},
utils::get_current_time,
},
};
pub async fn verify_and_update_channel(
state: &ChannelState,
config: &PaymentChannelConfig,
mut request: SignedRequest,
) -> Result<(PaymentChannel, bool), AuthError> {
println!("\n=== verify_and_update_channel ===");
println!("Payment amount: {}", request.payment_amount);
println!(
"Payment channel: {}",
serde_json::to_string(&request.payment_channel).map_err(|_| AuthError::InternalError)?
);
println!("Channel balance: {}", request.payment_channel.balance);
println!("Message length: {}", request.message.len());
println!("Original message: 0x{}", hex::encode(&request.message));
let now = get_current_time();
if now - request.timestamp > 300 {
return Err(AuthError::TimestampError);
}
let reconstructed_message = create_channel_message(
request.payment_channel.channel_id,
request.payment_channel.balance,
request.payment_channel.nonce,
&request.body_bytes,
);
if request.message != reconstructed_message {
println!("Failed: Message mismatch");
return Err(AuthError::InvalidMessage);
} else {
println!("Message match");
}
state
.verify_signature(
&request.payment_channel,
&request.signature,
&request.message,
)
.await?;
let mut channels = state.channels.write().await;
let now = get_current_time();
if request.payment_channel.expiration < U256::from(now) {
return Err(AuthError::Expired);
}
if let Some(existing_channel) = channels.get(&request.payment_channel.channel_id) {
println!("Existing channel found");
if request.payment_channel.nonce <= existing_channel.nonce {
println!(
"Failed: Invalid nonce - current: {}, received: {}",
existing_channel.nonce, request.payment_channel.nonce
);
return Err(AuthError::InvalidNonce);
} else {
println!("Nonce match");
}
if request.payment_channel.balance != existing_channel.balance {
println!(
"Failed: Invalid balance - current: {}, received: {}",
existing_channel.balance, request.payment_channel.balance
);
return Err(AuthError::InvalidChannel(format!(
"Balance mismatch in verify_and_update_channel - expected: {}, received: {}",
existing_channel.balance, request.payment_channel.balance
)));
} else {
println!("Balance match");
}
} else {
println!("New channel found");
state
.validate_channel(config, &request.payment_channel)
.await?;
if request.payment_channel.nonce != U256::from(0) {
return Err(AuthError::InvalidNonce);
}
}
println!("Updating channel state");
request.payment_channel.balance -= request.payment_amount;
channels.insert(
request.payment_channel.channel_id,
request.payment_channel.clone(),
);
drop(channels);
state
.update_latest_signature(request.payment_channel.channel_id, request.signature)
.await;
println!("API request authorized");
Ok((request.payment_channel.clone(), true))
}
pub async fn verify_channel(
config: PaymentChannelConfig,
mut request: SignedRequest,
current_channel: Option<PaymentChannel>,
) -> Result<(PaymentChannel, bool), AuthError> {
println!("\n=== verify_channel ===");
println!("Payment amount: {}", request.payment_amount);
println!(
"Payment channel: {}",
serde_json::to_string(&request.payment_channel).map_err(|_| AuthError::InternalError)?
);
println!("Channel balance: {}", request.payment_channel.balance);
println!("Message length: {}", request.message.len());
println!("Original message: 0x{}", hex::encode(&request.message));
let reconstructed_message = create_channel_message(
request.payment_channel.channel_id,
request.payment_channel.balance,
request.payment_channel.nonce,
&request.body_bytes,
);
if request.message != reconstructed_message {
println!("Failed: Message mismatch");
return Err(AuthError::InvalidMessage);
} else {
println!("Message match");
}
let state = ChannelState::new();
if let Some(channel) = current_channel {
state
.channels
.write()
.await
.insert(channel.channel_id, channel);
}
state
.verify_signature(
&request.payment_channel,
&request.signature,
&request.message,
)
.await?;
let channels = state.channels.write().await;
let now = get_current_time();
if request.payment_channel.expiration < U256::from(now) {
return Err(AuthError::Expired);
}
if let Some(existing_channel) = channels.get(&request.payment_channel.channel_id) {
println!("Existing channel found");
if request.payment_channel.nonce <= existing_channel.nonce {
println!(
"Failed: Invalid nonce - current: {}, received: {}",
existing_channel.nonce, request.payment_channel.nonce
);
return Err(AuthError::InvalidNonce);
} else {
println!("Nonce match");
}
if request.payment_channel.balance != existing_channel.balance {
println!(
"Failed: Invalid balance - current: {}, received: {}",
existing_channel.balance, request.payment_channel.balance
);
return Err(AuthError::InvalidChannel(format!(
"Balance mismatch in verify_channel - expected: {}, received: {}",
existing_channel.balance, request.payment_channel.balance
)));
} else {
println!("Balance match");
}
} else {
println!("New channel found");
state
.validate_channel(&config, &request.payment_channel)
.await?;
if request.payment_channel.nonce != U256::from(0) {
return Err(AuthError::InvalidNonce);
}
}
println!("Updating channel state");
request.payment_channel.balance -= request.payment_amount;
println!("API request authorized");
Ok((request.payment_channel.clone(), true))
}