飞行的蜗牛

vuePress-theme-reco 极客学长    2013 - 2025
飞行的蜗牛 飞行的蜗牛

Choose mode

  • dark
  • auto
  • light
首页
分类
  • 技术杂谈
  • Database
  • Docker
  • PHP
  • 随笔杂谈
  • 前端开发
  • FunnyTools
  • Jekyll
  • 读书笔记
  • Java
  • SpringBoot
  • 区块链技术
  • IPFS
  • C/C++
  • Filecoin
  • Golang
  • Sharding-JDBC
  • 分布式存储
  • Lotus-源码系列
  • Lotus
  • 框架源码系列
  • Spring-源码系列
  • AI
  • ChatGPT
  • Stable Diffusion
  • DeepSeek-R1
  • DeepSeek-V3
标签
时间抽
关于作者
开源项目
GeekAI (opens new window)
author-avatar

极客学长

154

文章

151

标签

首页
分类
  • 技术杂谈
  • Database
  • Docker
  • PHP
  • 随笔杂谈
  • 前端开发
  • FunnyTools
  • Jekyll
  • 读书笔记
  • Java
  • SpringBoot
  • 区块链技术
  • IPFS
  • C/C++
  • Filecoin
  • Golang
  • Sharding-JDBC
  • 分布式存储
  • Lotus-源码系列
  • Lotus
  • 框架源码系列
  • Spring-源码系列
  • AI
  • ChatGPT
  • Stable Diffusion
  • DeepSeek-R1
  • DeepSeek-V3
标签
时间抽
关于作者
开源项目
GeekAI (opens new window)
  • Lotus 源码研究 03 - 源码目录结构

    • api
      • blockstore
        • build
          • chain(二级关注)
            • cli(一级关注)
              • cmd(一级关注)
                • documentation
                  • extern/filecoin-ffi
                    • extern/sector-storage (一级关注)
                      • extern/storage-sealing(一级关注)
                        • gen
                          • journal
                            • lib
                              • lotuspond
                                • markets(二级关注)
                                  • miner(二级关注)
                                    • node(一级关注)
                                      • paychmgr
                                        • scripts
                                          • storage(一级关注)
                                            • tools

                                            Lotus 源码研究 03 - 源码目录结构

                                            vuePress-theme-reco 极客学长    2013 - 2025

                                            Lotus 源码研究 03 - 源码目录结构


                                            极客学长 2021-09-14 0 Lotus源码 Filecoin

                                            南怀瑾

                                            佛为心,道为骨,儒为表,大度看世界;技在手,能在身,思在脑,从容过生活。

                                            记得年初的时候在写博客更新计划的时候,我立了一个 Flag:今年要写一个系列的 Lotus 源码解析文章。 但是目前只写了 2 篇,一篇是写如何开始源码研究,另一篇是 Lotus 1.10.0 FinalizeFailed Bug 修复方法。近期因为忙着原语云的产品优化以及培训业务,忙得不亦乐乎,差点忘了这事情了。 本着 自己装的逼,跪着也要实现 的精神,后期要尽量抽出时间把这个系列的文章写完。今天我们从 Lotus 源码的目录结构开始。

                                            一个软件的目录结构其实在一定程度上体现了它的架构,通过对整个 Lotus 目录结构的解读,你基本能大概知道 Lotus 源码中到底包含了哪些模块 和开发者的设计思路。

                                            源码版本:https://github.com/filecoin-project/lotus/releases/tag/v1.11.2

                                            下面介绍当前最新 Release 版本(v1.11.2)的 lotus 源码的主要目录结构,有些开发者不需要关注的目录就直接略过了。

                                            # api

                                            见名知意,这个目下主要存放 API 相关程序,Lotus 是一个大型的区块链项目,模块之间基本都通过 API 来通信,远程 API 的调用走的是 JSONRPC 调用模式,比如 Miner 上链要调用 Lotus Chain 的 API,Worker 和 Miner 之间通信也是相互调用 API。

                                            本目录抽象了节点定义,定义了若干go interface,如 Common(定义节点通用功能)、FullNode (定义一个全节点的行为,继承自Common)、StorageMiner(存储矿工,也从Common继承)和相关的函数。 这里有几个重要的接口:

                                            1. Common: 定义了一些节点通用的功能,在 api_common.go 中定义。
                                            2. FullNode: 定义一个全节点的所有 API,继承自 Common,在 api_full.go 中定义。
                                            3. StorageMiner: 定义一个存储矿工的行为,继承自 Common,在 api_storage.go 中定义。

                                            值得一提的是,Lotus 是使用代理模式实现上述接口的,一旦你对接口进行了更改,你需要执行:

                                            make gen
                                            

                                            该命令会生成一个 api/proxy_gen.go 文件,自动为上述接口生成一个对应的 struct,分别为CommonStruct,FullNodeStruct,StorageMinerStruct,这些实现只是简单地将请求转发给各自的Internal成员, 具体的功能函数需要使用者提供,比如获取扇区列表 SectorList API 的实现如下:

                                            func (s *StorageMinerStruct) SectorsList(p0 context.Context) ([]abi.SectorNumber, error) {
                                            	return s.Internal.SectorsList(p0)
                                            }
                                            

                                            切记:每次更改了 API 要记得执行 make gen 重新生成 API 代理文件 proxy_gen.go,否则编译的时候会提示找不到 API 方法。

                                            # blockstore

                                            区块存储工具包,包括区块的新增,删除,以及同步相关的 API,这里做了几种实现,有 leveldb 版本,内存(mem.go)版本以及 IPFS 版本的实现。

                                            IPFS 版本实现:

                                            func (i *IPFSBlockstore) DeleteBlock(cid cid.Cid) error
                                            
                                            func (i *IPFSBlockstore) Has(cid cid.Cid) (bool, error)
                                            
                                            func (i *IPFSBlockstore) Get(cid cid.Cid) (blocks.Block, error)
                                            
                                            func (i *IPFSBlockstore) Put(block blocks.Block) error
                                            

                                            内存版本实现:

                                            func NewMemory() MemBlockstore {
                                            	return make(MemBlockstore)
                                            }
                                            
                                            // MemBlockstore is a terminal blockstore that keeps blocks in memory.
                                            type MemBlockstore map[cid.Cid]blocks.Block
                                            
                                            func (m MemBlockstore) DeleteBlock(k cid.Cid) error {
                                            	delete(m, k)
                                            	return nil
                                            }
                                            
                                            func (m MemBlockstore) Get(k cid.Cid) (blocks.Block, error) {
                                            	b, ok := m[k]
                                            	if !ok {
                                            		return nil, ErrNotFound
                                            	}
                                            	return b, nil
                                            }
                                            
                                            func (m MemBlockstore) Has(k cid.Cid) (bool, error) {
                                            	_, ok := m[k]
                                            	return ok, nil
                                            }
                                            

                                            # build

                                            定义用于构建节点,创建网络相关功能,包括但不限于定义网络相关配置(如 params_main.go),定义创世节点相关信息(genesis目录), 以及创世节点的连接信息(bootstrap目录),复制证明参数下载地址配置等。

                                            # chain(二级关注)

                                            顾名思义,就是实现了 Louts 链相关的功能,主要包含了如下子模块:

                                            • types: 定义 Louts 链中的各种数据结构。
                                            • store: 公链存储相关,处理所有的本地链状态,包括链头、消息和状态等。
                                            • messagesinger: 消息签名工具包。
                                            • messagepool:消息池,定义消息打包规则。
                                            • wallet:实现钱包相关工具。
                                            • state: 处理 Filecoin 的状态树,内部包装了HAMT。
                                            • actors: 账户体系,定义了各种 actor。
                                            • vm: 智能合约虚拟机,这里实现了actor 的方法调用工具包。

                                            # cli(一级关注)

                                            Lotus命令行工具的实现,里面的go文件名基本上与Lotus的子命令保持一致,比如:

                                            • state.go: 对应 lotus state 命令
                                            • sync.go: 对应 lotus sync 命令
                                            • wallet.go: 对应 lotus wallet 命令
                                            • ...

                                            对应于每条子命令及子命令的子命令,都定义了一个Command对象,比如 wallet.go:

                                            // 每个条命定义了若干子命令对象
                                            var walletCmd = &cli.Command{
                                            	Name:  "wallet",
                                            	Usage: "Manage wallet",
                                            	Subcommands: []*cli.Command{
                                            		walletNew,
                                            		walletList,
                                            		walletBalance,
                                            		walletExport,
                                            		walletImport,
                                            		walletGetDefault,
                                            		walletSetDefault,
                                            		walletSign,
                                            		walletVerify,
                                            		walletDelete,
                                            		walletMarket,
                                            	},
                                            }
                                            
                                            // 每个子命令对象单独实现一个功能
                                            var walletNew = &cli.Command{
                                            	Name:      "new",
                                            	Usage:     "Generate a new key of the given type",
                                            	ArgsUsage: "[bls|secp256k1 (default secp256k1)]",
                                            	Action: func(cctx *cli.Context) error {
                                            		api, closer, err := GetFullNodeAPI(cctx)
                                            		if err != nil {
                                            			return err
                                            		}
                                            		defer closer()
                                            		ctx := ReqContext(cctx)
                                            
                                            		t := cctx.Args().First()
                                            		if t == "" {
                                            			t = "secp256k1"
                                            		}
                                            
                                            		nk, err := api.WalletNew(ctx, types.KeyType(t))
                                            		if err != nil {
                                            			return err
                                            		}
                                            
                                            		fmt.Println(nk.String())
                                            
                                            		return nil
                                            	},
                                            }
                                            

                                            # cmd(一级关注)

                                            包括 Lotus 项目所有的命令行项目,Lotus 将系统分为不同的进程模块,为每个模块定义一个项目:

                                            模块名称 模块说明
                                            lotus lotus 守护进程项目,负责与 lotus 公链通信,同步区块,是主要核心进程之一
                                            lotus-miner 存储矿工的核心进程,负责时空证明,爆块,任务调度,是主要核心进程之一
                                            lotus-seal-worker 数据密封主进程,整个复制证明工作由该进程完成,是主要核心进程之一
                                            lotus-bench 基准测试工具项目,如果你要做性能优化,那么这个工具应该要经常使用
                                            lotus-seed 用来生成创世区块的工具,构建网络不可或缺
                                            lotus-shed 非常有用的一个工具包命令集合,里面又各种黑科技命令,比如终止扇区,修复消息池,多重签名工具等。

                                            每个模块都可以单独编译,编译后的程序都可以单独启动一个进程独立运行:

                                            # 编译 lotus 程序
                                            make lotus
                                            # 编译 miner 程序
                                            make lotus-miner
                                            # 编译 worker 程序
                                            make lotus-worker
                                            # 编译 bench 测试工具
                                            make lotus-bench
                                            # 编译钱包工具
                                            make lotus-wallet
                                            

                                            你切换到 lotus 代码根目录下,然后输入 make 按 Tab 键就可以呼出各种编译命令:

                                            # documentation

                                            Lotus的文档目录,Lotus计划提供中英文两种文字的文档,目前已有的文档主要涉及以下方面:

                                            • 新手指导.
                                            • 构建 Lotus.
                                            • 如何启动 lotus, lotus-miner, lotus-worker.
                                            • 如何运行本地开发网络.
                                            • Pond介绍
                                            • Lotus API 接口说明

                                            # extern/filecoin-ffi

                                            FFI rust 调用封装,Lotus 的源码分两部分,公链和任务调度这块是 Golang 实现的,另外一些底层计算都是通过调用 Rust 底层库去计算的。比如 PC1,PC2,C1,C2,时空证明等都是用 Rust 实现的。 Lotus 通过 filecoin-ffi 这个组件来调用 Rust 底层库。

                                            # extern/sector-storage (一级关注)

                                            这里包含了任务调度,资源分配的的核心代码。属于整个项目比较核心的部分。

                                            • sealtasks: 定义了一些任务类别常量,如:
                                              const (
                                              	TTAddPiece   TaskType = "seal/v0/addpiece"
                                              	TTPreCommit1 TaskType = "seal/v0/precommit/1"
                                              	TTPreCommit2 TaskType = "seal/v0/precommit/2"
                                              	TTCommit1    TaskType = "seal/v0/commit/1" // NOTE: We use this to transfer the sector into miner-local storage for now; Don't use on workers!
                                              	TTCommit2    TaskType = "seal/v0/commit/2"
                                              	TTFinalize TaskType = "seal/v0/finalize"
                                              	TTFetch TaskType = "seal/v0/fetch"
                                              )
                                              
                                            • stores: 扇区存储相关代码,实现了扇区检索(index.go), 本地存储(local.go),远程存储(remote.go)等。
                                            • storiface: 定义远程调用相关 API
                                            • worker: worker 相关功能和属性定义
                                            • manager.go: 全局管理对象,调度入口程序,它管理着 Worker,存储,以及调度等对象。
                                            • sched.go: 任务调度的具体实现

                                            # extern/storage-sealing(一级关注)

                                            这也是 Lotus 的核心模块之一,它包含如下代码:

                                            • 扇区状态机实现(fsm.go)
                                            • 扇区的各种事件定义(event.go)
                                            • 扇区聚合提交上链(precommit_batch.go, commit_batch.go)
                                            • sealing 相关的 API 实现

                                            # gen

                                            API 代理对象的生成工具,略过即可。

                                            # journal

                                            journal 日志工具,略过即可。

                                            # lib

                                            实现 lotus 项目各模块公用的函数,主要有下面几个模块:

                                            • addrutil: 地址解析工具
                                            • backupds: lotus/lotus-miner 元数据备份工具
                                            • lotuslog: 定义 lotus 相关程序的日志等级
                                            • rpcenc: RPC 调用数据编码工具
                                            • sigs: 钱包签名工具包,包括 bls 和 secp256k 两种实现
                                            • **ulimit:**lotus 相关程序运行时的 FD 设置工具,主要用来设置 lotus-miner 程序的最大打开文件数。

                                            # lotuspond

                                            Pond 项目目录,Pond 是一个用于管理 Lotus 的UI工具,可用于建立一个独立的本地网络以方便调试。 Pond会启动节点,使用指定的拓扑进行连接,启动 Miner,并持续监控节点运行状况。不过我个人觉得这个项目没什么卵用 O(∩_∩)O~。

                                            # markets(二级关注)

                                            Filecoin 订单市场相关实现,包括订单的过滤,订单价格,以及存储订单和检索订单的适配器等。

                                            # miner(二级关注)

                                            爆块主程序,定义产出区块完整逻辑。

                                            # node(一级关注)

                                            定义了 lotus 节点相关的 struct 和 interface 等,各主要子目录如下:

                                            • config: 定义节点相关配置结构体
                                            • hello: 实现 hello 协议
                                            • modules: 定义实现节点功能的各种函数,比较重要的有 chain.go, storageminer.go 等。
                                            • impl: 节点各种 API 的实现,比如 full.go 实现全节点的相关 API,storminer.go 实现存储节点相关 API 等。
                                            • repo: 链上数据在本地的存储仓库,与本地文件系统打交道。

                                            # paychmgr

                                            各种支付凭证管理,定义了一些支付通道的 API。

                                            # scripts

                                            各种运行脚本,用于部署节点和矿工等,也包括一些用于启动的配置文件。

                                            # storage(一级关注)

                                            定义存储矿工逻辑,用于实现"lotus-storage-miner",时空证明的主程序逻辑也是在这里实现的。

                                            # tools

                                            各种打包工具封装,如使用 docker 部署 Lotus 等。

                                            1. 标注 一级关注 的模块是跟任务调度,密封相关的内容,这块的内容通常你最先去触碰并修改的, 通常这些模块你修改的需求最多,同时也是你能发挥的空间最大的地方。

                                            2. 标注 二级关注 的模块是跟链,以及爆块,时空证明相关的,再抽象一点归纳就是:它们都是跟共识有关, 显然相对前面的模块来说,你能修改的不多,因为如果你能随意修改的话,那就不叫共识了。建议有有需要了再去折腾那些,比如优化爆块程序,调试存储订单相关,以及实现多 Miner 方案的时候,通常你需要折腾这几个模块。

                                            3. 其他模块都是工具性的,对你理解 Lotus 原理几乎没有障碍,前期你完全可以直接忽略他们。 当然,如果你有特殊需求的,比如你要研究加密原理,多重签名算法等的时候,你可以试着去折腾一下相关工具类模块。

                                            相信在了解完 Lotus 源码的目录结构之后,你应该在脑子里面应该形成了一个大概的框架, 同时对于如此庞大的项目,你可能心生畏惧,没关系,这是人之常情。对于大型项目的研究,我们要有日拱一卒的决心,正所谓千里之行,始于足下,下篇文章我们就从一个小功能开始真正进行 Lotus 开发之旅。

                                            本站博文如非注明转载则均属作者原创文章,引用或转载无需申请版权或者注明出处,如需联系作者请加微信: geekmaster01

                                            使用原语云快速部署 Lotus 集群 Lotus 源码研究 04 - 小试牛刀