iota_validation/
validators.rs

1use iota_conversion;
2use iota_conversion::Trinary;
3use iota_crypto::{self, Kerl, Sponge};
4use iota_model::{Signature, Transaction};
5
6use crate::Result;
7
8use super::input_validator;
9use std::convert::TryInto;
10
11/// Validates that a slice of transactions is a valid bundle
12pub fn is_bundle(bundle: &[Transaction]) -> Result<bool> {
13    if !input_validator::is_slice_of_transactions(bundle) {
14        return Ok(false);
15    }
16    let mut total_sum = 0;
17    let bundle_hash = &bundle[0].bundle;
18
19    let mut hash_from_txs = [0; 243];
20    let mut kerl = Kerl::default();
21    let mut signatures_to_validate: Vec<Signature> = Vec::new();
22
23    for (index, tx) in bundle.iter().enumerate() {
24        let tx_value = tx.value;
25        total_sum += tx_value;
26        if index != tx.current_index {
27            return Ok(false);
28        }
29        let tx_trytes: String = tx.try_into()?;
30        let tx_trits = (&tx_trytes[2187..2187 + 162]).trits();
31        kerl.absorb(&tx_trits)?;
32        if tx_value < 0 {
33            let this_address = &tx.address;
34            let mut new_signature = Signature::default();
35            for i in index..bundle.len() - 1 {
36                let new_tx = &bundle[i + 1];
37                if new_tx.address == *this_address && new_tx.value == 0 {
38                    new_signature.add_fragment(new_tx.signature_fragments.clone());
39                }
40            }
41            signatures_to_validate.push(new_signature);
42        }
43    }
44    if total_sum != 0 {
45        return Ok(false);
46    }
47    kerl.squeeze(&mut hash_from_txs)?;
48    let bundle_from_txs = hash_from_txs.trytes()?;
49    if bundle_from_txs != *bundle_hash {
50        return Ok(false);
51    }
52    if bundle.last().unwrap().current_index != bundle.last().unwrap().last_index {
53        return Ok(false);
54    }
55    // TODO
56    // for sig in signatures_to_validate {
57    //     if !crypto::signing::validate_signatures(
58    //         sig.address(),
59    //         sig.signature_fragments(),
60    //         &bundle_hash,
61    //     )? {
62    //         return Ok(false);
63    //     }
64    // }
65    Ok(true)
66}