add clearing of host slots with MAX_SLOTS boundary

This commit is contained in:
Eric Mastro 2022-12-05 17:25:21 +11:00
parent 641892ccfa
commit 2aa50eabbf
No known key found for this signature in database
GPG Key ID: 141E3048D95A4E63
2 changed files with 43 additions and 9 deletions

View File

@ -11,11 +11,13 @@ import "./libs/DAL.sol";
contract Marketplace is Collateral, Proofs {
using DAL for DAL.Database;
using EnumerableSet for EnumerableSet.Bytes32Set;
using DAL for EnumerableSet.Bytes32Set;
uint256 public immutable collateral;
MarketplaceFunds private funds;
mapping(DAL.RequestId => RequestContext) private requestContexts;
DAL.Database private db;
uint16 private constant MAX_SLOTS = 256;
constructor(
IERC20 _token,
@ -45,6 +47,8 @@ contract Marketplace is Collateral, Proofs {
public
marketplaceInvariant
{
require(request.ask.slots <= MAX_SLOTS, "Max slots exceeded");
require(request.ask.maxSlotLoss <= MAX_SLOTS, "Max slot loss exceeded");
require(request.client == msg.sender, "Invalid client address");
DAL.RequestId requestId = _toRequestId(request);
@ -152,7 +156,14 @@ contract Marketplace is Collateral, Proofs {
DAL.Client storage client = db.select(request.client);
db.remove(client.requests, requestId);
db.remove(host.requests, requestId);
// Remove all request's slots from hosts.slots. This is an expensive
// operation as it iterates all slots and removes them one-by-one.
// An alternative is to use EnumerableExtensions.ClearableBytes32Set
// for host.slots instead, however this would not free any storage
// but instead use a new EnumerableSet.Bytes32Set each time it is cleared.
db.clearSlots(host, requestId, MAX_SLOTS);
emit RequestFailed(requestId);
// TODO: burn all remaining slot collateral (note: slot collateral not

View File

@ -3,7 +3,6 @@
pragma solidity ^0.8.8;
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "../Marketplace.sol";
import "./Utils.sol";
library DAL {
@ -18,18 +17,18 @@ library DAL {
struct Client {
ClientId id; // PK
EnumerableSet.Bytes32Set requests;
EnumerableSet.Bytes32Set requests; // FKs
}
struct Host {
HostId id; // PK
EnumerableSet.Bytes32Set slots;
EnumerableSet.Bytes32Set requests;
EnumerableSet.Bytes32Set slots; // FKs
EnumerableSet.Bytes32Set requests; // FKs
}
struct Request {
RequestId id;
RequestId id; // PK
ClientId client;
Ask ask;
Content content;
@ -40,10 +39,10 @@ library DAL {
}
struct Slot {
SlotId id;
HostId host;
SlotId id; // PK
HostId host; // FK
bool hostPaid;
RequestId requestId;
RequestId requestId; // FK
}
struct Ask {
@ -246,6 +245,8 @@ library DAL {
Client storage client = db.clients[request.client];
bytes32 bRequestId = RequestId.unwrap(request.id);
require(!client.requests.contains(bRequestId), "active request refs");
// TODO: iterate all request's hosts and check that host.requests doesn't
// have requestId
delete db.requests[request.id];
}
@ -279,6 +280,8 @@ library DAL {
internal
{
require(exists(db, requestId), "request does not exist");
// TODO: check that host.slots doesn't have a slot belonging to the request
// being removed
requests.remove(RequestId.unwrap(requestId));
}
@ -293,6 +296,26 @@ library DAL {
slots.remove(SlotId.unwrap(slotId));
}
// WARNING: this may cause a transaction to run out of gas!
function clearSlots(Database storage db,
Host storage host,
RequestId requestId,
uint256 maxIterations)
internal
{
require(maxIterations > 0, "maxIterations must be > 0");
require(host.slots.length() <= maxIterations, "iterations out of bounds");
for (uint256 i = 0; i < host.slots.length(); i++) {
bytes32 slotId = host.slots.at(i);
Slot storage slot = select(db, SlotId.wrap(slotId));
if (equals(slot.requestId, requestId)) {
host.slots.remove(slotId);
}
}
remove(db, host.requests, requestId);
}
/// *** CALCULATED PROPERTIES *** ///