Skip to content
Open
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,6 @@ lint/tmp/
gas-report.txt

contracts/test/fuzzing/crytic-export
temp
temp

yarn.lock
170 changes: 144 additions & 26 deletions contracts/DealStatus.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,39 @@ pragma solidity ^0.8.17;
// import "hardhat/console.sol";

import "./interfaces/IAggregatorOracle.sol";
import "./data-segment/Proof.sol";
import {Proof} from "./data-segment/Proof.sol";
import {MarketTypes} from "@zondax/filecoin-solidity/contracts/v0.8/types/MarketTypes.sol";
import {MarketAPI} from "@zondax/filecoin-solidity/contracts/v0.8/MarketAPI.sol";
import {CommonTypes} from "@zondax/filecoin-solidity/contracts/v0.8/types/CommonTypes.sol";

// Delta that implements the AggregatorOracle interface
contract DealStatus is IAggregatorOracle, Proof {
///////////////////
// State Variables
///////////////////

uint256 private transactionId;
mapping(uint256 => bytes) private txIdToCid;
mapping(bytes => Deal[]) private cidToDeals;

///////////////////
// Functions
///////////////////

//constructor
constructor() {
transactionId = 0;
}

// external functions

/**
* @notice Submits a new transaction with the given content identifier.
* @dev Increments the transaction ID, saves the content identifier, and emits a SubmitAggregatorRequest event.
* @param _cid The content identifier for the new transaction.
* @return The ID of the newly created transaction.
*/

function submit(bytes memory _cid) external returns (uint256) {
// Increment the transaction ID
transactionId++;
Expand All @@ -29,11 +50,21 @@ contract DealStatus is IAggregatorOracle, Proof {
return transactionId;
}

/**
* @notice Submits a new transaction with the given content identifier and RaaS parameters.
* @dev Increments the transaction ID, saves the content identifier, and emits a SubmitAggregatorRequestWithRaaS event.
* @param _cid The content identifier for the new transaction.
* @param _replication_target The number of replications of data needed.
* @param _repair_threshold The threshold to repair the deal if miner faults.
* @param _renew_threshold The threshold to renew the deal.
* @return The ID of the newly created transaction.
*/

function submitRaaS(
bytes memory _cid,
uint256 _replication_target,
uint256 _replication_target,
uint256 _repair_threshold,
uint256 _renew_threshold
uint256 _renew_threshold
) external returns (uint256) {
// Increment the transaction ID
transactionId++;
Expand All @@ -42,10 +73,27 @@ contract DealStatus is IAggregatorOracle, Proof {
txIdToCid[transactionId] = _cid;

// Emit the event
emit SubmitAggregatorRequestWithRaaS(transactionId, _cid, _replication_target, _repair_threshold, _renew_threshold);
emit SubmitAggregatorRequestWithRaaS(
transactionId,
_cid,
_replication_target,
_repair_threshold,
_renew_threshold
);
return transactionId;
}

/**
* @notice Completes a transaction with the given transaction ID, deal ID, miner ID, inclusion proof, and inclusion verifier data.
* @dev Emits a CompleteAggregatorRequest event.
* @param _id The ID of the transaction to complete.
* @param _dealId The ID of the deal to complete.
* @param _minerId The ID of the miner that completed the deal.
* @param _proof The inclusion proof for the transaction.
* @param _verifierData The inclusion verifier data for the transaction.
* @return The inclusion auxiliary data proof for the given file proof and verifier data.
*/

function complete(
uint256 _id,
uint64 _dealId,
Expand All @@ -61,7 +109,7 @@ contract DealStatus is IAggregatorOracle, Proof {
bytes memory cid = txIdToCid[_id];
for (uint256 i = 0; i < cidToDeals[cid].length; i++) {
if (cidToDeals[cid][i].dealId == _dealId) {
return this.computeExpectedAuxData(_proof, _verifierData);
return computeExpectedAuxData(_proof, _verifierData);
}
}

Expand All @@ -70,43 +118,48 @@ contract DealStatus is IAggregatorOracle, Proof {

// Perform validation logic
// return this.computeExpectedAuxDataWithDeal(_dealId, _proof, _verifierData);
return this.computeExpectedAuxData(_proof, _verifierData);
return computeExpectedAuxData(_proof, _verifierData);
}

// allDealIds should return all the deal ids created by the aggregator
function getAllDeals(bytes memory _cid) external view returns (Deal[] memory) {
return cidToDeals[_cid];
}
// View functions

function getAllCIDs() external view returns (bytes[] memory) {
bytes[] memory cids = new bytes[](transactionId);
for (uint256 i = 0; i < transactionId; i++) {
cids[i] = txIdToCid[i + 1];
}
return cids;
}
/**
* @notice Retrieves all active deals associated with a given content identifier.
* @dev Iterates through all deals associated with the content identifier, checks their activation and termination status, and removes any inactive deals from the returned array.
* @param _cid The content identifier for which to retrieve active deals.
* @return An array of Deal structs representing all active deals associated with the given content identifier.
*/

// getActiveDeals should return all the _cid's active dealIds
function getActiveDeals(bytes memory _cid) external returns (Deal[] memory) {
function getActiveDeals(bytes memory _cid) external view returns (Deal[] memory) {
// get all the deal ids for the cid
Deal[] memory activeDealIds;
activeDealIds = this.getAllDeals(_cid);

for (uint256 i = 0; i < activeDealIds.length; i++) {
uint64 dealID = activeDealIds[i].dealId;
// get the deal's expiration epoch
MarketTypes.GetDealActivationReturn memory dealActivationStatus = MarketAPI.getDealActivation(dealID);
(int64 activated, int64 terminated) = this.getDealActivationData(dealID);

if (dealActivationStatus.terminated > 0 || dealActivationStatus.activated == -1) {
if (terminated > 0 || activated == -1) {
delete activeDealIds[i];
}
}

return activeDealIds;
}

// getExpiringDeals should return all the deals' dealIds if they are expiring within `epochs`
function getExpiringDeals(bytes memory _cid, uint64 epochs) external returns (Deal[] memory) {
/**
* @notice Retrieves all expiring deals associated with a given content identifier.
* @dev Iterates through all deals associated with the content identifier, checks their expiration status, and removes any non-expiring deals from the returned array.
* @param _cid The content identifier for which to retrieve expiring deals.
* @param epochs The number of epochs before a deal's expiration to consider it expiring.
* @return An array of Deal structs representing all expiring deals associated with the given content identifier.
*/

function getExpiringDeals(
bytes memory _cid,
uint64 epochs
) external view returns (Deal[] memory) {
// the logic is similar to the above, but use this api call:
// https://github.com/Zondax/filecoin-solidity/blob/master/contracts/v0.8/MarketAPI.sol#LL110C9-L110C9
Deal[] memory expiringDealIds;
Expand All @@ -115,13 +168,78 @@ contract DealStatus is IAggregatorOracle, Proof {
for (uint256 i = 0; i < expiringDealIds.length; i++) {
uint64 dealId = expiringDealIds[i].dealId;
// get the deal's expiration epoch
MarketTypes.GetDealTermReturn memory dealTerm = MarketAPI.getDealTerm(dealId);

if (block.number < uint64(dealTerm.end) - epochs || block.number > uint64(dealTerm.end)) {
(int64 startEpoch, int64 duration) = this.getDealTermData(dealId);
if (
(block.number + epochs < uint64(startEpoch) + uint64(duration)) ||
(block.number > uint64(startEpoch) + uint64(duration))
) {
delete expiringDealIds[i];
}
}

return expiringDealIds;
}

//Getter Functions

/**
* @notice Retrieves the activation and termination data for a given deal.
* @dev Calls the MarketAPI to get the deal's activation status and then unwraps the activation and termination epochs.
* @param _dealId The ID of the deal for which to retrieve activation data.
* @return dealActivation The activation epoch of the deal or -1.
* @return dealTermination The termination epoch of the deal or -1.
*/

function getDealActivationData(
uint64 _dealId
) public view returns (int64 dealActivation, int64 dealTermination) {
MarketTypes.GetDealActivationReturn memory dealActivationStatus = MarketAPI
.getDealActivation(_dealId);
return (
CommonTypes.ChainEpoch.unwrap(dealActivationStatus.activated),
CommonTypes.ChainEpoch.unwrap(dealActivationStatus.terminated)
);
}

/**
* @notice Retrieves the start and end epochs for a given deal.
* @dev Calls the MarketAPI to get the deal's start and end epochs and then unwraps them.
* @param _dealId The ID of the deal for which to retrieve term data.
* @return startEpoch The start epoch of the deal.
* @return endEpoch The end epoch of the deal.
*/
function getDealTermData(
uint64 _dealId
) public view returns (int64 startEpoch, int64 endEpoch) {
MarketTypes.GetDealTermReturn memory dealTerm = MarketAPI.getDealTerm(_dealId);
return (
CommonTypes.ChainEpoch.unwrap(dealTerm.start),
CommonTypes.ChainEpoch.unwrap(dealTerm.end)
);
}

/**
* @notice Retrieves all deals associated with a given content identifier.
* @dev Returns the array of deals associated with the given content identifier.
* @param _cid The content identifier for which to retrieve deals.
* @return An array of Deal structs representing all deals associated with the given content identifier.
*/

function getAllDeals(bytes memory _cid) external view returns (Deal[] memory) {
return cidToDeals[_cid];
}

/**
* @notice Retrieves all content identifiers associated with the contract.
* @dev Returns the array of content identifiers associated with the aggregator.
* @return An array of bytes representing all content identifiers associated with the aggregator.
*/

function getAllCIDs() external view returns (bytes[] memory) {
bytes[] memory cids = new bytes[](transactionId);
for (uint256 i = 0; i < transactionId; i++) {
cids[i] = txIdToCid[i + 1];
}
return cids;
}
}
13 changes: 8 additions & 5 deletions contracts/data-segment/Cid.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import "./Const.sol";

library Cid {
// cidToPieceCommitment converts a CID to a piece commitment.
function cidToPieceCommitment(bytes memory _cb) public pure returns (bytes32) {
require(_cb.length == CID_COMMP_HEADER_LENGTH + MERKLE_TREE_NODE_SIZE, "wrong length of CID");
function cidToPieceCommitment(bytes memory _cb) internal pure returns (bytes32) {
require(
keccak256(abi.encodePacked(_cb[0], _cb[1], _cb[2], _cb[3], _cb[4], _cb[5], _cb[6]))
== keccak256(abi.encodePacked(CID_COMMP_HEADER)),
_cb.length == CID_COMMP_HEADER_LENGTH + MERKLE_TREE_NODE_SIZE,
"wrong length of CID"
);
require(
keccak256(abi.encodePacked(_cb[0], _cb[1], _cb[2], _cb[3], _cb[4], _cb[5], _cb[6])) ==
keccak256(abi.encodePacked(CID_COMMP_HEADER)),
"wrong content of CID header"
);
bytes32 res;
Expand All @@ -22,7 +25,7 @@ library Cid {
}

// pieceCommitmentToCid converts a piece commitment to a CID.
function pieceCommitmentToCid(bytes32 _commp) public pure returns (bytes memory) {
function pieceCommitmentToCid(bytes32 _commp) internal pure returns (bytes memory) {
bytes memory cb = abi.encodePacked(CID_COMMP_HEADER, _commp);
return cb;
}
Expand Down
Loading