Skip to content
This repository has been archived by the owner on Sep 9, 2024. It is now read-only.

Commit

Permalink
Removes SignedHash struct and separates timestamp into its own mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
acenolaza committed Oct 5, 2023
1 parent 89328b3 commit 9bae6ef
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 66 deletions.
39 changes: 15 additions & 24 deletions contracts/utils/TimestampedHashRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ contract TimestampedHashRegistry is

mapping(bytes32 => EnumerableSet.AddressSet) private _hashTypeToSigners;

mapping(bytes32 => SignedHash) public hashTypeToSignedHash;
mapping(bytes32 => bytes32) public hashTypeToHash;

mapping(bytes32 => uint256) public hashTypeToTimestamp;

bytes32 private constant _SIGNED_HASH_TYPE_HASH =
keccak256(
Expand All @@ -32,9 +34,7 @@ contract TimestampedHashRegistry is
require(hashType != bytes32(0), "Hash type is zero");
require(signer != address(0), "Signer is zero");
require(
_hashTypeToSigners[keccak256(abi.encodePacked(hashType))].add(
signer
),
_hashTypeToSigners[hashType].add(signer),
"Signer already exists"
);
emit AddedSigner(hashType, signer);
Expand All @@ -44,9 +44,7 @@ contract TimestampedHashRegistry is
require(hashType != bytes32(0), "Hash type is zero");
require(signer != address(0), "Signer is zero");
require(
_hashTypeToSigners[keccak256(abi.encodePacked(hashType))].remove(
signer
),
_hashTypeToSigners[hashType].remove(signer),
"Signer does not exist"
);
emit RemovedSigner(hashType, signer);
Expand All @@ -55,19 +53,17 @@ contract TimestampedHashRegistry is
function getSigners(
bytes32 hashType
) external view returns (address[] memory signers) {
signers = _hashTypeToSigners[keccak256(abi.encodePacked(hashType))]
.values();
signers = _hashTypeToSigners[hashType].values();
}

function registerSignedHash(
function registerHash(
bytes32 hashType,
SignedHash calldata signedHash,
bytes32 hash,
uint256 timestamp,
bytes[] calldata signatures
) external {
require(hashType != bytes32(0), "Hash type is zero");
EnumerableSet.AddressSet storage signers = _hashTypeToSigners[
keccak256(abi.encodePacked(hashType))
];
EnumerableSet.AddressSet storage signers = _hashTypeToSigners[hashType];
require(signers.length() != 0, "Signers have not been set");
require(
signatures.length == signers.length(),
Expand All @@ -80,21 +76,16 @@ contract TimestampedHashRegistry is
abi.encode(
_SIGNED_HASH_TYPE_HASH,
hashType,
signedHash.hash,
signedHash.timestamp
hash,
timestamp
)
)
).recover(signatures[ind]) == signers.at(ind),
"Signature mismatch"
);
}
hashTypeToSignedHash[
keccak256(abi.encodePacked(hashType))
] = SignedHash(signedHash.hash, signedHash.timestamp);
emit RegisteredSignedHash(
hashType,
signedHash.hash,
signedHash.timestamp
);
hashTypeToHash[hashType] = hash;
hashTypeToTimestamp[hashType] = timestamp;
emit RegisteredHash(hashType, hash, timestamp);
}
}
20 changes: 10 additions & 10 deletions contracts/utils/interfaces/ITimestampedHashRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,12 @@ interface ITimestampedHashRegistry {

event RemovedSigner(bytes32 indexed hashType, address signer);

event RegisteredSignedHash(
event RegisteredHash(
bytes32 indexed hashType,
bytes32 hash,
uint256 timestamp
);

struct SignedHash {
bytes32 hash; // i.e. merkle tree root
uint256 timestamp;
}

function addSigner(bytes32 hashType, address signer) external;

function removeSigner(bytes32 hashType, address signer) external;
Expand All @@ -25,13 +20,18 @@ interface ITimestampedHashRegistry {
bytes32 hashType
) external view returns (address[] memory signers);

function registerSignedHash(
function registerHash(
bytes32 hashType,
SignedHash calldata signedHash,
bytes32 hash,
uint256 timestamp,
bytes[] calldata signatures
) external;

function hashTypeToSignedHash(
function hashTypeToHash(
bytes32 hashType
) external view returns (bytes32 hash);

function hashTypeToTimestamp(
bytes32 hashType
) external view returns (bytes32 hash, uint256 timestamp);
) external view returns (uint256 timestamp);
}
50 changes: 18 additions & 32 deletions test/utils/TimestampedHashRegistry.sol.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe('TimestampedHashRegistry', function () {
{ name: 'timestamp', type: 'uint256' },
],
};
const dapiFallbackHashType = hre.ethers.utils.formatBytes32String('dAPI fallback root');
const dapiFallbackHashType = hre.ethers.utils.solidityKeccak256(['string'], ['dAPI fallback root']);
const values = {
hashType: dapiFallbackHashType,
hash: root,
Expand Down Expand Up @@ -275,7 +275,7 @@ describe('TimestampedHashRegistry', function () {
});
});

describe('registerSignedHash', function () {
describe('registerHash', function () {
context('Hash type is not zero', function () {
context('Signers is not empty', function () {
context('Number of signatures is equal to number of signers', function () {
Expand All @@ -288,25 +288,22 @@ describe('TimestampedHashRegistry', function () {
roles.dapiFallbackRootSigner2.address,
roles.dapiFallbackRootSigner3.address,
];
expect(await timestampedHashRegistry.hashTypeToSignedHash(dapiFallbackHashType)).to.contain(
hre.ethers.constants.HashZero,
0
expect(await timestampedHashRegistry.hashTypeToHash(dapiFallbackHashType)).to.equal(
hre.ethers.constants.HashZero
);
expect(await timestampedHashRegistry.hashTypeToTimestamp(dapiFallbackHashType)).to.equal(0);
await timestampedHashRegistry
.connect(roles.owner)
.multicall(
signers.map((signer) =>
timestampedHashRegistry.interface.encodeFunctionData('addSigner', [dapiFallbackHashType, signer])
)
);
await expect(
timestampedHashRegistry.registerSignedHash(dapiFallbackHashType, { hash: root, timestamp }, signatures)
)
.to.emit(timestampedHashRegistry, 'RegisteredSignedHash')
await expect(timestampedHashRegistry.registerHash(dapiFallbackHashType, root, timestamp, signatures))
.to.emit(timestampedHashRegistry, 'RegisteredHash')
.withArgs(dapiFallbackHashType, root, timestamp);
expect(
await timestampedHashRegistry.hashTypeToSignedHash(hre.ethers.utils.keccak256(dapiFallbackHashType))
).to.contain(root, timestamp);
expect(await timestampedHashRegistry.hashTypeToHash(dapiFallbackHashType)).to.equal(root);
expect(await timestampedHashRegistry.hashTypeToTimestamp(dapiFallbackHashType)).to.equal(timestamp);
});
});
context('All signatures do not match', function () {
Expand Down Expand Up @@ -335,7 +332,7 @@ describe('TimestampedHashRegistry', function () {
);
// Signed by a different signer
await expect(
timestampedHashRegistry.registerSignedHash(dapiFallbackHashType, { hash: root, timestamp }, [
timestampedHashRegistry.registerHash(dapiFallbackHashType, root, timestamp, [
await roles.randomPerson._signTypedData(domain, types, {
hashType: dapiFallbackHashType,
hash: root,
Expand All @@ -346,7 +343,7 @@ describe('TimestampedHashRegistry', function () {
).to.be.revertedWith('Signature mismatch');
// Signed a different root
await expect(
timestampedHashRegistry.registerSignedHash(dapiFallbackHashType, { hash: root, timestamp }, [
timestampedHashRegistry.registerHash(dapiFallbackHashType, root, timestamp, [
await roles.dapiFallbackRootSigner1._signTypedData(domain, types, {
hashType: dapiFallbackHashType,
hash: generateRandomBytes32(),
Expand All @@ -357,19 +354,16 @@ describe('TimestampedHashRegistry', function () {
).to.be.revertedWith('Signature mismatch');
// All signatures are different
await expect(
timestampedHashRegistry.registerSignedHash(
timestampedHashRegistry.registerHash(
dapiFallbackHashType,
{ hash: root, timestamp },
root,
timestamp,
Array(3).fill(signatures[0])
)
).to.be.revertedWith('Signature mismatch');
// All signatures are in the expected order
await expect(
timestampedHashRegistry.registerSignedHash(
dapiFallbackHashType,
{ hash: root, timestamp },
signatures.reverse()
)
timestampedHashRegistry.registerHash(dapiFallbackHashType, root, timestamp, signatures.reverse())
).to.be.revertedWith('Signature mismatch');
});
});
Expand All @@ -391,11 +385,7 @@ describe('TimestampedHashRegistry', function () {
)
);
await expect(
timestampedHashRegistry.registerSignedHash(
dapiFallbackHashType,
{ hash: root, timestamp },
signatures.slice(1)
)
timestampedHashRegistry.registerHash(dapiFallbackHashType, root, timestamp, signatures.slice(1))
).to.be.revertedWith('Invalid number of signatures');
});
});
Expand All @@ -404,7 +394,7 @@ describe('TimestampedHashRegistry', function () {
it('reverts', async function () {
const { timestampedHashRegistry, dapiFallbackHashType, root, timestamp } = await helpers.loadFixture(deploy);
await expect(
timestampedHashRegistry.registerSignedHash(dapiFallbackHashType, { hash: root, timestamp }, [])
timestampedHashRegistry.registerHash(dapiFallbackHashType, root, timestamp, [])
).to.be.revertedWith('Signers have not been set');
});
});
Expand All @@ -413,11 +403,7 @@ describe('TimestampedHashRegistry', function () {
it('reverts', async function () {
const { timestampedHashRegistry, root, timestamp, signatures } = await helpers.loadFixture(deploy);
await expect(
timestampedHashRegistry.registerSignedHash(
hre.ethers.constants.HashZero,
{ hash: root, timestamp },
signatures
)
timestampedHashRegistry.registerHash(hre.ethers.constants.HashZero, root, timestamp, signatures)
).to.be.revertedWith('Hash type is zero');
});
});
Expand Down

0 comments on commit 9bae6ef

Please sign in to comment.