1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use derive_more::Display;
use serde::{Deserialize, Serialize};

use crate::smr::smr_types::{Lock, Step};
use crate::types::{AggregatedVote, UpdateFrom};
use crate::Codec;

#[derive(Serialize, Deserialize, Clone, Debug, Display, Eq, PartialEq)]
#[rustfmt::skip]
#[display(
    fmt = "wal info height {}, round {}, step {:?}",
    height, round, step,
)]
/// Structure of Wal Info
pub struct WalInfo<T: Codec> {
    /// height
    pub height: u64,
    /// round
    pub round:  u64,
    /// step
    pub step:   Step,
    /// lock
    pub lock:   Option<WalLock<T>>,
    /// from
    pub from:   UpdateFrom,
}

impl<T: Codec> WalInfo<T> {
    /// transfer WalInfo to SMRBase
    pub fn into_smr_base(self) -> SMRBase {
        SMRBase {
            height: self.height,
            round: self.round,
            step: self.step.clone(),
            polc: self.lock.map(|polc| polc.to_lock()),
        }
    }
}

#[derive(Serialize, Deserialize, Clone, Debug, Display, PartialEq, Eq)]
#[display(fmt = "wal lock round {}, qc {:?}", lock_round, lock_votes)]
pub struct WalLock<T: Codec> {
    pub lock_round: u64,
    pub lock_votes: AggregatedVote,
    pub content: T,
}

impl<T: Codec> WalLock<T> {
    pub fn to_lock(&self) -> Lock {
        Lock {
            round: self.lock_round,
            hash: self.lock_votes.block_hash.clone(),
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SMRBase {
    pub height: u64,
    pub round: u64,
    pub step: Step,
    pub polc: Option<Lock>,
}

#[cfg(test)]
mod test {
    use std::error::Error;

    use bytes::Bytes;
    use rand::random;

    use super::*;
    use crate::types::{AggregatedSignature, VoteType};

    #[derive(Clone, Debug, PartialEq, Eq)]
    struct Pill {
        inner: Vec<u8>,
    }

    impl Codec for Pill {
        fn encode(&self) -> Result<Bytes, Box<dyn Error + Send>> {
            Ok(Bytes::from(self.inner.clone()))
        }

        fn decode(data: Bytes) -> Result<Self, Box<dyn Error + Send>> {
            Ok(Pill {
                inner: data.as_ref().to_vec(),
            })
        }
    }

    impl Pill {
        fn new() -> Self {
            Pill {
                inner: (0..128).map(|_| random::<u8>()).collect::<Vec<_>>(),
            }
        }
    }

    fn mock_qc() -> AggregatedVote {
        let aggregated_signature = AggregatedSignature {
            signature: Bytes::default(),
            address_bitmap: Bytes::default(),
        };

        AggregatedVote {
            signature: aggregated_signature,
            vote_type: VoteType::Precommit,
            height: 0u64,
            round: 0u64,
            block_hash: Bytes::default(),
            leader: Bytes::default(),
        }
    }

    #[test]
    fn test_display() {
        let wal_lock = WalLock {
            lock_round: 0,
            lock_votes: mock_qc(),
            content: Pill::new(),
        };
        println!("{}", wal_lock);

        let wal_info = WalInfo {
            height: 0,
            round: 0,
            step: Step::Propose,
            lock: Some(wal_lock),
            from: UpdateFrom::PrecommitQC(mock_qc()),
        };

        assert_eq!(
            wal_info.to_string(),
            "wal info height 0, round 0, step Propose"
        );
    }
}