forked from DecentralizedClimateFoundation/DCIPs
162 lines
5.8 KiB
Markdown
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).
|