Open raulk opened 4 years ago
From @nonsense's analysis:
1. cache - check if we validate already?
2. sanity checks on block.Header:
if h.ElectionProof == nil {
return xerrors.Errorf("block cannot have nil election proof")
}
if h.Ticket == nil {
return xerrors.Errorf("block cannot have nil ticket")
}
if h.BlockSig == nil {
return xerrors.Errorf("block had nil signature")
}
if h.BLSAggregate == nil {
return xerrors.Errorf("block had nil bls aggregate signature")
}
3. load parent tipset (called base tipset - `basets`)
4. lbts: get lookback tipset for round (what is that? / something to do with null rounds)
5. lbst: get `lbts` state
6. get last beacon entry (based on base tipset `basets`)
7. checking nulls / some timestamp:
nulls := h.Height - (baseTs.Height() + 1)
if tgtTs := baseTs.MinTimestamp() + build.BlockDelaySecs*uint64(nulls+1); h.Timestamp != tgtTs {
return xerrors.Errorf("block has wrong timestamp: %d != %d", h.Timestamp, tgtTs)
}
8. check that block was from the past (AllowableClockDriftSecs)
now := uint64(build.Clock.Now().Unix())
if h.Timestamp > now+build.AllowableClockDriftSecs {
return xerrors.Errorf("block was from the future (now=%d, blk=%d): %w", now, h.Timestamp, ErrTemporal)
}
if h.Timestamp > now {
log.Warn("Got block from the future, but within threshold", h.Timestamp, build.Clock.Now().Unix())
}
9. check block messages
10. check that miner is valid
11. confirm base fee (fee for the base tipset)
12. confirm parent weight (again based on `baseTs`)
13. confirm stateroot for baseTs
14. check receipts root
15. minerWorkerRaw? what is that?
16. winner check:
16.1. block should claim it is a winner
16.2. check that miner has minimum power
16.3. draw randomness
16.4. validate block election PoSt VRF
16.5. check if block miner was slashed
16.6. get power
16.7. confirm number of wins that miner claims
17. check block signature
18. validate block random beacon values
19. again validate block election PoSt VRF (based on baseTs?)
20. verify winning PoSt proof
From @nonsense's analysis:
1. verify bls aggregate signature
2. get stateroot for baseTs
3. phase 1: syntactic validation - Message.ValidForBlockInclusion?
if m.Version != 0 {
return xerrors.New("'Version' unsupported")
}
if m.To == address.Undef {
return xerrors.New("'To' address cannot be empty")
}
if m.From == address.Undef {
return xerrors.New("'From' address cannot be empty")
}
if m.Value.Int == nil {
return xerrors.New("'Value' cannot be nil")
}
if m.Value.LessThan(big.Zero()) {
return xerrors.New("'Value' field cannot be negative")
}
if m.Value.GreaterThan(TotalFilecoinInt) {
return xerrors.New("'Value' field cannot be greater than total filecoin supply")
}
if m.GasFeeCap.Int == nil {
return xerrors.New("'GasFeeCap' cannot be nil")
}
if m.GasFeeCap.LessThan(big.Zero()) {
return xerrors.New("'GasFeeCap' field cannot be negative")
}
if m.GasPremium.Int == nil {
return xerrors.New("'GasPremium' cannot be nil")
}
if m.GasPremium.LessThan(big.Zero()) {
return xerrors.New("'GasPremium' field cannot be negative")
}
if m.GasLimit > build.BlockGasLimit {
return xerrors.New("'GasLimit' field cannot be greater than a block's gas limit")
}
// since prices might vary with time, this is technically semantic validation
if m.GasLimit < minGas {
return xerrors.New("'GasLimit' field cannot be less than the cost of storing a message on chain")
}
4. phase 2: (Partial) semantic validation:
// the sender exists and is an account actor, and the nonces make sense
if !act.IsAccountActor() {
return xerrors.New("Sender must be an account actor")
}
5. check each bls message
6. check each secp message
Copied from the Chain Validation - Layer 3 requests: