总结:
let hash_num = <Tree::Hasher as Hasher>::Function::hash2_circuit(
mbi, err := m.api.MinerGetBaseInfo(ctx, addr, round, base.TipSet.Key())let hash = hasher.result();
rand, err := m.api.ChainGetRandomness(ctx, base.TipSet.Key(), crypto.DomainSeparationTag_WinningPoStChallengeSeed, base.TipSet.Height()+base.NullRounds, nil)
.map(Into::into)
let comm_c_num = num::AllocatedNum::alloc(cs.namespace(|| "comm_c"), || {
}
Lotus的PoSt的部门从electionPoSt酿成两种新的PoSt,一种是winningPoSt,一种是windowPoSt。先讲讲winningPoSt吧。winningPoSt,顾名思义,,在winning的时候举办的PoSt。所谓的winning,也就是获取出块权。
简朴的说,winningPoSt,随机抽查的一个sector,该sector中的66条随机抽查的merkle path都正确。代码逻辑从Lotus的go的代码说起。一切从出块开始 - lotus/miner/miner.go的Miner布局的mineOne函数。Root::Val(*leaf),
&comm_r_num,
let mut hasher = Sha256::new();
})?;
})?;
4. 零常识证明电路
因为这些逻辑的详细实现是在rust-fil-proofs,也就是rust语言实现的。从go到rust-fil-proofs,超过了不少接口:
comm_r_num.inputize(cs.namespace(|| "comm_r_input"))?;
.ok_or_else(|| SynthesisError::AssignmentMissing)
)?;
中间的接口就不先容了,直接看rust-fil-proofs提供的两个API函数。
postProof, err := m.epp.ComputeProof(ctx, mbi.Sectors, prand)
讲讲rust-fil-proofs/post/fallback/circuit.rs中的Sector布局吧。这个布局就代表一个抽查。从synthesize函数可以看出:
let comm_r_num = num::AllocatedNum::alloc(cs.namespace(|| "comm_r"), || {
个中,MinerGetBaseInfo函数是获取一些根基信息,个中包罗需要抽取的sector信息。ComputeProof函数就是计较winningPoSt证明。
hasher.input(AsRef::<[u8]>::as_ref(&randomness));
hasher.input(§or_id.to_le_bytes()[..]);
let comm_r_last_num = num::AllocatedNum::alloc(cs.namespace(|| "comm_r_last"), || {
generate_winning_post_sector_challenge函数实现了Sector的抽查逻辑。焦点逻辑显然是如何抽查Sector?详细的逻辑在fallback::generate_sector_challenges的函数中:
|| "enforce_comm_c_comm_r_last_hash_comm_r",
}
// 1. Verify H(Comm_C || comm_r_last) == comm_r
let hash = hasher.result();
cs.namespace(|| format!("challenge_inclusion_{}", i)),
prand := abi.PoStRandomness(rand)
for (i, (leaf, path)) in leafs.iter().zip(paths.iter()).enumerate() {
hasher.input(AsRef::<[u8]>::as_ref(&prover_id));
pub const WINNING_POST_CHALLENGE_COUNT: usize = 66;
let challenged_range_index = leaf_challenge % (pub_params.sector_size / NODE_SIZE as u64);
.ok_or_else(|| SynthesisError::AssignmentMissing)
let leaf_challenge = LittleEndian::read_u64(&hash.as_ref()[..8]);
3. Challenge的叶子抽查逻辑
pub const WINNING_POST_SECTOR_COUNT: usize = 1;
// Check actual equality
PoRCircuit::<Tree>::synthesize(
Sector个数以及总的抽查的叶子个数的界说在rust-fil-proofs/filecoin-proofs/src/constants.rs中:
Filecoin - PoREP电路先容
let mut hasher = Sha256::new();
)?;
// 2. Verify Inclusion Paths
hasher.input(&n.to_le_bytes()[..]);
comm_r
.map(Into::into)
hasher.input(&leaf_challenge_index.to_le_bytes()[..]);
let sector_index = sector_challenge % sector_set_len;
零常识证明的计较部门可以查察rust-fil-proofs/post/fallback目次。概略的逻辑模块和布局可以查察之前的文章先容:
&comm_c_num,
{
generate_winning_post在抽查的Sector形成的merkle树(replica_r_last)上,抽查叶子节点。抽查叶子节点的计较逻辑在fallback::generate_leaf_challenge的函数中:
hasher.input(AsRef::<[u8]>::as_ref(&randomness));
constraint::equal(
func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningBase) (*types.BlockMsg, error) {
&hash_num,
简朴的说,就是把prover_id, 随机信息,抽查Sector的编号做sha256的hash计较,计较功效和当前有限的Sector个数取模。也就是sector_index就是最终抽查的Sector的id。
comm_r_last
comm_r作为public输入,其他comm_r_last和comm_c作为private输入。
Lotus的PoSt包罗两部门:winningPoSt和windowPoSt。winningPoSt是在获取出块权时,需要提供的PoSt证明。从所有有效的Sector中,抽取一个Sector,并抽查该Sector上的66个叶子。
.map(Into::into)
.ok_or_else(|| SynthesisError::AssignmentMissing)
comm_c
验证comm_r是否由comm_c和comm_r_last计较获得。
Root::from_allocated::<CS>(comm_r_last_num.clone()),
cs,
cs.namespace(|| "H_comm_c_comm_r_last"),
验证从叶子节点是否可以正确计较出Merkle树根。
);
1. 抽查个数配置
2. Sector的抽查逻辑
let sector_challenge = LittleEndian::read_u64(&hash.as_ref()[..8]);
也就是说,要从有效Sector中抽取一个Sector,并在这个Sector上抽查66个叶子节点。
把随机信息,sector id和挑战叶子的编号举办hash计较。计较的功效和叶子的总个数取模。32G的Sector,叶子个数为1G个。
true,
})?;
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。