Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: clean up formatting #18

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,37 @@ import {FileSystem} from "src/FileSystem.sol";
import "script/utils/Constants.sol";

contract Deploy is Script {
/*//////////////////////////////////////////////////////////////////////////
STORAGE
//////////////////////////////////////////////////////////////////////////*/

bytes internal creationCode;
bytes internal constructorArgs;
bytes32 internal salt;

/*//////////////////////////////////////////////////////////////////////////
SETUP
//////////////////////////////////////////////////////////////////////////*/

function setUp() public virtual {
salt = keccak256(abi.encode("ONCHFS"));
creationCode = type(FileSystem).creationCode;
mehtaculous marked this conversation as resolved.
Show resolved Hide resolved
}

/*//////////////////////////////////////////////////////////////////////////
RUN
//////////////////////////////////////////////////////////////////////////*/

function run() public virtual {
bytes32 salt = keccak256(abi.encode("ONCHFS"));
bytes memory creationCode = type(FileSystem).creationCode;
vm.startBroadcast();
_deployCreate2(creationCode, salt);
vm.stopBroadcast();
}

/*//////////////////////////////////////////////////////////////////////////
CREATE2
//////////////////////////////////////////////////////////////////////////*/

function _deployCreate2(bytes memory _creationCode, bytes32 _salt) internal returns (address deployedAddr) {
deployedAddr = _deployCreate2(_creationCode, bytes(""), _salt);
}
Expand Down
5 changes: 1 addition & 4 deletions script/utils/Constants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ uint256 constant GOERLI = 5;
uint256 constant HOLESKY = 17000;
uint256 constant SEPOLIA = 11155111;

// Content Store
address constant GOERLI_CONTENT_STORE = 0x7c1730B7bE9424D0b983B84aEb254e3a2a105d91;
address constant MAINNET_CONTENT_STORE = 0xC6806fd75745bB5F5B32ADa19963898155f9DB91;

// File Store
address constant GOERLI_FILE_STORE = 0x5E348d0975A920E9611F8140f84458998A53af94;
address constant MAINNET_FILE_STORE = 0x9746fD0A77829E12F8A9DBe70D7a322412325B91;
67 changes: 32 additions & 35 deletions src/FileSystem.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ contract FileSystem is IFileSystem {
STORAGE
//////////////////////////////////////////////////////////////////////////*/

address internal constant GOERLI_CONTENT_STORE = 0x7c1730B7bE9424D0b983B84aEb254e3a2a105d91;
address internal constant MAINNET_CONTENT_STORE = 0xC6806fd75745bB5F5B32ADa19963898155f9DB91;

/**
* @inheritdoc IFileSystem
*/
Expand All @@ -39,7 +36,7 @@ contract FileSystem is IFileSystem {
* @dev Initializes the ContentStore contract
*/
constructor() {
CONTENT_STORE = block.chainid == 1 ? MAINNET_CONTENT_STORE : GOERLI_CONTENT_STORE;
CONTENT_STORE = (block.chainid == 1) ? MAINNET_CONTENT_STORE : GOERLI_CONTENT_STORE;
}

/*//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -88,6 +85,37 @@ contract FileSystem is IFileSystem {
emit FileCreated(fileChecksum, _metadata, _chunkPointers);
}

/**
* @inheritdoc IFileSystem
*/
function getInodeAt(
bytes32 _inodeChecksum,
string[] memory _pathSegments
) external view returns (bytes32 inodeChecksum, Inode memory inode) {
if (!inodeExists(_inodeChecksum)) revert InodeNotFound();
inode = inodes[_inodeChecksum];
inodeChecksum = _inodeChecksum;
uint256 length = _pathSegments.length;
Directory memory directory;
string[] memory filenames;
bool found;
for (uint256 i; i < length; i++) {
if (inode.inodeType != InodeType.Directory) revert InodeNotFound();
directory = inode.directory;
filenames = inode.directory.filenames;
found = false;
for (uint256 j; j < filenames.length; j++) {
if (keccak256(bytes(filenames[j])) == keccak256(bytes(_pathSegments[i]))) {
found = true;
inodeChecksum = directory.fileChecksums[j];
inode = inodes[inodeChecksum];
break;
}
}
if (!found) revert InodeNotFound();
}
}

/**
* @inheritdoc IFileSystem
*/
Expand Down Expand Up @@ -172,35 +200,4 @@ contract FileSystem is IFileSystem {
}
return false;
}

function getInodeAt(
bytes32 _inodeChecksum,
string[] memory _pathSegments
) public view returns (bytes32, Inode memory) {
if (!inodeExists(_inodeChecksum)) revert InodeNotFound();

Inode memory inode = inodes[_inodeChecksum];
bytes32 inodeChecksum = _inodeChecksum;

uint256 length = _pathSegments.length;
Directory memory directory;
string[] memory filenames;
bool found;
for (uint256 i; i < length; i++) {
if (inode.inodeType != InodeType.Directory) revert InodeNotFound();
directory = inode.directory;
filenames = inode.directory.filenames;
found = false;
for (uint256 j; j < filenames.length; j++) {
if (keccak256(bytes(filenames[j])) == keccak256(bytes(_pathSegments[i]))) {
found = true;
inodeChecksum = directory.fileChecksums[j];
inode = inodes[inodeChecksum];
break;
}
}
if (!found) revert InodeNotFound();
}
return (inodeChecksum, inode);
}
}
44 changes: 25 additions & 19 deletions src/interfaces/IFileSystem.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ interface IFileSystem {
//////////////////////////////////////////////////////////////////////////*/

/**
* @notice Event emitted when creating a new file inode
* @notice Event emitted when creating a new directory inode
*/
event FileCreated(bytes32 indexed _checksum, bytes metadata, bytes32[] _chunkPointers);
event DirectoryCreated(bytes32 indexed _checksum, string[] _names, bytes32[] _inodeChecksums);

/**
* @notice Event emitted when creating a new directory inode
* @notice Event emitted when creating a new file inode
*/
event DirectoryCreated(bytes32 indexed _checksum, string[] _names, bytes32[] _inodeChecksums);
event FileCreated(bytes32 indexed _checksum, bytes metadata, bytes32[] _chunkPointers);

/*//////////////////////////////////////////////////////////////////////////
ERRORS
Expand All @@ -31,6 +31,7 @@ interface IFileSystem {
* @notice Error thrown when attempting to read chunk that does not exist
*/
error ChunkNotFound();

/**
* @notice Error thrown when reading a directory that does not exist
*/
Expand All @@ -47,14 +48,14 @@ interface IFileSystem {
error InodeNotFound();

/**
* @notice Error thrown when file name is empty
* @notice Error thrown when a forbidden character is present
*/
error InvalidFileName();
error InvalidCharacter();

/**
* @notice Error thrown when a forbidden character is present
* @notice Error thrown when file name is empty
*/
error InvalidCharacter();
error InvalidFileName();

/**
* @notice Error thrown when array lengths do not match
Expand All @@ -72,6 +73,17 @@ interface IFileSystem {
*/
function concatenateChunks(bytes32[] memory _chunkChecksums) external view returns (bytes memory);

/**
* @notice Hashes a list of file names in the directory
* @param _fileNames List of file names
* @param _inodeChecksums List of checksums for the inodes
* @return The concatenated files
*/
function concatenateFiles(
string[] calldata _fileNames,
bytes32[] calldata _inodeChecksums
) external view returns (bytes memory);

/**
* @notice Returns the address of the ContentStore contract
*/
Expand All @@ -97,22 +109,16 @@ interface IFileSystem {
bytes32[] calldata _chunkChecksums
) external returns (bytes32 fileChecksum);

/**
* @notice Traverses a directory and returns an inode
* @param _inodeChecksum Checksum value of the inode
* @param _pathSegments List of path segments being traversed
*/
function getInodeAt(
bytes32 _inodeChecksum,
string[] memory _pathSegments
) external view returns (bytes32, Inode memory);

/**
* @notice Hashes a list of file names in the directory
* @param _fileNames List of file names
* @param _inodeChecksums List of checksums for the inodes
* @return The concatenated files
*/
function concatenateFiles(
string[] calldata _fileNames,
bytes32[] calldata _inodeChecksums
) external view returns (bytes memory);

/**
* @notice Mapping of checksum pointer to Inode struct
*/
Expand Down
21 changes: 21 additions & 0 deletions src/lib/Structs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,42 @@ pragma solidity 0.8.23;
STRUCTS
//////////////////////////////////////////////////////////////////////////*/

/**
* @notice Type of inode
* - `Directory` List of inodes with their assigned names
* - `File` Single inode with assigned name
*/
enum InodeType {
Directory,
File
}

/**
* @notice Struct of directory information
* - `filenames` List of filenames
* - `fileChecksums` List of checksums for each file
*/
struct Directory {
string[] filenames;
bytes32[] fileChecksums;
}

/**
* @notice Struct of file information
* - `metadata` Bytes-encoded metadata of file
* - `chunkChecksums` List of chunked checksums
*/
struct File {
bytes metadata;
bytes32[] chunkChecksums;
}

/**
* @notice Struct of inode information
* - `inodeType` Type of inode
* - `file` Struct of file information
* - `directory` Struct of directory information
*/
struct Inode {
InodeType inodeType;
File file;
Expand Down
5 changes: 5 additions & 0 deletions src/utils/Constants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ pragma solidity 0.8.23;
CONSTANTS
//////////////////////////////////////////////////////////////////////////*/

// Content Store
address constant GOERLI_CONTENT_STORE = 0x7c1730B7bE9424D0b983B84aEb254e3a2a105d91;
address constant MAINNET_CONTENT_STORE = 0xC6806fd75745bB5F5B32ADa19963898155f9DB91;

// ASCII Characters
bytes constant FORBIDDEN_CHARS = ":/?#[]@!$&'()*+,;=";
10 changes: 0 additions & 10 deletions test/FileSystem/CreateDirectory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,8 @@ pragma solidity 0.8.23;
import "test/FileSystem/FileSystemTest.t.sol";

contract CreateDirectory is FileSystemTest {
bytes internal metadata;
bytes internal fileContent;
bytes32[] internal chunkChecksums;
bytes internal hashedFiles;
bytes32 internal fileChecksum;

function setUp() public override {
super.setUp();
metadata = "file metadata";
fileContent = bytes("asdf");
(bytes32 checksum, ) = IContentStore(contentStore).addContent(fileContent);
chunkChecksums.push(checksum);
fileChecksum = fileSystem.createFile(metadata, chunkChecksums);
fileNames.push("file1");
filePointers.push(fileChecksum);
Expand Down
8 changes: 0 additions & 8 deletions test/FileSystem/CreateFile.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,8 @@ pragma solidity 0.8.23;
import "test/FileSystem/FileSystemTest.t.sol";

contract CreateFile is FileSystemTest {
bytes internal metadata;
bytes internal fileContent;
bytes32[] internal chunkChecksums;

function setUp() public override {
super.setUp();
metadata = "file metadata";
fileContent = bytes("asdf");
(bytes32 checksum, ) = IContentStore(contentStore).addContent(fileContent);
chunkChecksums.push(checksum);
}

function test_CreateFile() public {
Expand Down
24 changes: 16 additions & 8 deletions test/FileSystem/FileSystemTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,29 @@
pragma solidity 0.8.23;

import "forge-std/Test.sol";
import "script/utils/Constants.sol";
import "src/utils/Constants.sol";
import "test/utils/Constants.sol";

import {BytesLib} from "test/lib/BytesLib.sol";
import {ContentStore} from "ethfs/packages/contracts/src/ContentStore.sol";
import {FileSystem, InodeType} from "src/FileSystem.sol";
import {BytesLib} from "test/utils/BytesLib.sol";
import {FileSystem} from "src/FileSystem.sol";

import {IContentStore} from "ethfs/packages/contracts/src/IContentStore.sol";
import {IFileSystem} from "src/interfaces/IFileSystem.sol";
import {IFileSystem, InodeType} from "src/interfaces/IFileSystem.sol";

contract FileSystemTest is Test {
// Contracts
bytes internal constant contentStoreByteCode =
hex"608060405234801561001057600080fd5b50600436106100625760003560e01c8063093e9839146100675780631bf226ac1461009c57806331654b09146100dd5780633a77c6c9146100fe5780634641dce614610111578063f97406f714610124575b600080fd5b61007a61007536600461040d565b61015f565b604080519283526001600160a01b039091166020830152015b60405180910390f35b6100c56100aa3660046104be565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610093565b6100f06100eb3660046104be565b610218565b604051908152602001610093565b6100f061010c3660046104d7565b61027d565b6100c561011f3660046104be565b610320565b61014f6101323660046104be565b6000908152602081905260409020546001600160a01b0316151590565b6040519015158152602001610093565b805160208083019190912060008181529182905260408220549091906001600160a01b0316156101aa575060008181526020819052604090205490926001600160a01b039091169150565b6101b383610374565b6000838152602081815260409182902080546001600160a01b0319166001600160a01b0385161790558551915191825291925083917fa1011c3aaafa54b70d8ca12f3b9257ca9a4fe1f6a02196819ea1dcaee1932ca0910160405180910390a2915091565b6000818152602081905260408120546001600160a01b0316610255576040516303001a1960e41b8152600481018390526024015b60405180910390fd5b600082815260208190526040902054610276906001600160a01b03166103b6565b5192915050565b600080610289836103b6565b80516020808301919091206000818152918290526040909120549093509091506001600160a01b0316156102bd5750919050565b6000828152602081815260409182902080546001600160a01b0319166001600160a01b0387161790558251915191825283917fa1011c3aaafa54b70d8ca12f3b9257ca9a4fe1f6a02196819ea1dcaee1932ca0910160405180910390a250919050565b6000818152602081905260408120546001600160a01b0316610358576040516303001a1960e41b81526004810183905260240161024c565b506000908152602081905260409020546001600160a01b031690565b60008151600181018060401b6a61000080600a3d393df300178452600a8101601585016000f0925050816103b05763301164256000526004601cfd5b90915290565b6060813b806103cd576311052bb46000526004601cfd5b600181039050604051915061ffe0603f820116820160405280825280600160208401853c50919050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561041f57600080fd5b813567ffffffffffffffff8082111561043757600080fd5b818401915084601f83011261044b57600080fd5b81358181111561045d5761045d6103f7565b604051601f8201601f19908116603f01168101908382118183101715610485576104856103f7565b8160405282815287602084870101111561049e57600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000602082840312156104d057600080fd5b5035919050565b6000602082840312156104e957600080fd5b81356001600160a01b038116811461050057600080fd5b939250505056fea164736f6c634300080d000a";
FileSystem internal fileSystem;

// State
address internal contentStore;
bytes internal fileContent;
bytes internal hashedFiles;
bytes internal metadata;
bytes32 internal checksum;
bytes32 internal fileChecksum;
bytes32[] internal chunkChecksums;
bytes32[] internal filePointers;
string[] internal fileNames;

Expand All @@ -33,9 +38,12 @@ contract FileSystemTest is Test {
bytes4 internal immutable LENGTH_MISMATCH_ERROR = IFileSystem.LengthMismatch.selector;

function setUp() public virtual {
contentStore = 0x7c1730B7bE9424D0b983B84aEb254e3a2a105d91;
vm.etch(contentStore, contentStoreByteCode);

contentStore = GOERLI_CONTENT_STORE;
vm.etch(contentStore, CONTENT_STORE_BYTE_CODE);
fileSystem = new FileSystem();
metadata = "file metadata";
fileContent = bytes("asdf");
(checksum, ) = IContentStore(contentStore).addContent(fileContent);
chunkChecksums.push(checksum);
}
}
10 changes: 0 additions & 10 deletions test/FileSystem/GetInodeAt.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,8 @@ pragma solidity 0.8.23;
import "test/FileSystem/FileSystemTest.t.sol";

contract GetInodeAt is FileSystemTest {
bytes internal metadata;
bytes internal fileContent;
bytes32[] internal chunkChecksums;
bytes32[] internal hashedFiles;
bytes32 internal fileChecksum;

function setUp() public override {
super.setUp();
metadata = "file metadata";
fileContent = bytes("asdf");
(bytes32 checksum, ) = IContentStore(contentStore).addContent(fileContent);
chunkChecksums.push(checksum);
fileChecksum = fileSystem.createFile(metadata, chunkChecksums);
fileNames.push("file1");
filePointers.push(fileChecksum);
Expand Down
Loading