cfxcore/light_protocol/handler/sync/common/
ledger_proof.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use cfx_types::H256;
6use primitives::{BlockHeader, BlockHeaderBuilder};
7use std::ops::Index;
8
9use crate::light_protocol::Error;
10
11pub enum LedgerProof {
12    StateRoot(Vec<H256>),
13    ReceiptsRoot(Vec<H256>),
14    LogsBloomHash(Vec<H256>),
15}
16
17impl Index<usize> for LedgerProof {
18    type Output = H256;
19
20    fn index(&self, ii: usize) -> &Self::Output {
21        let hashes = match self {
22            LedgerProof::StateRoot(hs) => hs,
23            LedgerProof::ReceiptsRoot(hs) => hs,
24            LedgerProof::LogsBloomHash(hs) => hs,
25        };
26
27        &hashes[ii]
28    }
29}
30
31impl LedgerProof {
32    pub fn validate(&self, witness: &BlockHeader) -> Result<(), Error> {
33        // extract proof hashes and corresponding local root hash
34        let (hashes, expected) = match self {
35            LedgerProof::StateRoot(hashes) => {
36                (hashes, *witness.deferred_state_root())
37            }
38            LedgerProof::ReceiptsRoot(hashes) => {
39                (hashes, *witness.deferred_receipts_root())
40            }
41            LedgerProof::LogsBloomHash(hashes) => {
42                (hashes, *witness.deferred_logs_bloom_hash())
43            }
44        };
45
46        // validate the number of hashes provided against local witness blame
47        let hash = witness.hash();
48        let blame = witness.blame() as u64;
49
50        if hashes.len() as u64 != blame + 1 {
51            bail!(Error::InvalidLedgerProofSize {
52                hash,
53                expected: blame + 1,
54                received: hashes.len() as u64
55            });
56        }
57
58        // compute witness deferred root hash from the hashes provided
59        let received = match blame {
60            0 => hashes[0],
61            _ => {
62                let hashes = hashes.clone();
63                BlockHeaderBuilder::compute_blame_state_root_vec_root(hashes)
64            }
65        };
66
67        // validate against local witness deferred state root hash
68        if received != expected {
69            bail!(Error::InvalidWitnessRoot {
70                hash,
71                expected,
72                received,
73            });
74        }
75
76        Ok(())
77    }
78}