DCIPs/EIPS/eip-5018.md

162 lines
5.8 KiB
Markdown

---
eip: 5018
title: Filesystem-like Interface for Contracts
description: An interface to provide access to binary objects similar to filesystems.
author: Qi Zhou (@qizhou)
discussions-to: https://ethereum-magicians.org/t/eip-5018-directory-standard/8958
status: Review
type: Standards Track
category: ERC
created: 2022-04-18
---
## Abstract
The following standardizes an API for directories and files within smart contracts, similar to traditional filesystems.
This standard provides basic functionality to read/write binary objects of any size, as well as allow reading/writing chunks of the object if the object is too large to fit in a single transaction.
## Motivation
A standard interface allows any binary objects on EVM-based blockchain to be re-used by other dApps.
With [EIP-4804](./eip-4804.md), we are able to locate a Web3 resource on blockchain using HTTP-style URIs. One application of Web3 resources are web contents that are referenced within a directory using relative paths such as HTML/SVG. This standard proposes a contract-based directory to simplify the mapping between local web contents and on-chain web contents. Further, with relative paths referenced in the web contents and EIP-4804, the users will have a consistent view of the web contents locally and on-chain.
## Specification
### Directory
#### Methods
##### write
Writes binary `data` to the file `name` in the directory by an account with write permission.
```
function write(bytes memory name, bytes memory data) external payable
```
##### read
Returns the binary `data` from the file `name` in the directory and existence of the file.
```
function read(bytes memory name) external view returns (bytes memory data, bool exist)
```
##### fallback read
Returns the binary `data` from the file `prefixedName` (prefixed with `/`) in the directory.
```
fallback(bytes calldata prefixedName) external returns (bytes memory data)
```
##### size
Returns the size of the `data` from the file `name` in the directory and the number of chunks of the data.
```
function size(bytes memory name) external view returns (uint256 size, uint256 chunks)
```
##### remove
Removes the file `name` in the directory and returns the number of chunks removed (0 means the file does not exist) by an account with write permission.
```
function remove(bytes memory name) external returns (uint256 numOfChunksRemoved)
```
##### countChunks
Returns the number of chunks of the file `name`.
```
function countChunks(bytes memory name) external view returns (uint256 numOfChunks);
```
##### writeChunk
Writes a chunk of data to the file by an account with write permission. The write will fail if `chunkId > numOfChunks`, i.e., the write must append the file or replace the existing chunk.
```
function writeChunk(bytes memory name, uint256 chunkId, bytes memory chunkData) external payable;
```
##### readChunk
Returns the chunk data of the file `name` and the existence of the chunk.
```
function readChunk(bytes memory name, uint256 chunkId) external view returns (bytes memory chunkData, bool exist);
```
##### chunkSize
Returns the size of a chunk of the file `name` and the existence of the chunk.
```
function chunkSize(bytes memory name, uint256 chunkId) external view returns (uint256 chunkSize, bool exist);
```
##### removeChunk
Removes a chunk of the file `name` and returns `false` if such chunk does not exist. The method should be called by an account with write permission.
```
function removeChunk(bytes memory name, uint256 chunkId) external returns (bool exist);
```
##### truncate
Removes the chunks of the file `name` in the directory from the given `chunkId` and returns the number of chunks removed by an account with write permission. When `chunkId = 0`, the method is essentially the same as `remove()`.
```
function truncate(bytes memory name, uint256 chunkId) external returns (uint256 numOfChunksRemoved);
```
##### getChunkHash
Returns the hash value of the chunk data.
```
function getChunkHash(bytes memory name, uint256 chunkId) external view returns (bytes32);
```
## Rationale
One issue of uploading the web contents to the blockchain is that the web contents may be too large to fit into a single transaction. As a result, the standard provides chunk-based operations so that uploading a content can be split into several transactions. Meanwhile, the read operation can be done in a single transaction, i.e., with a single Web3 URL defined in EIP-4804.
### Interactions Between Unchunked/Chunked Functions
`read` method should return the concatenated chunked data written by `writeChunk` method. The following gives some examples of the interactions:
- `read("hello.txt")` => "" (file is empty)
- `writeChunk("hello.txt", 0, "abc")` will succeed
- `read("hello.txt")` => "abc"
- `writeChunk("hello.txt", 1, "efg")` will succeed
- `read("hello.txt")` => "abcefg"
- `writeChunk("hello.txt", 0, "aaa")` will succeed (replace chunk 0's data)
- `read("hello.txt")` => "aaaefg"
- `writeChunk("hello.txt", 3, "hij")` will fail because the operation is not replacement or append.
With `writeChunk` method, we allow writing a file with external data that exceeds the current calldata limit (e.g., 1.8MB now), and it is able to read the whole file in a single `read` method (which is friendly for large web objects such as HTML/SVG/PNG/JPG, etc).
For `write` method, calling a `write` method will replace all data chunks of the file with `write` method data, and one implementation can be:
1. `writeChunk(filename, chunkId=0, data_from_write)` to chunk 0 with the same `write` method data; and
2. `truncate(filename, chunkId=1)`, which will remove the rest chunks.
## Backwards Compatibility
No backwards compatibility issues were identified.
## Security Considerations
No security considerations were found.
## Copyright
Copyright and related rights waived via [CC0](../LICENSE.md).