Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add single and mapping struct to integration test for generic extraction (Part 4) #397

Open
wants to merge 24 commits into
base: generic-extraction-row-id-update
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
93c80de
Update integration test for generic extraction.
silathdiir Oct 24, 2024
a2c4cfc
Remove `bit_offset` in API.
silathdiir Nov 7, 2024
d7607cf
Merge remote-tracking branch 'origin/generic-extraction-row-id-update…
silathdiir Nov 7, 2024
51768ea
Merge remote-tracking branch 'origin/generic-extraction-row-id-update…
silathdiir Nov 7, 2024
b33cd73
Combine the single and mapping test cases, and update the merge test …
silathdiir Nov 8, 2024
911aadb
Rename to `ContractController` and update the trait function names.
silathdiir Nov 12, 2024
6b8d4bc
Add TODO to the deprecated `bit_offset`.
silathdiir Nov 12, 2024
e2b717c
Fix the wrong log.
silathdiir Nov 12, 2024
302b17e
Add back the MPT key and ptr check.
silathdiir Nov 12, 2024
6155a66
Fix `last_byte_offset` to not restrict the maximum length.
silathdiir Nov 12, 2024
051bf96
Rename `MetadataGadget` to `ColumnsMetadata`, and leave `build` and `…
silathdiir Nov 12, 2024
c21fe13
Add more common `_raw` functions for the values extraction identifier…
silathdiir Nov 12, 2024
29fd77b
Remove `TableDimension`.
silathdiir Nov 13, 2024
2d1aa8a
Fix the row unique ID always get from the key ID column.
silathdiir Nov 13, 2024
38d6d30
Fix to the value column as the secondary index column in mapping stru…
silathdiir Nov 13, 2024
be3db69
Merge the match arms for mapping update.
silathdiir Nov 14, 2024
973325d
Set to simple rest for the row key.
silathdiir Nov 14, 2024
c423611
Fix the slot checking logic in the storage trie.
silathdiir Nov 14, 2024
50a58d9
Refactor the columns metadata and APIs.
silathdiir Nov 14, 2024
f53f0ee
Fix test.
silathdiir Nov 15, 2024
45deacf
Fix test.
silathdiir Nov 15, 2024
8e1fb40
Merge remote-tracking branch 'origin/generic-extraction-row-id-update…
silathdiir Nov 18, 2024
a22e6d7
Merge remote-tracking branch 'origin/generic-extraction-row-id-update…
silathdiir Dec 13, 2024
47a5784
Merge branch 'generic-extraction-row-id-update' into generic-extracti…
nicholas-mainardi Jan 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions mp2-v1/src/values_extraction/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
use super::{
branch::{BranchCircuit, BranchWires},
extension::{ExtensionNodeCircuit, ExtensionNodeWires},
gadgets::metadata_gadget::MetadataGadget,
gadgets::metadata_gadget::ColumnsMetadata,
leaf_mapping::{LeafMappingCircuit, LeafMappingWires},
leaf_mapping_of_mappings::{LeafMappingOfMappingsCircuit, LeafMappingOfMappingsWires},
leaf_single::{LeafSingleCircuit, LeafSingleWires},
public_inputs::PublicInputs,
};
use crate::{api::InputNode, MAX_BRANCH_NODE_LEN, MAX_LEAF_NODE_LEN};
use crate::{api::InputNode, MAX_BRANCH_NODE_LEN};
use anyhow::{bail, ensure, Result};
use log::debug;
use mp2_common::{
Expand Down Expand Up @@ -67,7 +67,7 @@ where
pub fn new_single_variable_leaf(
node: Vec<u8>,
slot: u8,
metadata: MetadataGadget<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
metadata: ColumnsMetadata<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
) -> Self {
let slot = SimpleSlot::new(slot);

Expand All @@ -84,7 +84,7 @@ where
slot: u8,
mapping_key: Vec<u8>,
key_id: u64,
metadata: MetadataGadget<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
metadata: ColumnsMetadata<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
) -> Self {
let slot = MappingSlot::new(slot, mapping_key);
let key_id = F::from_canonical_u64(key_id);
Expand All @@ -106,7 +106,7 @@ where
inner_key: Vec<u8>,
outer_key_id: u64,
inner_key_id: u64,
metadata: MetadataGadget<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
metadata: ColumnsMetadata<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
) -> Self {
let slot = MappingSlot::new(slot, outer_key);
let [outer_key_id, inner_key_id] = [outer_key_id, inner_key_id].map(F::from_canonical_u64);
Expand Down Expand Up @@ -517,14 +517,14 @@ mod tests {
let storage_slot1 = StorageSlot::Simple(TEST_SLOTS[0] as usize);
let storage_slot2 = StorageSlot::Simple(TEST_SLOTS[1] as usize);

let mut metadata1 = MetadataGadget::sample(TEST_SLOTS[0], 0);
let mut metadata1 = ColumnsMetadata::sample(TEST_SLOTS[0], 0);
// We only extract the first column for simple slot.
metadata1.num_extracted_columns = 1;
// Set the second test slot and EVM word.
metadata1.table_info[1].slot = TEST_SLOTS[1].to_field();
metadata1.table_info[1].evm_word = F::ZERO;
// Initialize the second metadata with second column identifier.
let metadata2 = MetadataGadget::new(
let metadata2 = ColumnsMetadata::new(
metadata1.table_info[..metadata1.num_actual_columns].to_vec(),
slice::from_ref(&metadata1.table_info[1].identifier.to_canonical_u64()),
0,
Expand Down Expand Up @@ -553,14 +553,14 @@ mod tests {
let storage_slot2 =
StorageSlot::Node(StorageSlotNode::new_struct(parent_slot, TEST_EVM_WORDS[1]));

let mut metadata1 = MetadataGadget::sample(TEST_SLOT, TEST_EVM_WORDS[0]);
let mut metadata1 = ColumnsMetadata::sample(TEST_SLOT, TEST_EVM_WORDS[0]);
// We only extract the first column for simple slot.
metadata1.num_extracted_columns = 1;
// Set the second test slot and EVM word.
metadata1.table_info[1].slot = TEST_SLOT.to_field();
metadata1.table_info[1].evm_word = TEST_EVM_WORDS[1].to_field();
// Initialize the second metadata with second column identifier.
let metadata2 = MetadataGadget::new(
let metadata2 = ColumnsMetadata::new(
metadata1.table_info[..metadata1.num_actual_columns].to_vec(),
slice::from_ref(&metadata1.table_info[1].identifier.to_canonical_u64()),
TEST_EVM_WORDS[1],
Expand All @@ -587,7 +587,7 @@ mod tests {
let storage_slot1 = StorageSlot::Mapping(mapping_key1, TEST_SLOT as usize);
let storage_slot2 = StorageSlot::Mapping(mapping_key2, TEST_SLOT as usize);

let mut metadata1 = MetadataGadget::sample(TEST_SLOT, 0);
let mut metadata1 = ColumnsMetadata::sample(TEST_SLOT, 0);
// We only extract the first column for simple slot.
metadata1.num_extracted_columns = 1;
// Set the second test slot and EVM word.
Expand Down Expand Up @@ -622,14 +622,14 @@ mod tests {
let storage_slot2 =
StorageSlot::Node(StorageSlotNode::new_struct(parent_slot, TEST_EVM_WORDS[1]));

let mut metadata1 = MetadataGadget::sample(TEST_SLOT, TEST_EVM_WORDS[0]);
let mut metadata1 = ColumnsMetadata::sample(TEST_SLOT, TEST_EVM_WORDS[0]);
// We only extract the first column for simple slot.
metadata1.num_extracted_columns = 1;
// Set the second test slot and EVM word.
metadata1.table_info[1].slot = TEST_SLOT.to_field();
metadata1.table_info[1].evm_word = TEST_EVM_WORDS[1].to_field();
// Initialize the second metadata with second column identifier.
let metadata2 = MetadataGadget::new(
let metadata2 = ColumnsMetadata::new(
metadata1.table_info[..metadata1.num_actual_columns].to_vec(),
slice::from_ref(&metadata1.table_info[1].identifier.to_canonical_u64()),
TEST_EVM_WORDS[1],
Expand Down Expand Up @@ -663,7 +663,7 @@ mod tests {
let storage_slot2 =
StorageSlot::Node(StorageSlotNode::new_struct(parent_slot, TEST_EVM_WORDS[1]));

let mut metadata1 = MetadataGadget::sample(TEST_SLOT, TEST_EVM_WORDS[0]);
let mut metadata1 = ColumnsMetadata::sample(TEST_SLOT, TEST_EVM_WORDS[0]);
// We only extract the first column for simple slot.
metadata1.num_extracted_columns = 1;
// Set the second test slot and EVM word.
Expand Down Expand Up @@ -692,7 +692,7 @@ mod tests {
let _ = env_logger::try_init();

let storage_slot = StorageSlot::Simple(TEST_SLOT as usize);
let metadata = MetadataGadget::sample(TEST_SLOT, 0);
let metadata = ColumnsMetadata::sample(TEST_SLOT, 0);
let test_slot = StorageSlotInfo::new(storage_slot, metadata, None, None);

test_branch_with_multiple_children(NUM_CHILDREN, test_slot);
Expand Down Expand Up @@ -735,7 +735,7 @@ mod tests {
parent_slot.clone(),
TEST_EVM_WORD,
));
let mut metadata = MetadataGadget::sample(TEST_SLOT, 0);
let mut metadata = ColumnsMetadata::sample(TEST_SLOT, 0);
// We only extract the first column for simple slot.
metadata.num_extracted_columns = 1;
let test_slot = StorageSlotInfo::new(storage_slot, metadata, None, None);
Expand All @@ -753,7 +753,7 @@ mod tests {
parent_slot.clone(),
TEST_EVM_WORD,
));
let mut metadata = MetadataGadget::sample(TEST_SLOT, TEST_EVM_WORD);
let mut metadata = ColumnsMetadata::sample(TEST_SLOT, TEST_EVM_WORD);
// We only extract the first column.
metadata.num_extracted_columns = 1;
let key_id = rng.gen();
Expand All @@ -775,7 +775,7 @@ mod tests {
);
let storage_slot =
StorageSlot::Node(StorageSlotNode::new_struct(parent_slot, TEST_EVM_WORD));
let mut metadata = MetadataGadget::sample(TEST_SLOT, TEST_EVM_WORD);
let mut metadata = ColumnsMetadata::sample(TEST_SLOT, TEST_EVM_WORD);
// We only extract the first column.
metadata.num_extracted_columns = 1;
let outer_key_id = rng.gen();
Expand Down
2 changes: 1 addition & 1 deletion mp2-v1/src/values_extraction/gadgets/column_gadget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ pub fn extract_value(
[info.byte_offset, info.length].map(|f| usize::try_from(f.to_canonical_u64()).unwrap());

// last_byte_offset = info.byte_offset + ceil(info.length / 8) - 1
let last_byte_offset = (byte_offset + length.div_ceil(8) - 1).min(MAPPING_LEAF_VALUE_LEN - 1);
let last_byte_offset = byte_offset + length.div_ceil(8) - 1;

// Extract all the bits of the field aligined with bytes.
let mut result_bytes = Vec::with_capacity(last_byte_offset - byte_offset + 1);
Expand Down
3 changes: 2 additions & 1 deletion mp2-v1/src/values_extraction/gadgets/column_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ impl ColumnInfo {
slot_input.slot,
identifier,
slot_input.byte_offset,
0, // bit_offset
// TODO: Will remove this bit_offset from the internal data structures and the circuit.
0,
slot_input.length,
slot_input.evm_word,
)
Expand Down
28 changes: 17 additions & 11 deletions mp2-v1/src/values_extraction/gadgets/metadata_gadget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use serde::{Deserialize, Serialize};
use std::{array, iter::once};

#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct MetadataGadget<const MAX_COLUMNS: usize, const MAX_FIELD_PER_EVM: usize> {
pub struct ColumnsMetadata<const MAX_COLUMNS: usize, const MAX_FIELD_PER_EVM: usize> {
#[serde(
serialize_with = "serialize_long_array",
deserialize_with = "deserialize_long_array"
Expand All @@ -45,7 +45,7 @@ pub struct MetadataGadget<const MAX_COLUMNS: usize, const MAX_FIELD_PER_EVM: usi
}

impl<const MAX_COLUMNS: usize, const MAX_FIELD_PER_EVM: usize>
MetadataGadget<MAX_COLUMNS, MAX_FIELD_PER_EVM>
ColumnsMetadata<MAX_COLUMNS, MAX_FIELD_PER_EVM>
{
/// Create a new MPT metadata.
pub fn new(
Expand Down Expand Up @@ -145,7 +145,13 @@ impl<const MAX_COLUMNS: usize, const MAX_FIELD_PER_EVM: usize>
pub fn evm_word(&self) -> u32 {
self.evm_word
}
}

pub struct MetadataGadget<const MAX_COLUMNS: usize, const MAX_FIELD_PER_EVM: usize>;

impl<const MAX_COLUMNS: usize, const MAX_FIELD_PER_EVM: usize>
MetadataGadget<MAX_COLUMNS, MAX_FIELD_PER_EVM>
{
pub(crate) fn build(b: &mut CBuilder) -> MetadataTarget<MAX_COLUMNS, MAX_FIELD_PER_EVM> {
let table_info = array::from_fn(|_| b.add_virtual_column_info());
let [is_actual_columns, is_extracted_columns] =
Expand All @@ -161,24 +167,24 @@ impl<const MAX_COLUMNS: usize, const MAX_FIELD_PER_EVM: usize>
}

pub(crate) fn assign(
&self,
pw: &mut PartialWitness<F>,
columns_metadata: &ColumnsMetadata<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
metadata_target: &MetadataTarget<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
) {
pw.set_column_info_target_arr(&metadata_target.table_info, &self.table_info);
pw.set_column_info_target_arr(&metadata_target.table_info, &columns_metadata.table_info);
metadata_target
.is_actual_columns
.iter()
.enumerate()
.for_each(|(i, t)| pw.set_bool_target(*t, i < self.num_actual_columns));
.for_each(|(i, t)| pw.set_bool_target(*t, i < columns_metadata.num_actual_columns));
metadata_target
.is_extracted_columns
.iter()
.enumerate()
.for_each(|(i, t)| pw.set_bool_target(*t, i < self.num_extracted_columns));
.for_each(|(i, t)| pw.set_bool_target(*t, i < columns_metadata.num_extracted_columns));
pw.set_target(
metadata_target.evm_word,
F::from_canonical_u32(self.evm_word),
F::from_canonical_u32(columns_metadata.evm_word),
);
}
}
Expand Down Expand Up @@ -314,7 +320,7 @@ pub(crate) mod tests {

#[derive(Clone, Debug)]
struct TestMedataCircuit {
metadata_gadget: MetadataGadget<TEST_MAX_COLUMNS, TEST_MAX_FIELD_PER_EVM>,
columns_metadata: ColumnsMetadata<TEST_MAX_COLUMNS, TEST_MAX_FIELD_PER_EVM>,
slot: u8,
expected_num_actual_columns: usize,
expected_metadata_digest: Point,
Expand Down Expand Up @@ -348,7 +354,7 @@ pub(crate) mod tests {
}

fn prove(&self, pw: &mut PartialWitness<F>, wires: &Self::Wires) {
self.metadata_gadget.assign(pw, &wires.0);
MetadataGadget::assign(pw, &self.columns_metadata, &wires.0);
pw.set_target(wires.1, F::from_canonical_u8(self.slot));
pw.set_target(
wires.2,
Expand All @@ -365,12 +371,12 @@ pub(crate) mod tests {
let slot = rng.gen();
let evm_word = rng.gen();

let metadata_gadget = MetadataGadget::sample(slot, evm_word);
let metadata_gadget = ColumnsMetadata::sample(slot, evm_word);
let expected_num_actual_columns = metadata_gadget.num_actual_columns();
let expected_metadata_digest = metadata_gadget.digest();

let test_circuit = TestMedataCircuit {
metadata_gadget,
columns_metadata: metadata_gadget,
slot,
expected_num_actual_columns,
expected_metadata_digest,
Expand Down
10 changes: 6 additions & 4 deletions mp2-v1/src/values_extraction/leaf_mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::values_extraction::{
gadgets::{
column_gadget::ColumnGadget,
metadata_gadget::{MetadataGadget, MetadataTarget},
metadata_gadget::{ColumnsMetadata, MetadataTarget},
},
public_inputs::{PublicInputs, PublicInputsArgs},
KEY_ID_PREFIX,
Expand Down Expand Up @@ -38,6 +38,8 @@ use recursion_framework::circuit_builder::CircuitLogicWires;
use serde::{Deserialize, Serialize};
use std::{iter, iter::once};

use super::gadgets::metadata_gadget::MetadataGadget;

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct LeafMappingWires<
const NODE_LEN: usize,
Expand Down Expand Up @@ -72,7 +74,7 @@ pub struct LeafMappingCircuit<
pub(crate) node: Vec<u8>,
pub(crate) slot: MappingSlot,
pub(crate) key_id: F,
pub(crate) metadata: MetadataGadget<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
pub(crate) metadata: ColumnsMetadata<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
}

impl<const NODE_LEN: usize, const MAX_COLUMNS: usize, const MAX_FIELD_PER_EVM: usize>
Expand Down Expand Up @@ -194,7 +196,7 @@ where
pw.set_target(wires.key_id, self.key_id);
self.slot
.assign_struct(pw, &wires.slot, self.metadata.evm_word);
self.metadata.assign(pw, &wires.metadata);
MetadataGadget::assign(pw, &self.metadata, &wires.metadata);
}
}

Expand Down Expand Up @@ -301,7 +303,7 @@ mod tests {
let evm_word = storage_slot.evm_offset();
let key_id = rng.gen();
let metadata =
MetadataGadget::<TEST_MAX_COLUMNS, TEST_MAX_FIELD_PER_EVM>::sample(slot, evm_word);
ColumnsMetadata::<TEST_MAX_COLUMNS, TEST_MAX_FIELD_PER_EVM>::sample(slot, evm_word);
// Compute the metadata digest.
let table_info = metadata.actual_table_info().to_vec();
let extracted_column_identifiers = metadata.extracted_column_identifiers();
Expand Down
10 changes: 6 additions & 4 deletions mp2-v1/src/values_extraction/leaf_mapping_of_mappings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use crate::values_extraction::{
gadgets::{
column_gadget::ColumnGadget,
metadata_gadget::{MetadataGadget, MetadataTarget},
metadata_gadget::{ColumnsMetadata, MetadataTarget},
},
public_inputs::{PublicInputs, PublicInputsArgs},
INNER_KEY_ID_PREFIX, OUTER_KEY_ID_PREFIX,
Expand Down Expand Up @@ -40,6 +40,8 @@ use recursion_framework::circuit_builder::CircuitLogicWires;
use serde::{Deserialize, Serialize};
use std::{iter, iter::once};

use super::gadgets::metadata_gadget::MetadataGadget;

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct LeafMappingOfMappingsWires<
const NODE_LEN: usize,
Expand Down Expand Up @@ -79,7 +81,7 @@ pub struct LeafMappingOfMappingsCircuit<
pub(crate) inner_key: Vec<u8>,
pub(crate) outer_key_id: F,
pub(crate) inner_key_id: F,
pub(crate) metadata: MetadataGadget<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
pub(crate) metadata: ColumnsMetadata<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
}

impl<const NODE_LEN: usize, const MAX_COLUMNS: usize, const MAX_FIELD_PER_EVM: usize>
Expand Down Expand Up @@ -234,7 +236,7 @@ where
&self.inner_key,
self.metadata.evm_word,
);
self.metadata.assign(pw, &wires.metadata);
MetadataGadget::assign(pw, &self.metadata, &wires.metadata);
}
}

Expand Down Expand Up @@ -349,7 +351,7 @@ mod tests {
let evm_word = storage_slot.evm_offset();
let [outer_key_id, inner_key_id] = array::from_fn(|_| rng.gen());
let metadata =
MetadataGadget::<TEST_MAX_COLUMNS, TEST_MAX_FIELD_PER_EVM>::sample(slot, evm_word);
ColumnsMetadata::<TEST_MAX_COLUMNS, TEST_MAX_FIELD_PER_EVM>::sample(slot, evm_word);
// Compute the metadata digest.
let table_info = metadata.actual_table_info().to_vec();
let extracted_column_identifiers = metadata.extracted_column_identifiers();
Expand Down
10 changes: 6 additions & 4 deletions mp2-v1/src/values_extraction/leaf_single.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::values_extraction::{
gadgets::{
column_gadget::ColumnGadget,
metadata_gadget::{MetadataGadget, MetadataTarget},
metadata_gadget::{ColumnsMetadata, MetadataTarget},
},
public_inputs::{PublicInputs, PublicInputsArgs},
};
Expand Down Expand Up @@ -31,6 +31,8 @@ use recursion_framework::circuit_builder::CircuitLogicWires;
use serde::{Deserialize, Serialize};
use std::iter::once;

use super::gadgets::metadata_gadget::MetadataGadget;

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct LeafSingleWires<
const NODE_LEN: usize,
Expand Down Expand Up @@ -60,7 +62,7 @@ pub struct LeafSingleCircuit<
> {
pub(crate) node: Vec<u8>,
pub(crate) slot: SimpleSlot,
pub(crate) metadata: MetadataGadget<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
pub(crate) metadata: ColumnsMetadata<MAX_COLUMNS, MAX_FIELD_PER_EVM>,
}

impl<const NODE_LEN: usize, const MAX_COLUMNS: usize, const MAX_FIELD_PER_EVM: usize>
Expand Down Expand Up @@ -146,7 +148,7 @@ where
);
self.slot
.assign_struct(pw, &wires.slot, self.metadata.evm_word);
self.metadata.assign(pw, &wires.metadata);
MetadataGadget::assign(pw, &self.metadata, &wires.metadata);
}
}

Expand Down Expand Up @@ -247,7 +249,7 @@ mod tests {
let slot = storage_slot.slot();
let evm_word = storage_slot.evm_offset();
let metadata =
MetadataGadget::<TEST_MAX_COLUMNS, TEST_MAX_FIELD_PER_EVM>::sample(slot, evm_word);
ColumnsMetadata::<TEST_MAX_COLUMNS, TEST_MAX_FIELD_PER_EVM>::sample(slot, evm_word);
// Compute the metadata digest.
let metadata_digest = metadata.digest();
// Compute the values digest.
Expand Down
Loading
Loading