Created
October 12, 2024 10:54
-
-
Save magik6k/7e73a8603479d495870717cff0db00aa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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