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
//! Mock types and functions to generate mock data useful for tests

use crate::{
    circuit_input_builder::{
        get_state_accesses, Block, CircuitInputBuilder, CircuitsParams, DynamicCParams,
        FeatureConfig, FixedCParams,
    },
    state_db::{self, CodeDB, StateDB},
};
use eth_types::{geth_types::GethData, Word};

/// BlockData is a type that contains all the information from a block required
/// to build the circuit inputs.
#[derive(Debug)]
pub struct BlockData<C: CircuitsParams> {
    /// StateDB
    pub sdb: StateDB,
    /// CodeDB
    pub code_db: CodeDB,
    /// chain id
    pub chain_id: Word,
    /// history hashes contains most recent 256 block hashes in history, where
    /// the latest one is at history_hashes[history_hashes.len() - 1].
    pub history_hashes: Vec<Word>,
    /// Block from geth
    pub eth_block: eth_types::Block<eth_types::Transaction>,
    /// Execution Trace from geth
    pub geth_traces: Vec<eth_types::GethExecTrace>,
    /// Circuits setup parameters
    pub circuits_params: C,
}

impl<C: CircuitsParams> BlockData<C> {
    /// Generate a new CircuitInputBuilder initialized with the context of the
    /// BlockData.
    pub fn new_circuit_input_builder(&self) -> CircuitInputBuilder<C> {
        self.new_circuit_input_builder_with_feature(FeatureConfig::default())
    }
    /// Generate a new CircuitInputBuilder initialized with the context of the
    /// BlockData.
    pub fn new_circuit_input_builder_with_feature(
        &self,
        feature_config: FeatureConfig,
    ) -> CircuitInputBuilder<C> {
        CircuitInputBuilder::new(
            self.sdb.clone(),
            self.code_db.clone(),
            Block::new(
                self.chain_id,
                self.history_hashes.clone(),
                Word::default(),
                &self.eth_block,
            )
            .unwrap(),
            self.circuits_params,
            feature_config,
        )
    }

    fn init_dbs(geth_data: &GethData) -> (StateDB, CodeDB) {
        let mut sdb = StateDB::new();
        let mut code_db = CodeDB::default();

        let access_set = get_state_accesses(&geth_data.eth_block, &geth_data.geth_traces)
            .expect("state accesses");
        // Initialize all accesses accounts to zero
        for addr in access_set.state.keys() {
            sdb.set_account(addr, state_db::Account::zero());
        }

        for account in &geth_data.accounts {
            code_db.insert(account.code.to_vec());
            sdb.set_account(&account.address, state_db::Account::from(account.clone()));
        }
        (sdb, code_db)
    }
}
impl BlockData<FixedCParams> {
    /// Create a new block from the given Geth data.
    pub fn new_from_geth_data_with_params(
        geth_data: GethData,
        circuits_params: FixedCParams,
    ) -> Self {
        let (sdb, code_db) = Self::init_dbs(&geth_data);

        Self {
            sdb,
            code_db,
            chain_id: geth_data.chain_id,
            history_hashes: geth_data.history_hashes,
            eth_block: geth_data.eth_block,
            geth_traces: geth_data.geth_traces,
            circuits_params,
        }
    }
}

impl BlockData<DynamicCParams> {
    /// Create a new block with one chunk
    /// from the given Geth data with default CircuitsParams.
    pub fn new_from_geth_data(geth_data: GethData) -> Self {
        Self::new_from_geth_data_chunked(geth_data, 1)
    }

    /// Create a new block with given number of chunks
    /// from the given Geth data with default CircuitsParams.
    pub fn new_from_geth_data_chunked(geth_data: GethData, total_chunks: usize) -> Self {
        let (sdb, code_db) = Self::init_dbs(&geth_data);

        Self {
            sdb,
            code_db,
            chain_id: geth_data.chain_id,
            history_hashes: geth_data.history_hashes,
            eth_block: geth_data.eth_block,
            geth_traces: geth_data.geth_traces,
            circuits_params: DynamicCParams { total_chunks },
        }
    }
}