first stab
This commit is contained in:
parent
3426611340
commit
aa5cec39ca
@ -161,6 +161,15 @@ func CidArrsEqual(a, b []cid.Cid) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func CidArrsContains(a []cid.Cid, b cid.Cid) bool {
|
||||
for _, elem := range a {
|
||||
if elem.Equals(b) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var blocksPerEpoch = NewInt(build.BlocksPerEpoch)
|
||||
|
||||
const sha256bits = 256
|
||||
|
@ -1,14 +1,21 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/minio/blake2b-simd"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
@ -27,6 +34,10 @@ func Syscalls(verifier ffiwrapper.Verifier) runtime.Syscalls {
|
||||
}
|
||||
|
||||
type syscallShim struct {
|
||||
ctx context.Context
|
||||
|
||||
cstate *state.StateTree
|
||||
cst *cbor.BasicIpldStore
|
||||
verifier ffiwrapper.Verifier
|
||||
}
|
||||
|
||||
@ -46,15 +57,122 @@ func (ss *syscallShim) ComputeUnsealedSectorCID(st abi.RegisteredProof, pieces [
|
||||
}
|
||||
|
||||
func (ss *syscallShim) HashBlake2b(data []byte) [32]byte {
|
||||
panic("NYI")
|
||||
return blake2b.Sum256(data)
|
||||
}
|
||||
|
||||
// Checks validity of the submitted consensus fault with the two block headers needed to prove the fault
|
||||
// and an optional extra one to check common ancestry (as needed).
|
||||
// Note that the blocks are ordered: the method requires a.Epoch() <= b.Epoch().
|
||||
func (ss *syscallShim) VerifyConsensusFault(a, b, extra []byte, epoch abi.ChainEpoch) (*runtime.ConsensusFault, error) {
|
||||
panic("NYI")
|
||||
// Note that block syntax is not validated. Any validly signed block will be accepted pursuant to the below conditions.
|
||||
// Whether or not it could ever have been accepted in a chain is not checked/does not matter here.
|
||||
// for that reason when checking block parent relationships, rather than instantiating a Tipset to do so
|
||||
// (which runs a syntactic check), we do it directly on the CIDs.
|
||||
|
||||
// (0) cheap preliminary checks
|
||||
|
||||
// are blocks the same?
|
||||
if bytes.Equal(a, b) {
|
||||
return nil, fmt.Errorf("no consensus fault: submitted blocks are the same")
|
||||
}
|
||||
|
||||
// can blocks be decoded properly?
|
||||
var blockA, blockB, blockC types.BlockHeader
|
||||
if decodeErr := blockA.UnmarshalCBOR(bytes.NewReader(a)); decodeErr != nil {
|
||||
return nil, errors.Wrapf(decodeErr, "cannot decode first block header")
|
||||
}
|
||||
|
||||
if decodeErr := blockB.UnmarshalCBOR(bytes.NewReader(b)); decodeErr != nil {
|
||||
return nil, errors.Wrapf(decodeErr, "cannot decode second block header")
|
||||
}
|
||||
|
||||
if len(extra) > 0 {
|
||||
if decodeErr := blockC.UnmarshalCBOR(bytes.NewReader(extra)); decodeErr != nil {
|
||||
return nil, errors.Wrapf(decodeErr, "cannot decode extra")
|
||||
}
|
||||
}
|
||||
|
||||
// (1) check conditions necessary to any consensus fault
|
||||
|
||||
// were blocks mined by same miner?
|
||||
if blockA.Miner != blockB.Miner {
|
||||
return nil, fmt.Errorf("no consensus fault: blocks not mined by same miner")
|
||||
}
|
||||
|
||||
// block a must be earlier or equal to block b, epoch wise (ie at least as early in the chain).
|
||||
if blockB.Height < blockA.Height {
|
||||
return nil, fmt.Errorf("first block must not be of higher height than second")
|
||||
}
|
||||
|
||||
// (2) check the consensus faults themselves
|
||||
var consensusFault *runtime.ConsensusFault
|
||||
|
||||
// (a) double-fork mining fault
|
||||
if blockA.Height == blockB.Height {
|
||||
consensusFault = &runtime.ConsensusFault{
|
||||
Target: blockA.Miner,
|
||||
Epoch: blockB.Height,
|
||||
Type: runtime.ConsensusFaultDoubleForkMining,
|
||||
}
|
||||
}
|
||||
|
||||
// (b) time-offset mining fault
|
||||
// strictly speaking no need to compare heights based on double fork mining check above,
|
||||
// but at same height this would be a different fault.
|
||||
if !types.CidArrsEqual(blockA.Parents, blockB.Parents) && blockA.Height != blockB.Height {
|
||||
consensusFault = &runtime.ConsensusFault{
|
||||
Target: blockA.Miner,
|
||||
Epoch: blockB.Height,
|
||||
Type: runtime.ConsensusFaultTimeOffsetMining,
|
||||
}
|
||||
}
|
||||
|
||||
// (c) parent-grinding fault
|
||||
// TODO HS: check is the blockB.height == blockA.height + 1 cond nec?
|
||||
// Here extra is the "witness", a third block that shows the connection between A and B
|
||||
// Specifically, since A is of lower height, it must be that B was mined omitting A from its tipset
|
||||
// so there must be a block C such that A and C are siblings and C is B's parent
|
||||
if types.CidArrsEqual(blockA.Parents, blockC.Parents) && types.CidArrsContains(blockB.Parents, blockC.Cid()) &&
|
||||
!types.CidArrsContains(blockB.Parents, blockA.Cid()) && blockB.Height == blockA.Height+1 {
|
||||
consensusFault = &runtime.ConsensusFault{
|
||||
Target: blockA.Miner,
|
||||
Epoch: blockB.Height,
|
||||
Type: runtime.ConsensusFaultParentGrinding,
|
||||
}
|
||||
}
|
||||
|
||||
// (3) expensive final checks
|
||||
|
||||
// check blocks are properly signed by their respective miner
|
||||
// note we do not need to check extra's: it is a parent to block b
|
||||
// which itself is signed, so it was willingly included by the miner
|
||||
if sigErr := ss.VerifyBlockSig(&blockA); sigErr != nil {
|
||||
return nil, errors.Wrapf(sigErr, "cannot verify first block sig")
|
||||
}
|
||||
|
||||
if sigErr := ss.VerifyBlockSig(&blockB); sigErr != nil {
|
||||
return nil, errors.Wrapf(sigErr, "cannot verify first block sig")
|
||||
}
|
||||
|
||||
return consensusFault, nil
|
||||
}
|
||||
|
||||
func (ss *syscallShim) VerifyBlockSig(blk *types.BlockHeader) error {
|
||||
|
||||
// // load actorState
|
||||
|
||||
// // get publicKeyAddr
|
||||
// waddr := ss.ResolveToKeyAddr(ss.cstate, ss.cst, mas.Info.Worker)
|
||||
|
||||
if err := sigs.CheckBlockSignature(blk, ss.ctx, waddr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *syscallShim) VerifyPoSt(proof abi.PoStVerifyInfo) error {
|
||||
ok, err := ss.verifier.VerifyFallbackPost(context.TODO(), proof)
|
||||
ok, err := ss.verifier.VerifyFallbackPost(ss.ctx, proof)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user