Multiple storage contracts in solidity contract
This commit is contained in:
parent
d005bf7c3c
commit
08cedae4bf
|
@ -4,28 +4,70 @@ pragma solidity ^0.8.0;
|
||||||
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
||||||
|
|
||||||
contract StorageContracts {
|
contract StorageContracts {
|
||||||
uint public immutable duration; // contract duration in seconds
|
|
||||||
uint public immutable size; // storage size in bytes
|
|
||||||
bytes32 public immutable contentHash; // hash of data that is to be stored
|
|
||||||
uint public immutable price; // price in coins
|
|
||||||
address public immutable host; // host that provides storage
|
|
||||||
uint public immutable proofPeriod; // average time between proofs (in blocks)
|
|
||||||
uint public immutable proofTimeout; // proof has to be submitted before this
|
|
||||||
uint public immutable proofMarker; // indicates when a proof is required
|
|
||||||
|
|
||||||
mapping(uint => bool) proofReceived; // whether proof for a block was received
|
struct Contract {
|
||||||
uint public missingProofs;
|
bool initialized; // always true, except for empty contracts in mapping
|
||||||
|
uint duration; // contract duration in seconds
|
||||||
|
uint size; // storage size in bytes
|
||||||
|
bytes32 contentHash; // hash of data that is to be stored
|
||||||
|
uint price; // price in coins
|
||||||
|
address host; // host that provides storage
|
||||||
|
uint proofPeriod; // average time between proofs (in blocks)
|
||||||
|
uint proofTimeout; // proof has to be submitted before this
|
||||||
|
uint proofMarker; // indicates when a proof is required
|
||||||
|
mapping(uint => bool) proofReceived; // whether proof for block was received
|
||||||
|
uint missingProofs;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(uint _duration,
|
uint numberOfContracts;
|
||||||
uint _size,
|
mapping(uint => Contract) contracts;
|
||||||
bytes32 _contentHash,
|
|
||||||
uint _price,
|
function duration(uint contractId) public view returns (uint) {
|
||||||
uint _proofPeriod,
|
return contracts[contractId].duration;
|
||||||
uint _proofTimeout,
|
}
|
||||||
uint _bidExpiry,
|
|
||||||
address _host,
|
function size(uint contractId) public view returns (uint) {
|
||||||
bytes memory requestSignature,
|
return contracts[contractId].size;
|
||||||
bytes memory bidSignature)
|
}
|
||||||
|
|
||||||
|
function contentHash(uint contractId) public view returns (bytes32) {
|
||||||
|
return contracts[contractId].contentHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
function price(uint contractId) public view returns (uint) {
|
||||||
|
return contracts[contractId].price;
|
||||||
|
}
|
||||||
|
|
||||||
|
function host(uint contractId) public view returns (address) {
|
||||||
|
return contracts[contractId].host;
|
||||||
|
}
|
||||||
|
|
||||||
|
function proofPeriod(uint contractId) public view returns (uint) {
|
||||||
|
return contracts[contractId].proofPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
function proofTimeout(uint contractId) public view returns (uint) {
|
||||||
|
return contracts[contractId].proofTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
function missingProofs(uint contractId) public view returns (uint) {
|
||||||
|
return contracts[contractId].missingProofs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newContract(
|
||||||
|
uint contractId,
|
||||||
|
uint _duration,
|
||||||
|
uint _size,
|
||||||
|
bytes32 _contentHash,
|
||||||
|
uint _price,
|
||||||
|
uint _proofPeriod,
|
||||||
|
uint _proofTimeout,
|
||||||
|
uint _bidExpiry,
|
||||||
|
address _host,
|
||||||
|
bytes memory requestSignature,
|
||||||
|
bytes memory bidSignature
|
||||||
|
)
|
||||||
|
public
|
||||||
{
|
{
|
||||||
bytes32 requestHash = hashRequest(
|
bytes32 requestHash = hashRequest(
|
||||||
_duration,
|
_duration,
|
||||||
|
@ -39,14 +81,17 @@ contract StorageContracts {
|
||||||
checkSignature(bidSignature, bidHash, _host);
|
checkSignature(bidSignature, bidHash, _host);
|
||||||
checkProofTimeout(_proofTimeout);
|
checkProofTimeout(_proofTimeout);
|
||||||
checkBidExpiry(_bidExpiry);
|
checkBidExpiry(_bidExpiry);
|
||||||
duration = _duration;
|
checkId(contractId);
|
||||||
size = _size;
|
Contract storage c = contracts[contractId];
|
||||||
price = _price;
|
c.initialized = true;
|
||||||
contentHash = _contentHash;
|
c.duration = _duration;
|
||||||
host = _host;
|
c.size = _size;
|
||||||
proofPeriod = _proofPeriod;
|
c.price = _price;
|
||||||
proofTimeout = _proofTimeout;
|
c.contentHash = _contentHash;
|
||||||
proofMarker = uint(blockhash(block.number - 1)) % _proofPeriod;
|
c.host = _host;
|
||||||
|
c.proofPeriod = _proofPeriod;
|
||||||
|
c.proofTimeout = _proofTimeout;
|
||||||
|
c.proofMarker = uint(blockhash(block.number - 1)) % _proofPeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates hash for a storage request that can be used to check its signature.
|
// Creates hash for a storage request that can be used to check its signature.
|
||||||
|
@ -103,31 +148,75 @@ contract StorageContracts {
|
||||||
require(expiry > block.timestamp, "Bid expired");
|
require(expiry > block.timestamp, "Bid expired");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkId(uint contractId) internal view {
|
||||||
|
require(
|
||||||
|
!contracts[contractId].initialized,
|
||||||
|
"A contract with this id already exists"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether a proof is required at the time of the block with the
|
// Check whether a proof is required at the time of the block with the
|
||||||
// specified block number. A proof has to be submitted within the proof
|
// specified block number. A proof has to be submitted within the proof
|
||||||
// timeout for it to be valid. Whether a proof is required is determined
|
// timeout for it to be valid. Whether a proof is required is determined
|
||||||
// randomly, but on average it is once every proof period.
|
// randomly, but on average it is once every proof period.
|
||||||
function isProofRequired(uint blocknumber) public view returns (bool) {
|
function isProofRequired(
|
||||||
|
uint contractId,
|
||||||
|
uint blocknumber
|
||||||
|
)
|
||||||
|
public view
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
Contract storage c = contracts[contractId];
|
||||||
bytes32 hash = blockhash(blocknumber);
|
bytes32 hash = blockhash(blocknumber);
|
||||||
return hash != 0 && uint(hash) % proofPeriod == proofMarker;
|
return hash != 0 && uint(hash) % c.proofPeriod == c.proofMarker;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isProofTimedOut(uint blocknumber) internal view returns (bool) {
|
function isProofTimedOut(
|
||||||
return block.number >= blocknumber + proofTimeout;
|
uint contractId,
|
||||||
|
uint blocknumber
|
||||||
|
)
|
||||||
|
internal view
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
Contract storage c = contracts[contractId];
|
||||||
|
return block.number >= blocknumber + c.proofTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitProof(uint blocknumber, bool proof) public {
|
function submitProof(
|
||||||
|
uint contractId,
|
||||||
|
uint blocknumber,
|
||||||
|
bool proof
|
||||||
|
)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
Contract storage c = contracts[contractId];
|
||||||
require(proof, "Invalid proof"); // TODO: replace bool by actual proof
|
require(proof, "Invalid proof"); // TODO: replace bool by actual proof
|
||||||
require(isProofRequired(blocknumber), "No proof required for this block");
|
require(
|
||||||
require(!isProofTimedOut(blocknumber), "Proof not allowed after timeout");
|
isProofRequired(contractId, blocknumber),
|
||||||
require(!proofReceived[blocknumber], "Proof already submitted");
|
"No proof required for this block"
|
||||||
proofReceived[blocknumber] = true;
|
);
|
||||||
|
require(
|
||||||
|
!isProofTimedOut(contractId, blocknumber),
|
||||||
|
"Proof not allowed after timeout"
|
||||||
|
);
|
||||||
|
require(!c.proofReceived[blocknumber], "Proof already submitted");
|
||||||
|
c.proofReceived[blocknumber] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function markProofAsMissing(uint blocknumber) public {
|
function markProofAsMissing(uint contractId, uint blocknumber) public {
|
||||||
require(isProofTimedOut(blocknumber), "Proof has not timed out yet");
|
Contract storage c = contracts[contractId];
|
||||||
require(!proofReceived[blocknumber], "Proof was submitted, not missing");
|
require(
|
||||||
require(isProofRequired(blocknumber), "Proof was not required");
|
isProofTimedOut(contractId, blocknumber),
|
||||||
missingProofs += 1;
|
"Proof has not timed out yet"
|
||||||
|
);
|
||||||
|
require(
|
||||||
|
!c.proofReceived[blocknumber],
|
||||||
|
"Proof was submitted, not missing"
|
||||||
|
);
|
||||||
|
require(
|
||||||
|
isProofRequired(contractId, blocknumber),
|
||||||
|
"Proof was not required"
|
||||||
|
);
|
||||||
|
c.missingProofs += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,15 +11,16 @@ describe("Storage Contracts", function () {
|
||||||
const proofTimeout = 4 // 4 blocks ≈ 1 minute
|
const proofTimeout = 4 // 4 blocks ≈ 1 minute
|
||||||
const price = 42
|
const price = 42
|
||||||
|
|
||||||
var StorageContracts
|
var contracts
|
||||||
var client, host
|
var client, host
|
||||||
var bidExpiry
|
var bidExpiry
|
||||||
var requestHash, bidHash
|
var requestHash, bidHash
|
||||||
var contract
|
var id
|
||||||
|
|
||||||
beforeEach(async function () {
|
beforeEach(async function () {
|
||||||
[client, host] = await ethers.getSigners()
|
[client, host] = await ethers.getSigners()
|
||||||
StorageContracts = await ethers.getContractFactory("StorageContracts")
|
let StorageContracts = await ethers.getContractFactory("StorageContracts")
|
||||||
|
contracts = await StorageContracts.deploy()
|
||||||
requestHash = hashRequest(
|
requestHash = hashRequest(
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
|
@ -29,12 +30,14 @@ describe("Storage Contracts", function () {
|
||||||
)
|
)
|
||||||
bidExpiry = Math.round(Date.now() / 1000) + 60 * 60 // 1 hour from now
|
bidExpiry = Math.round(Date.now() / 1000) + 60 * 60 // 1 hour from now
|
||||||
bidHash = hashBid(requestHash, bidExpiry, price)
|
bidHash = hashBid(requestHash, bidExpiry, price)
|
||||||
|
id = Math.round(Math.random() * 99999999) // randomly chosen contract id
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("when properly instantiated", function () {
|
describe("when properly instantiated", function () {
|
||||||
|
|
||||||
beforeEach(async function () {
|
beforeEach(async function () {
|
||||||
contract = await StorageContracts.deploy(
|
await contracts.newContract(
|
||||||
|
id,
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
|
@ -49,34 +52,63 @@ describe("Storage Contracts", function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("has a duration", async function () {
|
it("has a duration", async function () {
|
||||||
expect(await contract.duration()).to.equal(duration)
|
expect(await contracts.duration(id)).to.equal(duration)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("contains the size of the data that is to be stored", async function () {
|
it("contains the size of the data that is to be stored", async function () {
|
||||||
expect(await contract.size()).to.equal(size)
|
expect(await contracts.size(id)).to.equal(size)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("contains the hash of the data that is to be stored", async function () {
|
it("contains the hash of the data that is to be stored", async function () {
|
||||||
expect(await contract.contentHash()).to.equal(contentHash)
|
expect(await contracts.contentHash(id)).to.equal(contentHash)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("has a price", async function () {
|
it("has a price", async function () {
|
||||||
expect(await contract.price()).to.equal(price)
|
expect(await contracts.price(id)).to.equal(price)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("knows the host that provides the storage", async function () {
|
it("knows the host that provides the storage", async function () {
|
||||||
expect(await contract.host()).to.equal(await host.getAddress())
|
expect(await contracts.host(id)).to.equal(await host.getAddress())
|
||||||
})
|
})
|
||||||
|
|
||||||
it("has an average time between proofs (in blocks)", async function (){
|
it("has an average time between proofs (in blocks)", async function (){
|
||||||
expect(await contract.proofPeriod()).to.equal(proofPeriod)
|
expect(await contracts.proofPeriod(id)).to.equal(proofPeriod)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("has a proof timeout (in blocks)", async function (){
|
it("has a proof timeout (in blocks)", async function (){
|
||||||
expect(await contract.proofTimeout()).to.equal(proofTimeout)
|
expect(await contracts.proofTimeout(id)).to.equal(proofTimeout)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("cannot be created when contract id already used", async function () {
|
||||||
|
await contracts.newContract(
|
||||||
|
id,
|
||||||
|
duration,
|
||||||
|
size,
|
||||||
|
contentHash,
|
||||||
|
price,
|
||||||
|
proofPeriod,
|
||||||
|
proofTimeout,
|
||||||
|
bidExpiry,
|
||||||
|
await host.getAddress(),
|
||||||
|
await sign(client, requestHash),
|
||||||
|
await sign(host, bidHash)
|
||||||
|
)
|
||||||
|
await expect(contracts.newContract(
|
||||||
|
id,
|
||||||
|
duration,
|
||||||
|
size,
|
||||||
|
contentHash,
|
||||||
|
price,
|
||||||
|
proofPeriod,
|
||||||
|
proofTimeout,
|
||||||
|
bidExpiry,
|
||||||
|
await host.getAddress(),
|
||||||
|
await sign(client, requestHash),
|
||||||
|
await sign(host, bidHash)
|
||||||
|
)).to.be.revertedWith("A contract with this id already exists")
|
||||||
|
})
|
||||||
|
|
||||||
it("cannot be created when client signature is invalid", async function () {
|
it("cannot be created when client signature is invalid", async function () {
|
||||||
let invalidHash = hashRequest(
|
let invalidHash = hashRequest(
|
||||||
duration + 1,
|
duration + 1,
|
||||||
|
@ -86,7 +118,8 @@ describe("Storage Contracts", function () {
|
||||||
proofTimeout
|
proofTimeout
|
||||||
)
|
)
|
||||||
let invalidSignature = await sign(client, invalidHash)
|
let invalidSignature = await sign(client, invalidHash)
|
||||||
await expect(StorageContract.deploy(
|
await expect(contracts.newContract(
|
||||||
|
id,
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
|
@ -103,7 +136,8 @@ describe("Storage Contracts", function () {
|
||||||
it("cannot be created when host signature is invalid", async function () {
|
it("cannot be created when host signature is invalid", async function () {
|
||||||
let invalidBid = hashBid(requestHash, bidExpiry, price - 1)
|
let invalidBid = hashBid(requestHash, bidExpiry, price - 1)
|
||||||
let invalidSignature = await sign(host, invalidBid)
|
let invalidSignature = await sign(host, invalidBid)
|
||||||
await expect(StorageContract.deploy(
|
await expect(contracts.newContract(
|
||||||
|
id,
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
|
@ -127,7 +161,8 @@ describe("Storage Contracts", function () {
|
||||||
invalidTimeout
|
invalidTimeout
|
||||||
)
|
)
|
||||||
bidHash = hashBid(requestHash, bidExpiry, price)
|
bidHash = hashBid(requestHash, bidExpiry, price)
|
||||||
await expect(StorageContract.deploy(
|
await expect(contracts.newContract(
|
||||||
|
id,
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
|
@ -144,7 +179,8 @@ describe("Storage Contracts", function () {
|
||||||
it("cannot be created when bid has expired", async function () {
|
it("cannot be created when bid has expired", async function () {
|
||||||
let expired = Math.round(Date.now() / 1000) - 60 // 1 minute ago
|
let expired = Math.round(Date.now() / 1000) - 60 // 1 minute ago
|
||||||
let bidHash = hashBid(requestHash, expired, price)
|
let bidHash = hashBid(requestHash, expired, price)
|
||||||
await expect(StorageContract.deploy(
|
await expect(contracts.newContract(
|
||||||
|
id,
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
|
@ -168,8 +204,8 @@ describe("Storage Contracts", function () {
|
||||||
return await ethers.provider.getBlockNumber() - 1
|
return await ethers.provider.getBlockNumber() - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
async function mineUntilProofIsRequired() {
|
async function mineUntilProofIsRequired(id) {
|
||||||
while (!await contract.isProofRequired(await minedBlockNumber())) {
|
while (!await contracts.isProofRequired(id, await minedBlockNumber())) {
|
||||||
mineBlock()
|
mineBlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,7 +217,8 @@ describe("Storage Contracts", function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(async function () {
|
beforeEach(async function () {
|
||||||
contract = await StorageContract.deploy(
|
await contracts.newContract(
|
||||||
|
id,
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
|
@ -200,7 +237,7 @@ describe("Storage Contracts", function () {
|
||||||
let proofs = 0
|
let proofs = 0
|
||||||
for (i=0; i<blocks; i++) {
|
for (i=0; i<blocks; i++) {
|
||||||
await mineBlock()
|
await mineBlock()
|
||||||
if (await contract.isProofRequired(await minedBlockNumber())) {
|
if (await contracts.isProofRequired(id, await minedBlockNumber())) {
|
||||||
proofs += 1
|
proofs += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,92 +246,92 @@ describe("Storage Contracts", function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("requires no proof for blocks that are unavailable", async function () {
|
it("requires no proof for blocks that are unavailable", async function () {
|
||||||
await mineUntilProofIsRequired()
|
await mineUntilProofIsRequired(id)
|
||||||
let blocknumber = await minedBlockNumber()
|
let blocknumber = await minedBlockNumber()
|
||||||
for (i=0; i<256; i++) { // only last 256 blocks are available in solidity
|
for (i=0; i<256; i++) { // only last 256 blocks are available in solidity
|
||||||
mineBlock()
|
mineBlock()
|
||||||
}
|
}
|
||||||
expect(await contract.isProofRequired(blocknumber)).to.be.false
|
expect(await contracts.isProofRequired(id, blocknumber)).to.be.false
|
||||||
})
|
})
|
||||||
|
|
||||||
it("submits a correct proof", async function () {
|
it("submits a correct proof", async function () {
|
||||||
await mineUntilProofIsRequired()
|
await mineUntilProofIsRequired(id)
|
||||||
let blocknumber = await minedBlockNumber()
|
let blocknumber = await minedBlockNumber()
|
||||||
await contract.submitProof(blocknumber, true)
|
await contracts.submitProof(id, blocknumber, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails proof submission when proof is incorrect", async function () {
|
it("fails proof submission when proof is incorrect", async function () {
|
||||||
await mineUntilProofIsRequired()
|
await mineUntilProofIsRequired(id)
|
||||||
let blocknumber = await minedBlockNumber()
|
let blocknumber = await minedBlockNumber()
|
||||||
await expect(
|
await expect(
|
||||||
contract.submitProof(blocknumber, false)
|
contracts.submitProof(id, blocknumber, false)
|
||||||
).to.be.revertedWith("Invalid proof")
|
).to.be.revertedWith("Invalid proof")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails proof submission when proof was not required", async function () {
|
it("fails proof submission when proof was not required", async function () {
|
||||||
while (await contract.isProofRequired(await minedBlockNumber())) {
|
while (await contracts.isProofRequired(id, await minedBlockNumber())) {
|
||||||
await mineBlock()
|
await mineBlock()
|
||||||
}
|
}
|
||||||
let blocknumber = await minedBlockNumber()
|
let blocknumber = await minedBlockNumber()
|
||||||
await expect(
|
await expect(
|
||||||
contract.submitProof(blocknumber, true)
|
contracts.submitProof(id, blocknumber, true)
|
||||||
).to.be.revertedWith("No proof required")
|
).to.be.revertedWith("No proof required")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails proof submission when proof is too late", async function () {
|
it("fails proof submission when proof is too late", async function () {
|
||||||
await mineUntilProofIsRequired()
|
await mineUntilProofIsRequired(id)
|
||||||
let blocknumber = await minedBlockNumber()
|
let blocknumber = await minedBlockNumber()
|
||||||
await mineUntilProofTimeout()
|
await mineUntilProofTimeout()
|
||||||
await expect(
|
await expect(
|
||||||
contract.submitProof(blocknumber, true)
|
contracts.submitProof(id, blocknumber, true)
|
||||||
).to.be.revertedWith("Proof not allowed after timeout")
|
).to.be.revertedWith("Proof not allowed after timeout")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails proof submission when already submitted", async function() {
|
it("fails proof submission when already submitted", async function() {
|
||||||
await mineUntilProofIsRequired()
|
await mineUntilProofIsRequired(id)
|
||||||
let blocknumber = await minedBlockNumber()
|
let blocknumber = await minedBlockNumber()
|
||||||
await contract.submitProof(blocknumber, true)
|
await contracts.submitProof(id, blocknumber, true)
|
||||||
await expect(
|
await expect(
|
||||||
contract.submitProof(blocknumber, true)
|
contracts.submitProof(id, blocknumber, true)
|
||||||
).to.be.revertedWith("Proof already submitted")
|
).to.be.revertedWith("Proof already submitted")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("marks a proof as missing", async function () {
|
it("marks a proof as missing", async function () {
|
||||||
expect(await contract.missingProofs()).to.equal(0)
|
expect(await contracts.missingProofs(id)).to.equal(0)
|
||||||
await mineUntilProofIsRequired()
|
await mineUntilProofIsRequired(id)
|
||||||
let blocknumber = await minedBlockNumber()
|
let blocknumber = await minedBlockNumber()
|
||||||
await mineUntilProofTimeout()
|
await mineUntilProofTimeout()
|
||||||
await contract.markProofAsMissing(blocknumber)
|
await contracts.markProofAsMissing(id, blocknumber)
|
||||||
expect(await contract.missingProofs()).to.equal(1)
|
expect(await contracts.missingProofs(id)).to.equal(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("does not mark a proof as missing before timeout", async function () {
|
it("does not mark a proof as missing before timeout", async function () {
|
||||||
await mineUntilProofIsRequired()
|
await mineUntilProofIsRequired(id)
|
||||||
let blocknumber = await minedBlockNumber()
|
let blocknumber = await minedBlockNumber()
|
||||||
await mineBlock()
|
await mineBlock()
|
||||||
await expect(
|
await expect(
|
||||||
contract.markProofAsMissing(blocknumber)
|
contracts.markProofAsMissing(id, blocknumber)
|
||||||
).to.be.revertedWith("Proof has not timed out yet")
|
).to.be.revertedWith("Proof has not timed out yet")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("does not mark a submitted proof as missing", async function () {
|
it("does not mark a submitted proof as missing", async function () {
|
||||||
await mineUntilProofIsRequired()
|
await mineUntilProofIsRequired(id)
|
||||||
let blocknumber = await minedBlockNumber()
|
let blocknumber = await minedBlockNumber()
|
||||||
await contract.submitProof(blocknumber, true)
|
await contracts.submitProof(id, blocknumber, true)
|
||||||
await mineUntilProofTimeout()
|
await mineUntilProofTimeout()
|
||||||
await expect(
|
await expect(
|
||||||
contract.markProofAsMissing(blocknumber)
|
contracts.markProofAsMissing(id, blocknumber)
|
||||||
).to.be.revertedWith("Proof was submitted, not missing")
|
).to.be.revertedWith("Proof was submitted, not missing")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("does not mark proof as missing when not required", async function () {
|
it("does not mark proof as missing when not required", async function () {
|
||||||
while (await contract.isProofRequired(await minedBlockNumber())) {
|
while (await contracts.isProofRequired(id, await minedBlockNumber())) {
|
||||||
mineBlock()
|
mineBlock()
|
||||||
}
|
}
|
||||||
let blocknumber = await minedBlockNumber()
|
let blocknumber = await minedBlockNumber()
|
||||||
await mineUntilProofTimeout()
|
await mineUntilProofTimeout()
|
||||||
await expect(
|
await expect(
|
||||||
contract.markProofAsMissing(blocknumber)
|
contracts.markProofAsMissing(id, blocknumber)
|
||||||
).to.be.revertedWith("Proof was not required")
|
).to.be.revertedWith("Proof was not required")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -306,4 +343,3 @@ describe("Storage Contracts", function () {
|
||||||
// TODO: only allow proofs after start of contract
|
// TODO: only allow proofs after start of contract
|
||||||
// TODO: payout
|
// TODO: payout
|
||||||
// TODO: stake
|
// TODO: stake
|
||||||
// TODO: multiple hosts in single contract
|
|
||||||
|
|
Loading…
Reference in New Issue