Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion mp2-common/src/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ pub struct ReceiptProofInfo {
}

/// Contains all the information for an [`Event`] in rlp form
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Hash, PartialEq, Eq)]
pub struct EventLogInfo<const NO_TOPICS: usize, const MAX_DATA: usize> {
/// Size in bytes of the whole log rlp encoded
pub size: usize,
Expand Down
7 changes: 2 additions & 5 deletions mp2-v1/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,12 @@ TEST_BINDINGS_OUT_PATH=$(TEST_CONTRACT_PATH)/out/$(TEST_BINDINGS_FOLDER)

# Generate the integration test contract bindings.
bindings:
rm -rf $(TEST_BINDINGS_MOD_PATH) $(TEST_BINDINGS_OUT_PATH)

# Generate new bindings.
forge install --root $(TEST_CONTRACT_PATH)
forge bind --alloy --module --root $(TEST_CONTRACT_PATH)

# Move the bindings module to the integration test location.
mv -f $(TEST_BINDINGS_OUT_PATH) $(TEST_BINDINGS_MOD_PATH)
forge bind --bindings-path $(TEST_BINDINGS_MOD_PATH) --alloy --module --root $(TEST_CONTRACT_PATH) --extra-output abi --overwrite
cargo fmt


# Declare phony targets
.PHONY: bindings
2 changes: 1 addition & 1 deletion mp2-v1/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ fn metadata_digest_mapping(address: &Address, chain_id: u64, extra: Vec<u8>, slo
compute_leaf_mapping_metadata_digest(key_id, value_id, slot)
}

fn combine_digest_and_block(digest: Digest) -> HashOutput {
pub fn combine_digest_and_block(digest: Digest) -> HashOutput {
let block_id = identifier_block_column();
let inputs = digest
.to_fields()
Expand Down
2 changes: 1 addition & 1 deletion mp2-v1/src/final_extraction/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub struct PublicParameters {
circuit_set: RecursiveCircuits<F, C, D>,
}

const FINAL_EXTRACTION_CIRCUIT_SET_SIZE: usize = 2;
const FINAL_EXTRACTION_CIRCUIT_SET_SIZE: usize = 4;
pub(super) const NUM_IO: usize = PublicInputs::<Target>::TOTAL_LEN;

impl PublicParameters {
Expand Down
1 change: 0 additions & 1 deletion mp2-v1/src/final_extraction/receipt_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ impl CircuitLogicWires<F, D, 0> for ReceiptRecursiveWires {
_verified_proofs: [&plonky2::plonk::proof::ProofWithPublicInputsTarget<D>; 0],
builder_parameters: Self::CircuitBuilderParams,
) -> Self {
// value proof for table a and value proof for table b = 2
let verification = ReceiptCircuitProofInputs::build(builder, &builder_parameters);
ReceiptExtractionCircuit::build(
builder,
Expand Down
42 changes: 28 additions & 14 deletions mp2-v1/src/values_extraction/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,27 +716,41 @@ mod tests {
let receipt_proof_infos = generate_receipt_test_info::<1, 0>();
let receipt_proofs = receipt_proof_infos.proofs();
let query = receipt_proof_infos.query();
// We check that we have enough receipts and then take the second and third info
// (the MPT proof for the first node is different).
// Then check that the node above both is a branch.
assert!(receipt_proofs.len() > 3);
let second_info = &receipt_proofs[1];
let third_info = &receipt_proofs[2];
// We need two nodes that are children of the same branch so we compare the last but two nodes for each of them until we find a case that works
let (info_one, info_two) = if let Some((one, two)) = receipt_proofs
.iter()
.enumerate()
.find_map(|(i, current_proof)| {
let current_node_second_to_last =
current_proof.mpt_proof[current_proof.mpt_proof.len() - 2].clone();
receipt_proofs
.iter()
.skip(i + 1)
.find(|find_info| {
find_info.mpt_proof[find_info.mpt_proof.len() - 2].clone()
== current_node_second_to_last
})
.map(|matching| (current_proof, matching))
}) {
(one, two)
} else {
panic!("No relevant events with same branch node parent")
};

let proof_length_1 = second_info.mpt_proof.len();
let proof_length_2 = third_info.mpt_proof.len();
let proof_length_1 = info_one.mpt_proof.len();
let proof_length_2 = info_two.mpt_proof.len();

let list_one = rlp::decode_list::<Vec<u8>>(&second_info.mpt_proof[proof_length_1 - 2]);
let list_two = rlp::decode_list::<Vec<u8>>(&third_info.mpt_proof[proof_length_2 - 2]);
let list_one = rlp::decode_list::<Vec<u8>>(&info_one.mpt_proof[proof_length_1 - 2]);
let list_two = rlp::decode_list::<Vec<u8>>(&info_two.mpt_proof[proof_length_2 - 2]);

assert!(list_one == list_two);
assert_eq!(list_one, list_two);
assert!(list_one.len() == 17);

println!("Generating params...");
let params = build_circuits_params();

println!("Proving leaf 1...");
let leaf_input_1 = CircuitInput::new_receipt_leaf(second_info, query);
let leaf_input_1 = CircuitInput::new_receipt_leaf(info_one, query);
let now = std::time::Instant::now();
let leaf_proof1 = generate_proof(&params, leaf_input_1).unwrap();
{
Expand All @@ -751,7 +765,7 @@ mod tests {
);

println!("Proving leaf 2...");
let leaf_input_2 = CircuitInput::new_receipt_leaf(third_info, query);
let leaf_input_2 = CircuitInput::new_receipt_leaf(info_two, query);
let now = std::time::Instant::now();
let leaf_proof2 = generate_proof(&params, leaf_input_2).unwrap();
println!(
Expand All @@ -762,7 +776,7 @@ mod tests {
// The branch case for receipts is identical to that of a mapping so we use the same api.
println!("Proving branch...");
let branch_input = CircuitInput::new_mapping_variable_branch(
second_info.mpt_proof[proof_length_1 - 2].clone(),
info_one.mpt_proof[proof_length_1 - 2].clone(),
vec![leaf_proof1, leaf_proof2],
);

Expand Down
91 changes: 90 additions & 1 deletion mp2-v1/src/values_extraction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,26 @@ pub(crate) const BLOCK_ID_DST: &[u8] = b"BLOCK_NUMBER";

/// Prefix used for making a topic column id.
const TOPIC_PREFIX: &[u8] = b"topic";
/// [`TOPIC_PREFIX`] as a [`str`]
const TOPIC_NAME: &str = "topic";

/// Prefix used for making a data column id.
const DATA_PREFIX: &[u8] = b"data";
/// [`DATA_PREFIX`] as a [`str`]
const DATA_NAME: &str = "data";

/// Prefix for transaction index
const TX_INDEX_PREFIX: &[u8] = b"tx index";

/// Prefix for log number
const LOG_NUMBER_PREFIX: &[u8] = b"log number";
/// [`LOG_NUMBER_PREFIX`] as a [`str`]
const LOG_NUMBER_NAME: &str = "log number";

/// Prefix for gas used
const GAS_USED_PREFIX: &[u8] = b" gas used";
const GAS_USED_PREFIX: &[u8] = b"gas used";
/// [`GAS_USED_PREFIX`] as a [`str`]
const GAS_USED_NAME: &str = "gas used";

pub fn identifier_block_column() -> u64 {
let inputs: Vec<F> = BLOCK_ID_DST.to_fields();
Expand Down Expand Up @@ -401,3 +409,84 @@ pub fn compute_receipt_leaf_value_digest<const NO_TOPICS: usize, const MAX_DATA:
})
.fold(Digest::NEUTRAL, |acc, p| acc + p)
}

/// Function that computes the column identifiers for the non-indexed columns together with their names as [`String`]s.
pub fn compute_non_indexed_receipt_column_ids<const NO_TOPICS: usize, const MAX_DATA: usize>(
event: &EventLogInfo<NO_TOPICS, MAX_DATA>,
) -> Vec<(String, GFp)> {
let log_number_input = [
event.address.as_slice(),
event.event_signature.as_slice(),
LOG_NUMBER_PREFIX,
]
.concat()
.into_iter()
.map(GFp::from_canonical_u8)
.collect::<Vec<GFp>>();
let log_number_column_id = H::hash_no_pad(&log_number_input).elements[0];

let gas_used_input = [
event.address.as_slice(),
event.event_signature.as_slice(),
GAS_USED_PREFIX,
]
.concat()
.into_iter()
.map(GFp::from_canonical_u8)
.collect::<Vec<GFp>>();
let gas_used_column_id = H::hash_no_pad(&gas_used_input).elements[0];

let topic_ids = event
.topics
.iter()
.enumerate()
.map(|(j, _)| {
let input = [
event.address.as_slice(),
event.event_signature.as_slice(),
TOPIC_PREFIX,
&[j as u8 + 1],
]
.concat()
.into_iter()
.map(GFp::from_canonical_u8)
.collect::<Vec<GFp>>();
(
format!("{}_{}", TOPIC_NAME, j + 1),
H::hash_no_pad(&input).elements[0],
)
})
.collect::<Vec<(String, GFp)>>();

let data_ids = event
.data
.iter()
.enumerate()
.map(|(j, _)| {
let input = [
event.address.as_slice(),
event.event_signature.as_slice(),
DATA_PREFIX,
&[j as u8 + 1],
]
.concat()
.into_iter()
.map(GFp::from_canonical_u8)
.collect::<Vec<GFp>>();
(
format!("{}_{}", DATA_NAME, j + 1),
H::hash_no_pad(&input).elements[0],
)
})
.collect::<Vec<(String, GFp)>>();

[
vec![
(LOG_NUMBER_NAME.to_string(), log_number_column_id),
(GAS_USED_NAME.to_string(), gas_used_column_id),
],
topic_ids,
data_ids,
]
.concat()
}
105 changes: 105 additions & 0 deletions mp2-v1/test-contracts/src/Event.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract EventEmitter {
uint256 public number;
event noIndexed();
event oneIndexed(uint256 indexed num);
event twoIndexed(uint256 indexed num, uint256 indexed numTwo);
event threeIndexed(
uint256 indexed num,
uint256 indexed numTwo,
uint256 indexed numThree
);
event oneData(
uint256 indexed num,
uint256 indexed numTwo,
uint256 indexed numThree,
uint256 numFour
);
event twoData(
uint256 indexed num,
uint256 indexed numTwo,
uint256 indexed numThree,
uint256 numFour,
uint256 numFive
);
event noIOneD(uint256 num);
event noITwoD(uint256 num, uint256 numTwo);
event oneIOneD(uint256 indexed num, uint256 numTwo);
event oneITwoD(uint256 indexed num, uint256 numTwo, uint256 numThree);
event twoIOneD(
uint256 indexed num,
uint256 indexed numTwo,
uint256 numThree
);
event twoITwoD(
uint256 indexed num,
uint256 indexed numTwo,
uint256 numThree,
uint256 numFour
);

function testNoIndexed() public {
emit noIndexed();
}

function testOneIndexed() public {
emit oneIndexed(number);
increment();
}

function testTwoIndexed() public {
emit twoIndexed(number, number + 1);
increment();
}

function testThreeIndexed() public {
emit threeIndexed(number, number + 1, number + 2);
increment();
}

function testOneData() public {
emit oneData(number, number + 1, number + 2, number + 3);
increment();
}

function testTwoData() public {
emit twoData(number, number + 1, number + 2, number + 3, number + 4);
increment();
}

function testNoIOneD() public {
emit noIOneD(number);
increment();
}

function testNoITwoD() public {
emit noITwoD(number, number + 1);
increment();
}

function testOneIOneD() public {
emit oneIOneD(number, number + 1);
increment();
}

function testOneITwoD() public {
emit oneITwoD(number, number + 1, number + 2);
increment();
}

function testTwoIOneD() public {
emit twoIOneD(number, number + 1, number + 2);
increment();
}

function testTwoITwoD() public {
emit twoITwoD(number, number + 1, number + 2, number + 3);
increment();
}

function increment() public {
number++;
}
}
Loading