diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index 3787d51..c973851 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -11,7 +11,6 @@ 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; diff --git a/contracts/libs/DAL.sol b/contracts/libs/DAL.sol index 8cc34a4..df87d1b 100644 --- a/contracts/libs/DAL.sol +++ b/contracts/libs/DAL.sol @@ -84,8 +84,8 @@ library DAL { function insert(Database storage db, RequestId requestId, ClientId clientId, - Ask memory ask, - Content memory content, + Ask calldata ask, + Content calldata content, uint256 expiry, bytes32 nonce) internal @@ -104,6 +104,18 @@ library DAL { r.nonce = nonce; } + function insert(Database storage db, Slot memory slot ) internal { + require(!_isDefault(slot.id), "slot id required"); + require(!isDefault(slot.requestId), "request id required"); + require(exists(db, slot.requestId), "request does not exist"); + require(!exists(db, slot.id), "slot already exists"); + require(exists(db, slot.host), "host does not exist"); + db.slots[slot.id] = slot; + + Request storage request = db.requests[slot.requestId]; + request.slots.add(SlotId.unwrap(slot.id)); + } + function insert(Database storage db, ClientId clientId) internal { require (!exists(db, clientId), "client already exists"); require (!_isDefault(clientId), "address required"); @@ -120,18 +132,6 @@ library DAL { // NOTE: by default db.hosts[host].slots already exists but has a default value } - function insert(Database storage db, Slot memory slot ) internal { - require(!_isDefault(slot.id), "slot id required"); - require(!isDefault(slot.requestId), "request id required"); - require(exists(db, slot.requestId), "request does not exist"); - require(!exists(db, slot.id), "slot already exists"); - require(exists(db, slot.host), "host does not exist"); - db.slots[slot.id] = slot; - - Request storage request = db.requests[slot.requestId]; - request.slots.add(SlotId.unwrap(slot.id)); - } - function insert(Database storage db, EnumerableSet.Bytes32Set storage requests, RequestId requestId) @@ -251,6 +251,17 @@ library DAL { delete db.requests[request.id]; } + function remove(Database storage db, Slot storage slot) internal { + require(exists(db, slot.requestId), "request does not exist"); + Host storage host = db.hosts[slot.host]; + bytes32 bSlotId = SlotId.unwrap(slot.id); + require(!host.slots.contains(bSlotId), "active slot refs"); + + Request storage request = db.requests[slot.requestId]; + request.slots.remove(bSlotId); + delete db.slots[slot.id]; + } + function remove(Database storage db, Client storage client) internal { require(client.requests.length() == 0, "active request refs"); @@ -263,17 +274,6 @@ library DAL { delete db.hosts[host.id]; } - function remove(Database storage db, Slot storage slot) internal { - require(exists(db, slot.requestId), "request does not exist"); - Host storage host = db.hosts[slot.host]; - bytes32 bSlotId = SlotId.unwrap(slot.id); - require(!host.slots.contains(bSlotId), "active slot refs"); - - Request storage request = db.requests[slot.requestId]; - request.slots.remove(bSlotId); - delete db.slots[slot.id]; - } - function remove(Database storage db, EnumerableSet.Bytes32Set storage requests, RequestId requestId) diff --git a/contracts/libs/TestDAL.sol b/contracts/libs/TestDAL.sol new file mode 100644 index 0000000..ebca1a1 --- /dev/null +++ b/contracts/libs/TestDAL.sol @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import "./DAL.sol"; + +// exposes public functions for testing +contract TestDAL { + using DAL for DAL.Database; + using EnumerableSet for EnumerableSet.Bytes32Set; + + event OperationResult(bool result); + + DAL.Database private _db; + + function insertRequest(DAL.RequestId requestId, + DAL.ClientId clientId, + DAL.Ask calldata ask, + DAL.Content calldata content, + uint256 expiry, + bytes32 nonce) + public + { + _db.insert(requestId, clientId, ask, content, expiry, nonce); + } + + function insertSlot(DAL.Slot memory slot) public { + _db.insert(slot); + } + + function insertClient(DAL.ClientId clientId) public { + _db.insert(clientId); + } + + function insertHost(DAL.HostId hostId) public { + _db.insert(hostId); + } + + function insertHostRequest(DAL.HostId hostId, + DAL.RequestId requestId) + public + { + DAL.Host storage host = _db.select(hostId); + _db.insert(host.requests, requestId); + } + + function insertClientRequest(DAL.ClientId clientId, + DAL.RequestId requestId) + public + { + DAL.Client storage client = _db.select(clientId); + _db.insert(client.requests, requestId); + } + + function insertHostSlot(DAL.HostId hostId, + DAL.SlotId slotId) + public + { + DAL.Host storage host = _db.select(hostId); + _db.insert(host.slots, slotId); + } + + function selectRequest(DAL.RequestId requestId) + public + view + returns (DAL.RequestId, + DAL.ClientId, + DAL.Ask memory, + DAL.Content memory, + uint256, + bytes32, + bytes32[] memory) + { + DAL.Request storage request = _db.select(requestId); + return (request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce, + request.slots.values()); + } + + function selectSlot(DAL.SlotId slotId) + public + view + returns (DAL.SlotId, DAL.HostId, bool, DAL.RequestId) + { + DAL.Slot storage slot = _db.select(slotId); + return (slot.id, slot.host, slot.hostPaid, slot.requestId); + } + + function selectClient(DAL.ClientId clientId) + public + view + returns (DAL.ClientId, bytes32[] memory) + { + DAL.Client storage client = _db.select(clientId); + return (client.id, client.requests.values()); + } + + function selectHost(DAL.HostId hostId) + public + view + returns (DAL.HostId, bytes32[] memory, bytes32[] memory) + { + DAL.Host storage host = _db.select(hostId); + return (host.id, host.slots.values(), host.requests.values()); + } + + function requestExists(DAL.RequestId requestId) + public + view + returns (bool) + { + return _db.exists(requestId); + } + + function slotExists(DAL.SlotId slotId) + public + view + returns (bool) + { + return _db.exists(slotId); + } + + function clientExists(DAL.ClientId clientId) + public + view + returns (bool) + { + return _db.exists(clientId); + } + + function hostExists(DAL.HostId hostId) + public + view + returns (bool) + { + return _db.exists(hostId); + } + + function removeRequest(DAL.RequestId requestId) public { + DAL.Request storage request = _db.select(requestId); + _db.remove(request); + } + + function removeSlot(DAL.SlotId slotId) public { + DAL.Slot storage slot = _db.select(slotId); + _db.remove(slot); + } + + function removeClient(DAL.ClientId clientId) public { + DAL.Client storage client = _db.select(clientId); + _db.remove(client); + } + + function removeHost(DAL.HostId hostId) public { + DAL.Host storage host = _db.select(hostId); + _db.remove(host); + } + + function removeClientRequest(DAL.ClientId clientId, + DAL.RequestId requestId) + public + { + DAL.Client storage client = _db.select(clientId); + _db.remove(client.requests, requestId); + } + + function removeHostRequest(DAL.HostId hostId, + DAL.RequestId requestId) + public + { + DAL.Host storage host = _db.select(hostId); + _db.remove(host.requests, requestId); + } + + function removeHostSlot(DAL.HostId hostId, + DAL.SlotId slotId) + public + { + DAL.Host storage host = _db.select(hostId); + _db.remove(host.slots, slotId); + } + + function clearSlots(DAL.HostId hostId, + DAL.RequestId requestId, + uint256 maxIterations) + public + { + DAL.Host storage host = _db.select(hostId); + _db.clearSlots(host, requestId, maxIterations); + } + + function activeSlots(DAL.HostId hostId) + public + view + returns (DAL.SlotId[] memory) + { + DAL.Host storage host = _db.select(hostId); + return _db.activeSlots(host); + } + + function toSlotId(DAL.RequestId requestId, uint256 slotIndex) + public + pure + returns (DAL.SlotId) + { + return toSlotId(requestId, slotIndex); + } +} diff --git a/test/DAL.test.js b/test/DAL.test.js new file mode 100644 index 0000000..c2a9264 --- /dev/null +++ b/test/DAL.test.js @@ -0,0 +1,600 @@ +const { ethers } = require("hardhat") +const { expect, Assertion } = require("chai") +const { hexlify, randomBytes } = ethers.utils +const { exampleAddress, exampleRequest, zeroBytesHex } = require("./examples") +const { slotId, requestId, requestToArray, askToArray } = require("./ids") +const { BigNumber } = ethers +const { supportDAL } = require("./dal") + +supportDAL(Assertion) + +describe("DAL", function () { + let account + let contract + let request + let slot + let host + let client + + describe("Database", function () { + beforeEach(async function () { + let DAL = await ethers.getContractFactory("TestDAL") + contract = await DAL.deploy() + ;[account] = await ethers.getSigners() + request = await exampleRequest() + request.id = requestId(request) + request.slots = [] + client = { + id: await exampleAddress(), + requests: [], + } + request.client = client.id + host = { + id: await exampleAddress(), + requests: [], + slots: [], + } + slot = { + id: slotId({ request: request.id, index: 0 }), + host: host.id, + hostPaid: false, + requestId: request.id, + } + }) + + describe("Create: successful", function () { + it("inserts a request", async function () { + await expect(await contract.requestExists(request.id)).to.be.false + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await expect(await contract.requestExists(request.id)).to.be.true + }) + + it("inserts a slot", async function () { + await expect(await contract.slotExists(slot.id)).to.be.false + await contract.insertClient(client.id) + await contract.insertHost(host.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertSlot(slot) + await expect(await contract.slotExists(slot.id)).to.be.true + }) + + it("inserts a client", async function () { + await expect(await contract.clientExists(client.id)).to.be.false + await contract.insertClient(client.id) + await expect(await contract.clientExists(client.id)).to.be.true + }) + + it("inserts a host", async function () { + await expect(await contract.hostExists(host.id)).to.be.false + await contract.insertHost(host.id) + await expect(await contract.hostExists(host.id)).to.be.true + }) + + it("inserts a host request", async function () { + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertHost(host.id) + await contract.insertHostRequest(host.id, request.id) + let [id, slots, requests] = await contract.selectHost(host.id) + await expect(requests.includes(request.id)).to.be.true + }) + + it("inserts a client request", async function () { + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertClientRequest(client.id, request.id) + let [id, requests] = await contract.selectClient(client.id) + await expect(requests.includes(request.id)).to.be.true + }) + + it("inserts a host slot", async function () { + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertHost(host.id) + await contract.insertHostRequest(host.id, request.id) + await contract.insertSlot(slot) + await contract.insertHostSlot(host.id, slot.id) + let [id, slots, requests] = await contract.selectHost(host.id) + await expect(slots.includes(slot.id)).to.be.true + }) + }) + + describe("Create: failure", function () { + it("fails to insert a request when request id not provided", async function () { + await expect(await contract.requestExists(request.id)).to.be.false + await expect( + contract.insertRequest( + zeroBytesHex(32), + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + ).to.be.revertedWith("request id required") + }) + it("fails to insert a request when client id (address) not provided", async function () { + await expect(await contract.requestExists(request.id)).to.be.false + await expect( + contract.insertRequest( + request.id, + zeroBytesHex(20), + request.ask, + request.content, + request.expiry, + request.nonce + ) + ).to.be.revertedWith("client address required") + }) + it("fails to insert a request when client doesn't exist", async function () { + await expect(await contract.requestExists(request.id)).to.be.false + await expect( + contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + ).to.be.revertedWith("client does not exist") + }) + it("fails to insert a request when request already exists", async function () { + await expect(await contract.requestExists(request.id)).to.be.false + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await expect( + contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + ).to.be.revertedWith("request already exists") + }) + it("fails to insert a slot when slot id not provided", async function () { + await expect(await contract.requestExists(request.id)).to.be.false + slot.id = zeroBytesHex(32) + await expect(contract.insertSlot(slot)).to.be.revertedWith( + "slot id required" + ) + }) + it("fails to insert a slot when request id not provided", async function () { + await expect(await contract.requestExists(request.id)).to.be.false + slot.requestId = zeroBytesHex(32) + await expect(contract.insertSlot(slot)).to.be.revertedWith( + "request id required" + ) + }) + it("fails to insert a slot when request id not provided", async function () { + await expect(await contract.requestExists(request.id)).to.be.false + slot.requestId = zeroBytesHex(32) + await expect(contract.insertSlot(slot)).to.be.revertedWith( + "request id required" + ) + }) + it("fails to insert a slot when request doesn't exist", async function () { + await expect(await contract.requestExists(request.id)).to.be.false + await expect(contract.insertSlot(slot)).to.be.revertedWith( + "request does not exist" + ) + }) + it("fails to insert a slot when the slot already exists", async function () { + await expect(await contract.requestExists(request.id)).to.be.false + await contract.insertClient(client.id) + await contract.insertHost(host.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertSlot(slot) + await expect(contract.insertSlot(slot)).to.be.revertedWith( + "slot already exists" + ) + }) + it("fails to insert a slot when the host does not exist", async function () { + await expect(await contract.requestExists(request.id)).to.be.false + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await expect(contract.insertSlot(slot)).to.be.revertedWith( + "host does not exist" + ) + }) + it("fails to insert a client when the client already exists", async function () { + await contract.insertClient(client.id) + await expect(contract.insertClient(client.id)).to.be.revertedWith( + "client already exists" + ) + }) + it("fails to insert a client when the address wasn't provided", async function () { + client.id = zeroBytesHex(20) + await expect(contract.insertClient(client.id)).to.be.revertedWith( + "address required" + ) + }) + it("fails to insert a host when the host already exists", async function () { + await contract.insertHost(host.id) + await expect(contract.insertHost(host.id)).to.be.revertedWith( + "host already exists" + ) + }) + it("fails to insert a host when the address wasn't provided", async function () { + host.id = zeroBytesHex(20) + await expect(contract.insertHost(host.id)).to.be.revertedWith( + "address required" + ) + }) + it("fails to insert a host request when request doesn't exist", async function () { + await contract.insertHost(host.id) + await expect( + contract.insertHostRequest(host.id, request.id) + ).to.be.revertedWith("request does not exist") + }) + it("fails to insert a client request when request doesn't exist", async function () { + await contract.insertClient(client.id) + await expect( + contract.insertClientRequest(client.id, request.id) + ).to.be.revertedWith("request does not exist") + }) + + it("fails to insert a host slot when slot doesn't exist", async function () { + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertHost(host.id) + await expect( + contract.insertHostSlot(host.id, slot.id) + ).to.be.revertedWith("slot does not exist") + }) + + it("fails to insert a host slot when host doesn't exist", async function () { + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await expect( + contract.insertHostSlot(host.id, slot.id) + ).to.be.revertedWith("Host does not exist") + }) + + it("fails to insert a host slot when the host request doesn't exist", async function () { + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertHost(host.id) + await contract.insertSlot(slot) + await expect( + contract.insertHostSlot(host.id, slot.id) + ).to.be.revertedWith("slot request not active") + }) + }) + + describe("Read: success", function () { + it("selects a request", async function () { + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await expect(await contract.selectRequest(request.id)).to.equalsRequest( + request + ) + }) + it("selects a slot", async function () { + await contract.insertClient(client.id) + await contract.insertHost(host.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertSlot(slot) + await expect(await contract.selectSlot(slot.id)).to.equalsSlot(slot) + }) + it("selects a client", async function () { + await contract.insertClient(client.id) + await expect(await contract.selectClient(client.id)).to.be.equalsClient( + client + ) + }) + it("selects a host", async function () { + await contract.insertHost(host.id) + await expect(await contract.selectHost(host.id)).to.be.equalsHost(host) + }) + }) + + describe("Read: failure", function () { + it("fails to select a request when request doesn't exist", async function () { + await expect(contract.selectRequest(request.id)).to.be.revertedWith( + "Unknown request" + ) + }) + it("fails to select a slot when slot is empty", async function () { + await expect(contract.selectSlot(slot.id)).to.be.revertedWith( + "Slot empty" + ) + }) + it("fails to select a client when client doesn't exist", async function () { + await expect(contract.selectClient(client.id)).to.be.revertedWith( + "Client does not exist" + ) + }) + it("fails to select a host when host doesn't exist", async function () { + await expect(contract.selectHost(host.id)).to.be.revertedWith( + "Host does not exist" + ) + }) + }) + + describe("Delete: success", function () { + it("deletes a request", async function () { + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.removeRequest(request.id) + await expect(contract.selectRequest(request.id)).to.be.revertedWith( + "Unknown request" + ) + }) + it("deletes a slot", async function () { + await contract.insertClient(client.id) + await contract.insertHost(host.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertSlot(slot) + await contract.removeSlot(slot.id) + await expect(contract.selectSlot(slot.id)).to.be.revertedWith( + "Slot empty" + ) + }) + it("deletes a client", async function () { + await contract.insertClient(client.id) + await contract.removeClient(client.id) + await expect(contract.selectClient(client.id)).to.be.revertedWith( + "Client does not exist" + ) + }) + it("deletes a host", async function () { + await contract.insertHost(host.id) + await contract.removeHost(host.id) + await expect(contract.selectHost(host.id)).to.be.revertedWith( + "Host does not exist" + ) + }) + it("deletes a client request", async function () { + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertClientRequest(client.id, request.id) + let [id, requests] = await contract.selectClient(client.id) + await expect(requests.length).to.equal(1) + await contract.removeClientRequest(client.id, request.id) + ;[id, requests] = await contract.selectClient(client.id) + await expect(requests.length).to.equal(0) + }) + it("deletes a host request", async function () { + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertHost(host.id) + await contract.insertHostRequest(host.id, request.id) + let [id, slots, requests] = await contract.selectHost(host.id) + await expect(requests.length).to.equal(1) + await contract.removeHostRequest(host.id, request.id) + ;[id, slots, requests] = await contract.selectHost(host.id) + await expect(requests.length).to.equal(0) + }) + it("deletes a host slot", async function () { + await contract.insertClient(client.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertHost(host.id) + await contract.insertHostRequest(host.id, request.id) + await contract.insertSlot(slot) + await contract.insertHostSlot(host.id, slot.id) + let [id, slots, requests] = await contract.selectHost(host.id) + await expect(slots.length).to.equal(1) + await contract.removeHostSlot(host.id, slot.id) + ;[id, slots, requests] = await contract.selectHost(host.id) + await expect(slots.length).to.equal(0) + }) + }) + + describe("Delete: failure", function () { + it("fails to delete a request when it references slots", async function () { + await contract.insertClient(client.id) + await contract.insertHost(host.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertSlot(slot) + await expect(contract.removeRequest(request.id)).to.be.revertedWith( + "references slots" + ) + }) + it("fails to delete a request when its client has request references", async function () { + await contract.insertClient(client.id) + await contract.insertHost(host.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertClientRequest(client.id, request.id) + await expect(contract.removeRequest(request.id)).to.be.revertedWith( + "active request refs" + ) + }) + it("fails to delete a client when it has request references", async function () { + await contract.insertClient(client.id) + await contract.insertHost(host.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertClientRequest(client.id, request.id) + await expect(contract.removeClient(client.id)).to.be.revertedWith( + "active request refs" + ) + }) + it("fails to delete a request when its host has slot references", async function () { + await contract.insertClient(client.id) + await contract.insertHost(host.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertSlot(slot) + await contract.insertHostRequest(host.id, request.id) + await contract.insertHostSlot(host.id, slot.id) + await expect(contract.removeSlot(slot.id)).to.be.revertedWith( + "active slot refs" + ) + }) + it("fails to delete a host when it has slot references", async function () { + await contract.insertClient(client.id) + await contract.insertHost(host.id) + await contract.insertRequest( + request.id, + request.client, + request.ask, + request.content, + request.expiry, + request.nonce + ) + await contract.insertSlot(slot) + await contract.insertHostRequest(host.id, request.id) + await contract.insertHostSlot(host.id, slot.id) + await expect(contract.removeHost(host.id)).to.be.revertedWith( + "active slot refs" + ) + }) + }) + }) +}) diff --git a/test/dal.js b/test/dal.js new file mode 100644 index 0000000..085feb6 --- /dev/null +++ b/test/dal.js @@ -0,0 +1,111 @@ +const { BigNumber } = require("ethers") +const { hexlify } = ethers.utils + +function isBigNumberish(bn) { + return bn._isBigNumber === true +} + +function normalizeBn(bn) { + return isBigNumberish(bn) ? bn.toNumber() : bn +} + +function supportDAL(Assertion) { + Assertion.addMethod("equalsRequest", function (request) { + const evmRequest = requestFromArray(this._obj) + request.content.por.u = hexlify(request.content.por.u) + request.content.por.publicKey = hexlify(request.content.por.publicKey) + request.content.por.name = hexlify(request.content.por.name) + new Assertion(evmRequest).to.deep.equal(request) + }) + Assertion.addMethod("equalsSlot", function (slot) { + const evmSlot = slotFromArray(this._obj) + new Assertion(evmSlot).to.deep.equal(slot) + }) + Assertion.addMethod("equalsClient", function (client) { + const evmClient = clientFromArray(this._obj) + new Assertion(evmClient).to.deep.equal(client) + }) + Assertion.addMethod("equalsHost", function (host) { + const evmHost = hostFromArray(this._obj) + new Assertion(evmHost).to.deep.equal(host) + }) +} + +function parse(keys, object) { + let obj = {} + keys.forEach((key, i) => (obj[key] = normalizeBn(object[i]))) + return obj +} + +function porFromArray(por) { + return { + u: por.u, + publicKey: por.publicKey, + name: por.name, + } +} + +function erasureFromArray(erasure) { + return { + totalChunks: normalizeBn(erasure.totalChunks), + } +} + +function contentFromArray(ask) { + return { + cid: ask.cid, + erasure: erasureFromArray(ask.erasure), + por: porFromArray(ask.por), + } +} + +function askFromArray(ask) { + return { + slots: normalizeBn(ask.slots), + slotSize: normalizeBn(ask.slotSize), + duration: normalizeBn(ask.duration), + proofProbability: normalizeBn(ask.proofProbability), + reward: normalizeBn(ask.reward), + maxSlotLoss: normalizeBn(ask.maxSlotLoss), + } +} + +function requestFromArray(request) { + return { + id: request[0], + client: request[1], + ask: askFromArray(request[2]), + content: contentFromArray(request[3]), + expiry: normalizeBn(request[4]), + nonce: request[5], + slots: normalizeBn(request[6]), + } +} + +function slotFromArray(slot) { + return { + id: slot[0], + host: slot[1], + hostPaid: slot[2], + requestId: slot[3], + } +} + +function clientFromArray(client) { + return { + id: client[0], + requests: client[1], + } +} + +function hostFromArray(host) { + return { + id: host[0], + slots: host[1], + requests: host[2], + } +} + +module.exports = { + supportDAL, +} diff --git a/test/examples.js b/test/examples.js index 50caa46..73bcf96 100644 --- a/test/examples.js +++ b/test/examples.js @@ -40,5 +40,12 @@ const exampleLock = async () => { const exampleAddress = () => { return getAddress(hexlify(randomBytes(20))) } +const zeroBytesHex = (bytes) => { + let hex = "0x" + for (let i = 0; i < bytes; i++) { + hex += "00" + } + return hex +} -module.exports = { exampleRequest, exampleLock, exampleAddress } +module.exports = { exampleRequest, exampleLock, exampleAddress, zeroBytesHex }