Skip to content

Instantly share code, notes, and snippets.

@magik6k
Created October 12, 2024 10:54
Show Gist options
  • Save magik6k/7e73a8603479d495870717cff0db00aa to your computer and use it in GitHub Desktop.
Save magik6k/7e73a8603479d495870717cff0db00aa to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
// Import the PDPService and necessary libraries
import "./PDPService.sol";
import {BitOps} from "../src/BitOps.sol";
import {Cids} from "../src/Cids.sol";
import {MerkleVerify} from "../src/Proofs.sol";
import {Hashes} from "../src/Proofs.sol"; // Assuming Hashes is part of Proofs.sol
contract PDPServiceDebug {
PDPService public pdpService;
constructor(address _pdpService) {
pdpService = PDPService(_pdpService);
}
// Define events for debugging
event DebugProofStep(
uint256 proofIndex,
uint256 stepIndex,
bytes32 prevComputedHash,
bytes32 sibling,
bytes32 newComputedHash,
bool isLeft
);
event DebugEvent(string message);
event DebugData(string messageType, uint256 index, bytes data, uint256 value);
// Struct definitions
struct Proof {
bytes32 leaf;
bytes32[] proof;
}
struct RootIdAndOffset {
uint256 rootId;
uint256 offset;
}
struct ProofData {
bytes32[] proof;
bytes32 leaf;
uint256 position;
}
// Public function to perform debug proof of possession without modifying the PDPService contract
function provePossession(uint256 setId, Proof[] calldata proofs) public {
// Use public functions of PDPService to access data
if (!pdpService.proofSetLive(setId)) {
emit DebugEvent("Proof set not live");
return;
}
uint256 challengeEpoch = pdpService.getNextChallengeEpoch(setId);
if (block.number < challengeEpoch) {
emit DebugEvent("Premature proof");
return;
}
if (proofs.length == 0) {
emit DebugEvent("Empty proof");
return;
}
// TODO: fetch proper seed from chain randomness
uint256 seed = challengeEpoch;
uint256 leafCount = pdpService.getProofSetLeafCount(setId);
uint256 nextRootId = pdpService.getNextRootId(setId);
uint256 sumTreeTop = 256 - BitOps.clz(nextRootId);
bool allSuccess = true;
for (uint256 i = 0; i < proofs.length; i++) {
// Compute challenge and emit event
bytes memory payload = abi.encodePacked(seed, setId, i);
bytes32 challengeHash = keccak256(payload);
uint256 challengeIdx = uint256(challengeHash) % leafCount;
emit DebugData("Challenge", i, payload, challengeIdx);
// Find the root that has this leaf, and the offset of the leaf within that root.
RootIdAndOffset memory root = findOneRootId(setId, challengeIdx, sumTreeTop, nextRootId);
Cids.Cid memory rootCid = pdpService.getRootCid(setId, root.rootId);
bytes32 rootHash = Cids.digestFromCid(rootCid);
emit DebugData("Root", root.rootId, "", root.offset);
// Prepare parameters for debugProcessProofMemory
ProofData memory proofData = ProofData({
proof: proofs[i].proof,
leaf: proofs[i].leaf,
position: root.offset
});
// Process the proof step by step and emit events
bool success = debugProcessProofMemory(proofData, rootHash, i);
if (success) {
emit DebugEvent("Proof verified successfully");
} else {
emit DebugEvent("Proof failed to verify");
allSuccess = false;
}
}
if (allSuccess) {
// Since we cannot modify the state of PDPService, we cannot update the nextChallengeEpoch
// But we can emit an event indicating success
emit DebugEvent("All proofs verified successfully");
} else {
emit DebugEvent("Some proofs failed to verify");
}
}
// Helper function to process the proof and emit debug information
function debugProcessProofMemory(
ProofData memory proofData,
bytes32 root,
uint256 proofIndex
) internal returns (bool) {
bytes32 computedHash = proofData.leaf;
uint256 position = proofData.position;
for (uint256 i = 0; i < proofData.proof.length; i++) {
bytes32 sibling = proofData.proof[i];
bool isLeft = (position % 2 == 0);
bytes32 prevComputedHash = computedHash;
if (isLeft) {
computedHash = Hashes.orderedHash(computedHash, sibling);
} else {
computedHash = Hashes.orderedHash(sibling, computedHash);
}
emit DebugProofStep(proofIndex, i, prevComputedHash, sibling, computedHash, isLeft);
position /= 2;
}
bool success = (computedHash == root);
return success;
}
// Reimplementation of findOneRootId using public functions of PDPService
function findOneRootId(uint256 setId, uint256 leafIndex, uint256 top, uint256 nextRootId) internal view returns (RootIdAndOffset memory) {
uint256 leafCount = pdpService.getProofSetLeafCount(setId);
require(leafIndex < leafCount, "Leaf index out of bounds");
uint256 searchPtr = (1 << top) - 1;
uint256 acc = 0;
// Binary search until we find the index of the sumtree leaf covering the index range
uint256 candidate;
uint256 h = top;
while (h > 0) {
// Search has taken us past the end of the sumtree
// Only option is to go left
if (searchPtr >= nextRootId) {
searchPtr -= 1 << (h - 1);
h--;
continue;
}
// Since we cannot access sumTreeCounts, we need to reconstruct the counts
uint256 countAtPtr = getSumTreeCountAt(setId, searchPtr);
candidate = acc + countAtPtr;
// Go right
if (candidate <= leafIndex) {
acc += countAtPtr;
searchPtr += 1 << (h - 1);
} else {
// Go left
searchPtr -= 1 << (h - 1);
}
h--;
}
// Final check after the loop
uint256 countAtPtr = getSumTreeCountAt(setId, searchPtr);
candidate = acc + countAtPtr;
if (candidate <= leafIndex) {
// Choose right
return RootIdAndOffset(searchPtr + 1, leafIndex - candidate);
} // Choose left
return RootIdAndOffset(searchPtr, leafIndex - acc);
}
// Since we cannot access sumTreeCounts directly, we need to reconstruct the counts
// We can reconstruct the counts by summing rootLeafCounts
function getSumTreeCountAt(uint256 setId, uint256 index) internal view returns (uint256) {
// Reconstruct the count at a given index in the sum tree
// This is a simplified example and may need adjustment based on the actual implementation
// For now, we assume that sumTreeCounts[setId][index] == rootLeafCounts[setId][index]
// So we use pdpService.getRootLeafCount(setId, index)
if (index >= pdpService.getNextRootId(setId)) {
return 0;
}
uint256 count = pdpService.getRootLeafCount(setId, index);
return count;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment