BlockChain-Solidity 虚拟文件系统 VFS

Solidity 虚拟文件系统 VFS

VFS 背景

为了能够支持在所有平台上进行可重复的构建,Solidity 编译器必须抽离存储源文件的文件系统的细节。 由于这个原因,导入路径并不直接指向主机文件系统中的文件。

编译器维护一个内部数据库( 虚拟文件系统 或简称 VFS ),其中每个源单元都被分配了一个唯一的源标识(Source Unit Name) ,这是一个不透明的、非结构化的标识符。 在导入语句中指定的导入路径被翻译成源标识,并用于在这个数据库中找到相应的源标识。

VFS Import Callback

VFS 初始化时,只把编译器接收的文件做为输入,其他文件在编译时通过 Import Callback 进行加载。当编译器在VFS中匹配不到导入的源标识(Source Unit Name)时,它调用Import Callback 进行获取。如果也获取不到,则编译失败。

Import Callback 可以将单位元进行自定义解析,不一定是路径。

  • 命令行编译器提供了Host Filesystem Loader,将源标识解析成本地系统的文件路径(Host Filesystem Loader 文件查找是跟操作系统相关的,例如 WINDOWS 跟 LINUX 路径表示就不同,所以尽量使用各个系统都通用的路径,例如用斜杠而不用反斜杠)
  • Solc-js等 JS 编译器不默认提供,因为它可能是运行在浏览器端,需要由用户提供 File Loader。例如 Remix,提供了支持 HTTP, IPFS 、短 URLs 或者 NPM 包的多元化 callback

VFS 初始化

取决于怎么调用编译器

通过 solc 或者命令行

1
solc contract.sol /usr/local/dapp-bin/token.sol,直接通过路径初始化,最好用相对路径

通过标准 JSON:–standard-json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"language": "Solidity",
"sources": {
"contract.sol": {
"content": "import \"./util.sol\";\ncontract C {}"
},
"util.sol": {
"content": "library Util {}"
},
"/usr/local/dapp-bin/token.sol": {
"content": "contract Token {}"
}
},
"settings": {"outputSelection": {"*": { "*": ["metadata", "evm.bytecode"]}}}
}

通过 Import Callback 的标准 JSON

编译器通过调用 Callback 挨个尝试加载里面的 Urls,直到有一个成功获取

1
2
3
4
5
6
7
8
9
10
11
12
{
"language": "Solidity",
"sources": {
"/usr/local/dapp-bin/token.sol": {
"urls": [
"/projects/mytoken.sol",
"https://example.com/projects/mytoken.sol"
]
}
},
"settings": {"outputSelection": {"*": { "*": ["metadata", "evm.bytecode"]}}}
}

通过标准的直接输入

1
2
echo 'import "./util.sol"; contract C {}' | solc -
- 符号用来指示编译器将内容放到一个特殊的源标识:<stdin>