use super::*;
impl<N: Network> FromBytes for Transaction<N> {
#[inline]
fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
let version = u8::read_le(&mut reader)?;
if version != 1 {
return Err(error("Invalid transaction version"));
}
let variant = u8::read_le(&mut reader)?;
let (id, transaction) = match variant {
0 => {
let id = N::TransactionID::read_le(&mut reader)?;
let owner = ProgramOwner::read_le(&mut reader)?;
let deployment = Deployment::read_le(&mut reader)?;
let fee = Fee::read_le(&mut reader)?;
let transaction = Self::from_deployment(owner, deployment, fee).map_err(|e| error(e.to_string()))?;
(id, transaction)
}
1 => {
let id = N::TransactionID::read_le(&mut reader)?;
let execution = Execution::read_le(&mut reader)?;
let fee_variant = u8::read_le(&mut reader)?;
let fee = match fee_variant {
0u8 => None,
1u8 => Some(Fee::read_le(&mut reader)?),
_ => return Err(error("Invalid fee variant")),
};
let transaction = Self::from_execution(execution, fee).map_err(|e| error(e.to_string()))?;
(id, transaction)
}
2 => {
let id = N::TransactionID::read_le(&mut reader)?;
let fee = Fee::read_le(&mut reader)?;
let transaction = Self::from_fee(fee).map_err(|e| error(e.to_string()))?;
(id, transaction)
}
3.. => return Err(error("Invalid transaction variant")),
};
match transaction.id() == id {
true => Ok(transaction),
false => Err(error("Transaction ID mismatch")),
}
}
}
impl<N: Network> ToBytes for Transaction<N> {
#[inline]
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
1u8.write_le(&mut writer)?;
match self {
Self::Deploy(id, _, owner, deployment, fee) => {
0u8.write_le(&mut writer)?;
id.write_le(&mut writer)?;
owner.write_le(&mut writer)?;
deployment.write_le(&mut writer)?;
fee.write_le(&mut writer)
}
Self::Execute(id, _, execution, fee) => {
1u8.write_le(&mut writer)?;
id.write_le(&mut writer)?;
execution.write_le(&mut writer)?;
match fee {
None => 0u8.write_le(&mut writer),
Some(fee) => {
1u8.write_le(&mut writer)?;
fee.write_le(&mut writer)
}
}
}
Self::Fee(id, fee) => {
2u8.write_le(&mut writer)?;
id.write_le(&mut writer)?;
fee.write_le(&mut writer)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bytes() -> Result<()> {
let rng = &mut TestRng::default();
for expected in [
crate::transaction::test_helpers::sample_deployment_transaction(1, Uniform::rand(rng), false, true, rng),
crate::transaction::test_helpers::sample_deployment_transaction(1, Uniform::rand(rng), false, false, rng),
crate::transaction::test_helpers::sample_deployment_transaction(2, Uniform::rand(rng), false, true, rng),
crate::transaction::test_helpers::sample_deployment_transaction(2, Uniform::rand(rng), false, false, rng),
crate::transaction::test_helpers::sample_deployment_transaction(2, Uniform::rand(rng), true, true, rng),
crate::transaction::test_helpers::sample_deployment_transaction(2, Uniform::rand(rng), true, false, rng),
crate::transaction::test_helpers::sample_execution_transaction_with_fee(true, rng, 0),
crate::transaction::test_helpers::sample_execution_transaction_with_fee(false, rng, 0),
]
.into_iter()
{
let expected_bytes = expected.to_bytes_le()?;
assert_eq!(expected, Transaction::read_le(&expected_bytes[..])?);
}
Ok(())
}
}