seal_pre_commit_phase2 generates three trees tree_c
, tree_d
, tree_r_last
and comm_r
.
seal_pre_commit_phase2
recives SealPreCommitPhase1Output as input this includes:
let SealPreCommitPhase1Output {
// the original data split into 11 layers x 32GiB
mut labels,
// StoreConfig relating to a binary tree of the original data
mut config,
// root of merkel tree above
comm_d,
..
} = phase1_output;
TODO: write about vanilla proofs
Here you can find a visual explination of the tree constuction process: figma
Tree_c
is generated here and depends on the layer arity for choosing the ColumnArity
and TreeArity
.
tree_c
can be generated using GPU or CPU this is detemened by the flags you use while compiling your client. For the sake of simplicity we will cover the CPU version. The GPU version is identical but abit more complex.
generate_tree_c_cpu recives the following inputs:
// number of layers, this is determind by the sector size.
layers: usize
// number of nodes per BaseTree (total_nodes / num_of_base_trees)
nodes_count: usize
// number of BaseTree
tree_count: usize
// number of congifs (one config per BaseTree)
configs: Vec<StoreConfig>
// the acctual data we are going to build the tree from
labels: &LabelsCache<Tree>
To understand how trees are constructed in filecoin please read this.
- First we allocate a Vec to store the tree in.
- Depending on the
nodes_count
andnum_cpus::get()
we generate chunck sizes in which we shall process the data. - We then proceed to read the data in columns numbering 11 elements. Which are used as preimages and hashed with Poseidon hash. The resulting hash in stored in the Vec created at stage 1.
The process defined above is executed for each Config (repersenting a BaseTree). Each time a BaseTree has been hashed its passed to DiskTree::<Tree::Hasher, Tree::Arity, U0, U0>::from_par_iter_with_config which persists the BaseTree to disk.
Once all BaseTrees have been constructed we call:
create_disk_tree::<DiskTree<Tree::Hasher, Tree::Arity, Tree::SubTreeArity, Tree::TopTreeArity>,>(configs[0].size.expect("config size failure"), &configs)
At this stage the root of the final tree is calculated and we have a complete tree persisted on disk.
Tree_d
is originally construcuted in PC1 phase. However if not found in PC2 phase tree_d
will be consturcted as part of PC2 phase.
tree_r_last
is constructed from the very last layer found in the replica (layer 11).
tree_r_last
can also be constructed usign eather GPU or CPU. Im more familer with the GPU implementation and will cover it.
- Layer 11 is split into chunks of 700k elements.
- These chuncks are then hashed by Poseidon(8 + 1) -> 1.
- The trees are constructed using a TreeBuilder
- Finally the complete tree is persisted to disk.
comm_r is simply a sha256 hash of tree_c_root
and tree_r_last_root
.