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
use std::iter;
use super::*;
/// Tag to identify the field in a Block Table row
// Keep the sequence consistent with OpcodeId for scalar
#[derive(Clone, Copy, Debug)]
pub enum BlockContextFieldTag {
/// Coinbase field
Coinbase = 1,
/// Timestamp field
Timestamp,
/// Number field
Number,
/// Difficulty field
Difficulty,
/// Gas Limit field
GasLimit,
/// Base Fee field
BaseFee = 8,
/// Block Hash field
BlockHash,
/// Chain ID field. Although this is not a field in the block header, we
/// add it here for convenience.
ChainId,
/// Withdrawal Root field
WithdrawalRoot,
}
impl_expr!(BlockContextFieldTag);
/// Table with Block header fields
#[derive(Clone, Debug)]
pub struct BlockTable {
/// Tag
pub tag: Column<Fixed>,
/// Index
pub index: Column<Fixed>,
/// Value
pub value: WordLoHi<Column<Advice>>,
}
impl BlockTable {
/// Construct a new BlockTable
pub fn construct<F: Field>(meta: &mut ConstraintSystem<F>) -> Self {
Self {
tag: meta.fixed_column(),
index: meta.fixed_column(),
value: WordLoHi::new([meta.advice_column(), meta.advice_column()]),
}
}
/// Assign the `BlockTable` from a `BlockContext`.
pub fn load<F: Field>(
&self,
layouter: &mut impl Layouter<F>,
block: &BlockContext,
) -> Result<(), Error> {
layouter.assign_region(
|| "block table",
|mut region| {
for (offset, row) in iter::once([Value::known(F::ZERO); 4])
.chain(block.table_assignments::<F>())
.enumerate()
{
region.assign_fixed(
|| format!("block table tag {}", offset),
self.tag,
offset,
|| row[0],
)?;
region.assign_fixed(
|| format!("block table index {}", offset),
self.index,
offset,
|| row[1],
)?;
WordLoHi::new([row[2], row[3]]).assign_advice(
&mut region,
|| format!("block table value {}", offset),
self.value,
offset,
)?;
}
Ok(())
},
)
}
}
impl<F: Field> LookupTable<F> for BlockTable {
fn columns(&self) -> Vec<Column<Any>> {
vec![
self.tag.into(),
self.index.into(),
self.value.lo().into(),
self.value.hi().into(),
]
}
fn annotations(&self) -> Vec<String> {
vec![
String::from("tag"),
String::from("index"),
String::from("value_lo"),
String::from("value_hi"),
]
}
}