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 generic extraction mapping of mappings to integration test (part 5, last part of generic extraction) #404

Open
wants to merge 8 commits into
base: generic-extraction-integration-test
Choose a base branch
from
66 changes: 34 additions & 32 deletions mp2-common/src/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,38 +532,40 @@ mod test {
Ok(())
}

#[tokio::test]
async fn test_pidgy_pinguin_mapping_slot() -> Result<()> {
// first pinguin holder https://dune.com/queries/2450476/4027653
// holder: 0x188b264aa1456b869c3a92eeed32117ebb835f47
// NFT id https://opensea.io/assets/ethereum/0xbd3531da5cf5857e7cfaa92426877b022e612cf8/1116
let mapping_value =
Address::from_str("0x188B264AA1456B869C3a92eeeD32117EbB835f47").unwrap();
let nft_id: u32 = 1116;
let mapping_key = left_pad32(&nft_id.to_be_bytes());
let url = get_mainnet_url();
let provider = ProviderBuilder::new().on_http(url.parse().unwrap());

// extracting from
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol
// assuming it's using ERC731Enumerable that inherits ERC721
let mapping_slot = 2;
// pudgy pinguins
let pudgy_address = Address::from_str("0xBd3531dA5CF5857e7CfAA92426877b022e612cf8")?;
let query = ProofQuery::new_mapping_slot(pudgy_address, mapping_slot, mapping_key.to_vec());
let res = query
.query_mpt_proof(&provider, BlockNumberOrTag::Latest)
.await?;
let raw_address = ProofQuery::verify_storage_proof(&res)?;
// the value is actually RLP encoded !
let decoded_address: Vec<u8> = rlp::decode(&raw_address).unwrap();
let leaf_node: Vec<Vec<u8>> = rlp::decode_list(res.storage_proof[0].proof.last().unwrap());
println!("leaf_node[1].len() = {}", leaf_node[1].len());
// this is read in the same order
let found_address = Address::from_slice(&decoded_address.into_iter().collect::<Vec<u8>>());
assert_eq!(found_address, mapping_value);
Ok(())
}
/* TODO: Need to update, since the mapping slot value is updated.
Copy link
Contributor

@nicholas-mainardi nicholas-mainardi Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this test, I placed the new value in PR #415 I am working on, you can just copy the new address from the changes to eth.rs in that PR and re-enable the test ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 5719de9, thanks.

#[tokio::test]
async fn test_pidgy_pinguin_mapping_slot() -> Result<()> {
// first pinguin holder https://dune.com/queries/2450476/4027653
// holder: 0x188b264aa1456b869c3a92eeed32117ebb835f47
// NFT id https://opensea.io/assets/ethereum/0xbd3531da5cf5857e7cfaa92426877b022e612cf8/1116
let mapping_value =
Address::from_str("0x188B264AA1456B869C3a92eeeD32117EbB835f47").unwrap();
let nft_id: u32 = 1116;
let mapping_key = left_pad32(&nft_id.to_be_bytes());
let url = get_mainnet_url();
let provider = ProviderBuilder::new().on_http(url.parse().unwrap());

// extracting from
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol
// assuming it's using ERC731Enumerable that inherits ERC721
let mapping_slot = 2;
// pudgy pinguins
let pudgy_address = Address::from_str("0xBd3531dA5CF5857e7CfAA92426877b022e612cf8")?;
let query = ProofQuery::new_mapping_slot(pudgy_address, mapping_slot, mapping_key.to_vec());
let res = query
.query_mpt_proof(&provider, BlockNumberOrTag::Latest)
.await?;
let raw_address = ProofQuery::verify_storage_proof(&res)?;
// the value is actually RLP encoded !
let decoded_address: Vec<u8> = rlp::decode(&raw_address).unwrap();
let leaf_node: Vec<Vec<u8>> = rlp::decode_list(res.storage_proof[0].proof.last().unwrap());
println!("leaf_node[1].len() = {}", leaf_node[1].len());
// this is read in the same order
let found_address = Address::from_slice(&decoded_address.into_iter().collect::<Vec<u8>>());
assert_eq!(found_address, mapping_value);
Ok(())
}
*/

#[tokio::test]
async fn test_kashish_contract_proof_query() -> Result<()> {
Expand Down
67 changes: 1 addition & 66 deletions mp2-common/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -773,33 +773,9 @@ impl<F: RichField + Extendable<D>, const D: usize> SliceConnector for CircuitBui
}
}

/// Convert an Uint32 target to Uint8 targets.
pub(crate) fn unpack_u32_to_u8_targets<F: RichField + Extendable<D>, const D: usize>(
b: &mut CircuitBuilder<F, D>,
u: Target,
endianness: Endianness,
) -> Vec<Target> {
let zero = b.zero();
let mut bits = b.split_le(u, u32::BITS as usize);
match endianness {
Endianness::Big => bits.reverse(),
Endianness::Little => (),
};
bits.chunks(8)
.map(|chunk| {
// let bits: Box<dyn Iterator<Item = &BoolTarget>> = match endianness {
let bits: Box<dyn Iterator<Item = _>> = match endianness {
Endianness::Big => Box::new(chunk.iter()),
Endianness::Little => Box::new(chunk.iter().rev()),
};
bits.fold(zero, |acc, bit| b.mul_const_add(F::TWO, acc, bit.target))
})
.collect()
}

#[cfg(test)]
mod test {
use super::{bits_to_num, unpack_u32_to_u8_targets, Packer, TargetsConnector, ToFields};
use super::{bits_to_num, Packer, TargetsConnector, ToFields};
use crate::types::CBuilder;
use crate::utils::{
greater_than, greater_than_or_equal_to, less_than, less_than_or_equal_to, num_to_bits,
Expand Down Expand Up @@ -1033,45 +1009,4 @@ mod test {
let proof = data.prove(pw)?;
data.verify(proof)
}

#[test]
fn test_unpack_u32_to_u8_targets() -> Result<()> {
let rng = &mut thread_rng();
let u32_value: u32 = rng.gen();
let big_endian_u8_values = u32_value.to_be_bytes().to_fields();
let little_endian_u8_values = u32_value.to_le_bytes().to_fields();

let config = default_config();
let mut builder = CBuilder::new(config);
let b = &mut builder;

let [exp_big_endian_u8_targets, exp_little_endian_u8_targets] =
array::from_fn(|_| b.add_virtual_target_arr::<4>());

let u32_target = b.constant(F::from_canonical_u32(u32_value));
let real_big_endian_u8_targets = unpack_u32_to_u8_targets(b, u32_target, Endianness::Big);
let real_little_endian_u8_targets =
unpack_u32_to_u8_targets(b, u32_target, Endianness::Little);

b.connect_targets(
real_big_endian_u8_targets,
exp_big_endian_u8_targets.to_vec(),
);
b.connect_targets(
real_little_endian_u8_targets,
exp_little_endian_u8_targets.to_vec(),
);

let data = builder.build::<C>();
let mut pw = PartialWitness::new();
[
(big_endian_u8_values, exp_big_endian_u8_targets),
(little_endian_u8_values, exp_little_endian_u8_targets),
]
.into_iter()
.for_each(|(values, targets)| pw.set_target_arr(&targets, &values));

let proof = data.prove(pw)?;
data.verify(proof)
}
}
2 changes: 1 addition & 1 deletion mp2-v1/src/values_extraction/leaf_mapping_of_mappings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ where
.collect();
let hash = b.hash_n_to_hash_no_pad::<CHasher>(inputs);
let row_id = hash_to_int_target(b, hash);
let row_id = b.biguint_to_nonnative(&row_id);

// values_digest = values_digest * row_id
let row_id = b.biguint_to_nonnative(&row_id);
let values_digest = b.curve_scalar_mul(values_digest, &row_id);

// Only one leaf in this node.
Expand Down
69 changes: 67 additions & 2 deletions mp2-v1/test-contracts/src/Simple.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ contract Simple {
MappingOperation operation;
}

struct MappingOfSingleValueMappingsChange {
uint256 outerKey;
uint256 innerKey;
uint256 value;
MappingOperation operation;
}

struct MappingOfStructMappingsChange {
uint256 outerKey;
uint256 innerKey;
uint256 field1;
uint128 field2;
uint128 field3;
MappingOperation operation;
}

struct LargeStruct {
// This field should live in one EVM word
uint256 field1;
Expand All @@ -48,9 +64,13 @@ contract Simple {
// Test mapping struct (slot 8)
mapping(uint256 => LargeStruct) public structMapping;

// Test mapping of mappings (slot 9)
// Test mapping of single value mappings (slot 9)
mapping(uint256 => mapping(uint256 => uint256))
public mappingOfSingleValueMappings;

// Test mapping of struct mappings (slot 10)
mapping(uint256 => mapping(uint256 => LargeStruct))
public mappingOfMappings;
public mappingOfStructMappings;

// Set the simple slots.
function setSimples(
Expand Down Expand Up @@ -125,4 +145,49 @@ contract Simple {
}
}

// Set mapping of single value mappings.
function setMappingOfSingleValueMappings(
uint256 outerKey,
uint256 innerKey,
uint256 value
) public {
mappingOfSingleValueMappings[outerKey][innerKey] = value;
}

function changeMappingOfSingleValueMappings(MappingOfSingleValueMappingsChange[] memory changes) public {
for (uint256 i = 0; i < changes.length; i++) {
if (changes[i].operation == MappingOperation.Deletion) {
delete mappingOfSingleValueMappings[changes[i].outerKey][changes[i].innerKey];
} else if (
changes[i].operation == MappingOperation.Insertion ||
changes[i].operation == MappingOperation.Update
) {
setMappingOfSingleValueMappings(changes[i].outerKey, changes[i].innerKey, changes[i].value);
}
}
}

// Set mapping of struct mappings.
function setMappingOfStructMappings(
uint256 outerKey,
uint256 innerKey,
uint256 field1,
uint128 field2,
uint128 field3
) public {
mappingOfStructMappings[outerKey][innerKey] = LargeStruct(field1, field2, field3);
}

function changeMappingOfStructMappings(MappingOfStructMappingsChange[] memory changes) public {
for (uint256 i = 0; i < changes.length; i++) {
if (changes[i].operation == MappingOperation.Deletion) {
delete mappingOfStructMappings[changes[i].outerKey][changes[i].innerKey];
} else if (
changes[i].operation == MappingOperation.Insertion ||
changes[i].operation == MappingOperation.Update
) {
setMappingOfStructMappings(changes[i].outerKey, changes[i].innerKey, changes[i].field1, changes[i].field2, changes[i].field3);
}
}
}
}
Loading
Loading