Use bid hash as contract id
Adds nonce to storage request to ensure uniqueness.
This commit is contained in:
parent
08cedae4bf
commit
c3e85c675a
|
@ -20,48 +20,48 @@ contract StorageContracts {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint numberOfContracts;
|
uint numberOfContracts;
|
||||||
mapping(uint => Contract) contracts;
|
mapping(bytes32 => Contract) contracts;
|
||||||
|
|
||||||
function duration(uint contractId) public view returns (uint) {
|
function duration(bytes32 contractId) public view returns (uint) {
|
||||||
return contracts[contractId].duration;
|
return contracts[contractId].duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
function size(uint contractId) public view returns (uint) {
|
function size(bytes32 contractId) public view returns (uint) {
|
||||||
return contracts[contractId].size;
|
return contracts[contractId].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
function contentHash(uint contractId) public view returns (bytes32) {
|
function contentHash(bytes32 contractId) public view returns (bytes32) {
|
||||||
return contracts[contractId].contentHash;
|
return contracts[contractId].contentHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
function price(uint contractId) public view returns (uint) {
|
function price(bytes32 contractId) public view returns (uint) {
|
||||||
return contracts[contractId].price;
|
return contracts[contractId].price;
|
||||||
}
|
}
|
||||||
|
|
||||||
function host(uint contractId) public view returns (address) {
|
function host(bytes32 contractId) public view returns (address) {
|
||||||
return contracts[contractId].host;
|
return contracts[contractId].host;
|
||||||
}
|
}
|
||||||
|
|
||||||
function proofPeriod(uint contractId) public view returns (uint) {
|
function proofPeriod(bytes32 contractId) public view returns (uint) {
|
||||||
return contracts[contractId].proofPeriod;
|
return contracts[contractId].proofPeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
function proofTimeout(uint contractId) public view returns (uint) {
|
function proofTimeout(bytes32 contractId) public view returns (uint) {
|
||||||
return contracts[contractId].proofTimeout;
|
return contracts[contractId].proofTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
function missingProofs(uint contractId) public view returns (uint) {
|
function missingProofs(bytes32 contractId) public view returns (uint) {
|
||||||
return contracts[contractId].missingProofs;
|
return contracts[contractId].missingProofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
function newContract(
|
function newContract(
|
||||||
uint contractId,
|
|
||||||
uint _duration,
|
uint _duration,
|
||||||
uint _size,
|
uint _size,
|
||||||
bytes32 _contentHash,
|
bytes32 _contentHash,
|
||||||
uint _price,
|
uint _price,
|
||||||
uint _proofPeriod,
|
uint _proofPeriod,
|
||||||
uint _proofTimeout,
|
uint _proofTimeout,
|
||||||
|
bytes32 _nonce,
|
||||||
uint _bidExpiry,
|
uint _bidExpiry,
|
||||||
address _host,
|
address _host,
|
||||||
bytes memory requestSignature,
|
bytes memory requestSignature,
|
||||||
|
@ -74,13 +74,15 @@ contract StorageContracts {
|
||||||
_size,
|
_size,
|
||||||
_contentHash,
|
_contentHash,
|
||||||
_proofPeriod,
|
_proofPeriod,
|
||||||
_proofTimeout
|
_proofTimeout,
|
||||||
|
_nonce
|
||||||
);
|
);
|
||||||
bytes32 bidHash = hashBid(requestHash, _bidExpiry, _price);
|
bytes32 bidHash = hashBid(requestHash, _bidExpiry, _price);
|
||||||
checkSignature(requestSignature, requestHash, msg.sender);
|
checkSignature(requestSignature, requestHash, msg.sender);
|
||||||
checkSignature(bidSignature, bidHash, _host);
|
checkSignature(bidSignature, bidHash, _host);
|
||||||
checkProofTimeout(_proofTimeout);
|
checkProofTimeout(_proofTimeout);
|
||||||
checkBidExpiry(_bidExpiry);
|
checkBidExpiry(_bidExpiry);
|
||||||
|
bytes32 contractId = bidHash;
|
||||||
checkId(contractId);
|
checkId(contractId);
|
||||||
Contract storage c = contracts[contractId];
|
Contract storage c = contracts[contractId];
|
||||||
c.initialized = true;
|
c.initialized = true;
|
||||||
|
@ -100,7 +102,8 @@ contract StorageContracts {
|
||||||
uint _size,
|
uint _size,
|
||||||
bytes32 _hash,
|
bytes32 _hash,
|
||||||
uint _proofPeriod,
|
uint _proofPeriod,
|
||||||
uint _proofTimeout
|
uint _proofTimeout,
|
||||||
|
bytes32 _nonce
|
||||||
)
|
)
|
||||||
internal pure
|
internal pure
|
||||||
returns (bytes32)
|
returns (bytes32)
|
||||||
|
@ -111,7 +114,8 @@ contract StorageContracts {
|
||||||
_size,
|
_size,
|
||||||
_hash,
|
_hash,
|
||||||
_proofPeriod,
|
_proofPeriod,
|
||||||
_proofTimeout
|
_proofTimeout,
|
||||||
|
_nonce
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +152,7 @@ contract StorageContracts {
|
||||||
require(expiry > block.timestamp, "Bid expired");
|
require(expiry > block.timestamp, "Bid expired");
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkId(uint contractId) internal view {
|
function checkId(bytes32 contractId) internal view {
|
||||||
require(
|
require(
|
||||||
!contracts[contractId].initialized,
|
!contracts[contractId].initialized,
|
||||||
"A contract with this id already exists"
|
"A contract with this id already exists"
|
||||||
|
@ -160,7 +164,7 @@ contract StorageContracts {
|
||||||
// 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(
|
function isProofRequired(
|
||||||
uint contractId,
|
bytes32 contractId,
|
||||||
uint blocknumber
|
uint blocknumber
|
||||||
)
|
)
|
||||||
public view
|
public view
|
||||||
|
@ -172,7 +176,7 @@ contract StorageContracts {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isProofTimedOut(
|
function isProofTimedOut(
|
||||||
uint contractId,
|
bytes32 contractId,
|
||||||
uint blocknumber
|
uint blocknumber
|
||||||
)
|
)
|
||||||
internal view
|
internal view
|
||||||
|
@ -183,7 +187,7 @@ contract StorageContracts {
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitProof(
|
function submitProof(
|
||||||
uint contractId,
|
bytes32 contractId,
|
||||||
uint blocknumber,
|
uint blocknumber,
|
||||||
bool proof
|
bool proof
|
||||||
)
|
)
|
||||||
|
@ -203,7 +207,7 @@ contract StorageContracts {
|
||||||
c.proofReceived[blocknumber] = true;
|
c.proofReceived[blocknumber] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function markProofAsMissing(uint contractId, uint blocknumber) public {
|
function markProofAsMissing(bytes32 contractId, uint blocknumber) public {
|
||||||
Contract storage c = contracts[contractId];
|
Contract storage c = contracts[contractId];
|
||||||
require(
|
require(
|
||||||
isProofTimedOut(contractId, blocknumber),
|
isProofTimedOut(contractId, blocknumber),
|
||||||
|
|
|
@ -10,6 +10,7 @@ describe("Storage Contracts", function () {
|
||||||
const proofPeriod = 8 // 8 blocks ≈ 2 minutes
|
const proofPeriod = 8 // 8 blocks ≈ 2 minutes
|
||||||
const proofTimeout = 4 // 4 blocks ≈ 1 minute
|
const proofTimeout = 4 // 4 blocks ≈ 1 minute
|
||||||
const price = 42
|
const price = 42
|
||||||
|
const nonce = ethers.utils.randomBytes(32)
|
||||||
|
|
||||||
var contracts
|
var contracts
|
||||||
var client, host
|
var client, host
|
||||||
|
@ -26,24 +27,25 @@ describe("Storage Contracts", function () {
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
proofPeriod,
|
proofPeriod,
|
||||||
proofTimeout
|
proofTimeout,
|
||||||
|
nonce
|
||||||
)
|
)
|
||||||
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
|
id = bidHash
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("when properly instantiated", function () {
|
describe("when properly instantiated", function () {
|
||||||
|
|
||||||
beforeEach(async function () {
|
beforeEach(async function () {
|
||||||
await contracts.newContract(
|
await contracts.newContract(
|
||||||
id,
|
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
price,
|
price,
|
||||||
proofPeriod,
|
proofPeriod,
|
||||||
proofTimeout,
|
proofTimeout,
|
||||||
|
nonce,
|
||||||
bidExpiry,
|
bidExpiry,
|
||||||
await host.getAddress(),
|
await host.getAddress(),
|
||||||
await sign(client, requestHash),
|
await sign(client, requestHash),
|
||||||
|
@ -82,26 +84,26 @@ describe("Storage Contracts", function () {
|
||||||
|
|
||||||
it("cannot be created when contract id already used", async function () {
|
it("cannot be created when contract id already used", async function () {
|
||||||
await contracts.newContract(
|
await contracts.newContract(
|
||||||
id,
|
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
price,
|
price,
|
||||||
proofPeriod,
|
proofPeriod,
|
||||||
proofTimeout,
|
proofTimeout,
|
||||||
|
nonce,
|
||||||
bidExpiry,
|
bidExpiry,
|
||||||
await host.getAddress(),
|
await host.getAddress(),
|
||||||
await sign(client, requestHash),
|
await sign(client, requestHash),
|
||||||
await sign(host, bidHash)
|
await sign(host, bidHash)
|
||||||
)
|
)
|
||||||
await expect(contracts.newContract(
|
await expect(contracts.newContract(
|
||||||
id,
|
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
price,
|
price,
|
||||||
proofPeriod,
|
proofPeriod,
|
||||||
proofTimeout,
|
proofTimeout,
|
||||||
|
nonce,
|
||||||
bidExpiry,
|
bidExpiry,
|
||||||
await host.getAddress(),
|
await host.getAddress(),
|
||||||
await sign(client, requestHash),
|
await sign(client, requestHash),
|
||||||
|
@ -115,17 +117,18 @@ describe("Storage Contracts", function () {
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
proofPeriod,
|
proofPeriod,
|
||||||
proofTimeout
|
proofTimeout,
|
||||||
|
nonce
|
||||||
)
|
)
|
||||||
let invalidSignature = await sign(client, invalidHash)
|
let invalidSignature = await sign(client, invalidHash)
|
||||||
await expect(contracts.newContract(
|
await expect(contracts.newContract(
|
||||||
id,
|
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
price,
|
price,
|
||||||
proofPeriod,
|
proofPeriod,
|
||||||
proofTimeout,
|
proofTimeout,
|
||||||
|
nonce,
|
||||||
bidExpiry,
|
bidExpiry,
|
||||||
await host.getAddress(),
|
await host.getAddress(),
|
||||||
invalidSignature,
|
invalidSignature,
|
||||||
|
@ -137,13 +140,13 @@ describe("Storage Contracts", 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(contracts.newContract(
|
await expect(contracts.newContract(
|
||||||
id,
|
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
price,
|
price,
|
||||||
proofPeriod,
|
proofPeriod,
|
||||||
proofTimeout,
|
proofTimeout,
|
||||||
|
nonce,
|
||||||
bidExpiry,
|
bidExpiry,
|
||||||
await host.getAddress(),
|
await host.getAddress(),
|
||||||
await sign(client, requestHash),
|
await sign(client, requestHash),
|
||||||
|
@ -158,17 +161,18 @@ describe("Storage Contracts", function () {
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
proofPeriod,
|
proofPeriod,
|
||||||
invalidTimeout
|
invalidTimeout,
|
||||||
|
nonce
|
||||||
)
|
)
|
||||||
bidHash = hashBid(requestHash, bidExpiry, price)
|
bidHash = hashBid(requestHash, bidExpiry, price)
|
||||||
await expect(contracts.newContract(
|
await expect(contracts.newContract(
|
||||||
id,
|
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
price,
|
price,
|
||||||
proofPeriod,
|
proofPeriod,
|
||||||
invalidTimeout,
|
invalidTimeout,
|
||||||
|
nonce,
|
||||||
bidExpiry,
|
bidExpiry,
|
||||||
await host.getAddress(),
|
await host.getAddress(),
|
||||||
await sign(client, requestHash),
|
await sign(client, requestHash),
|
||||||
|
@ -180,13 +184,13 @@ describe("Storage Contracts", 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(contracts.newContract(
|
await expect(contracts.newContract(
|
||||||
id,
|
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
price,
|
price,
|
||||||
proofPeriod,
|
proofPeriod,
|
||||||
proofTimeout,
|
proofTimeout,
|
||||||
|
nonce,
|
||||||
expired,
|
expired,
|
||||||
await host.getAddress(),
|
await host.getAddress(),
|
||||||
await sign(client, requestHash),
|
await sign(client, requestHash),
|
||||||
|
@ -218,13 +222,13 @@ describe("Storage Contracts", function () {
|
||||||
|
|
||||||
beforeEach(async function () {
|
beforeEach(async function () {
|
||||||
await contracts.newContract(
|
await contracts.newContract(
|
||||||
id,
|
|
||||||
duration,
|
duration,
|
||||||
size,
|
size,
|
||||||
contentHash,
|
contentHash,
|
||||||
price,
|
price,
|
||||||
proofPeriod,
|
proofPeriod,
|
||||||
proofTimeout,
|
proofTimeout,
|
||||||
|
nonce,
|
||||||
bidExpiry,
|
bidExpiry,
|
||||||
await host.getAddress(),
|
await host.getAddress(),
|
||||||
await sign(client, requestHash),
|
await sign(client, requestHash),
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
const { ethers } = require("hardhat")
|
const { ethers } = require("hardhat")
|
||||||
|
|
||||||
function hashRequest(duration, size, hash, proofPeriod, proofTimeout) {
|
function hashRequest(duration, size, hash, proofPeriod, proofTimeout, nonce) {
|
||||||
|
const type = "[dagger.request.v1]"
|
||||||
return ethers.utils.solidityKeccak256(
|
return ethers.utils.solidityKeccak256(
|
||||||
["string", "uint", "uint", "bytes32", "uint", "uint"],
|
["string", "uint", "uint", "bytes32", "uint", "uint", "bytes32"],
|
||||||
["[dagger.request.v1]", duration, size, hash, proofPeriod, proofTimeout]
|
[type, duration, size, hash, proofPeriod, proofTimeout, nonce]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function hashBid(requestHash, expiry, price) {
|
function hashBid(requestHash, expiry, price) {
|
||||||
|
const type = "[dagger.bid.v1]"
|
||||||
return ethers.utils.solidityKeccak256(
|
return ethers.utils.solidityKeccak256(
|
||||||
["string", "bytes32", "uint", "uint"],
|
["string", "bytes32", "uint", "uint"],
|
||||||
["[dagger.bid.v1]", requestHash, expiry, price]
|
[type, requestHash, expiry, price]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue