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
139
140
141
use super::{
    helpers::Indexable,
    rlp_gadgets::RLPItemWitness,
    witness_row::{Node, StartRowType},
};
use crate::{
    circuit,
    circuit_tools::{cached_region::CachedRegion, cell_manager::Cell},
    mpt_circuit::{
        helpers::{
            key_memory, main_memory, parent_memory, KeyData, MPTConstraintBuilder, MainData,
            ParentData,
        },
        MPTConfig, MPTContext, MptMemory, RlpItemType,
    },
    util::word::WordLoHi,
};
use eth_types::{Field, OpsIdentity};
use gadgets::util::Scalar;
use halo2_proofs::plonk::{Error, VirtualCells};

#[derive(Clone, Debug, Default)]
pub(crate) struct StartConfig<F> {
    proof_type: Cell<F>,
}

impl<F: Field> StartConfig<F> {
    pub fn configure(
        meta: &mut VirtualCells<'_, F>,
        cb: &mut MPTConstraintBuilder<F>,
        ctx: &mut MPTContext<F>,
    ) -> Self {
        let mut config = StartConfig::default();

        circuit!([meta, cb], {
            let root_items = [
                ctx.rlp_item(meta, cb, StartRowType::RootS as usize, RlpItemType::Hash),
                ctx.rlp_item(meta, cb, StartRowType::RootC as usize, RlpItemType::Hash),
            ];

            config.proof_type = cb.query_cell();

            let mut root = vec![WordLoHi::zero(); 2];
            for is_s in [true, false] {
                root[is_s.idx()] = root_items[is_s.idx()].word();
            }

            MainData::store(
                cb,
                &mut ctx.memory[main_memory()],
                [
                    config.proof_type.expr(),
                    false.expr(),
                    0.expr(),
                    root[true.idx()].lo().expr(),
                    root[true.idx()].hi().expr(),
                    root[false.idx()].lo().expr(),
                    root[false.idx()].hi().expr(),
                ],
            );

            for is_s in [true, false] {
                ParentData::store(
                    cb,
                    &mut ctx.memory[parent_memory(is_s)],
                    root[is_s.idx()].clone(),
                    0.expr(),
                    true.expr(),
                    false.expr(),
                    root[is_s.idx()].clone(),
                );
                KeyData::store_defaults(cb, &mut ctx.memory[key_memory(is_s)]);
            }
        });

        config
    }

    #[allow(clippy::too_many_arguments)]
    pub fn assign(
        &self,
        region: &mut CachedRegion<'_, '_, F>,
        _mpt_config: &MPTConfig<F>,
        memory: &mut MptMemory<F>,
        offset: usize,
        node: &Node,
        rlp_values: &[RLPItemWitness],
    ) -> Result<(), Error> {
        let start = &node.start.clone().unwrap();

        let _root_items = [
            rlp_values[StartRowType::RootS as usize].clone(),
            rlp_values[StartRowType::RootC as usize].clone(),
        ];

        self.proof_type
            .assign(region, offset, start.proof_type.scalar())?;

        let mut root = [WordLoHi::zero(); 2];
        for is_s in [true, false] {
            root[is_s.idx()] = rlp_values[is_s.idx()].word();
        }

        MainData::witness_store(
            region,
            offset,
            &mut memory[main_memory()],
            start.proof_type as usize,
            false,
            0.scalar(),
            root[true.idx()],
            root[false.idx()],
        )?;

        for is_s in [true, false] {
            ParentData::witness_store(
                region,
                offset,
                &mut memory[parent_memory(is_s)],
                root[is_s.idx()],
                0.scalar(),
                true,
                false,
                root[is_s.idx()],
            )?;
            KeyData::witness_store(
                region,
                offset,
                &mut memory[key_memory(is_s)],
                F::ZERO,
                F::ONE,
                0,
                F::ZERO,
                F::ONE,
                0,
            )?;
        }

        Ok(())
    }
}