lotus/cmd/lotus-sim/simulation/mock/mock.go
Steven Allen 52261fb814 refactor(lotus-sim): enterprise grade
While the previous version "worked", this version nicely separates out
the state for the separate stages. Hopefully, we'll be able to use this
to build different pipelines with different configs.
2021-06-18 15:44:36 -07:00

155 lines
4.6 KiB
Go

package mock
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner"
proof5 "github.com/filecoin-project/specs-actors/v5/actors/runtime/proof"
tutils "github.com/filecoin-project/specs-actors/v5/support/testing"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
)
// Ideally, we'd use extern/sector-storage/mock. Unfortunately, those mocks are a bit _too_ accurate
// and would force us to load sector info for window post proofs.
const (
mockSealProofPrefix = "valid seal proof:"
mockAggregateSealProofPrefix = "valid aggregate seal proof:"
mockPoStProofPrefix = "valid post proof:"
)
// mockVerifier is a simple mock for verifying "fake" proofs.
type mockVerifier struct{}
var Verifier ffiwrapper.Verifier = mockVerifier{}
func (mockVerifier) VerifySeal(proof proof5.SealVerifyInfo) (bool, error) {
addr, err := address.NewIDAddress(uint64(proof.Miner))
if err != nil {
return false, err
}
mockProof, err := MockSealProof(proof.SealProof, addr)
if err != nil {
return false, err
}
return bytes.Equal(proof.Proof, mockProof), nil
}
func (mockVerifier) VerifyAggregateSeals(aggregate proof5.AggregateSealVerifyProofAndInfos) (bool, error) {
addr, err := address.NewIDAddress(uint64(aggregate.Miner))
if err != nil {
return false, err
}
mockProof, err := MockAggregateSealProof(aggregate.SealProof, addr, len(aggregate.Infos))
if err != nil {
return false, err
}
return bytes.Equal(aggregate.Proof, mockProof), nil
}
func (mockVerifier) VerifyWinningPoSt(ctx context.Context, info proof5.WinningPoStVerifyInfo) (bool, error) {
panic("should not be called")
}
func (mockVerifier) VerifyWindowPoSt(ctx context.Context, info proof5.WindowPoStVerifyInfo) (bool, error) {
if len(info.Proofs) != 1 {
return false, fmt.Errorf("expected exactly one proof")
}
proof := info.Proofs[0]
addr, err := address.NewIDAddress(uint64(info.Prover))
if err != nil {
return false, err
}
mockProof, err := MockWindowPoStProof(proof.PoStProof, addr)
if err != nil {
return false, err
}
return bytes.Equal(proof.ProofBytes, mockProof), nil
}
func (mockVerifier) GenerateWinningPoStSectorChallenge(context.Context, abi.RegisteredPoStProof, abi.ActorID, abi.PoStRandomness, uint64) ([]uint64, error) {
panic("should not be called")
}
// MockSealProof generates a mock "seal" proof tied to the specified proof type and the given miner.
func MockSealProof(proofType abi.RegisteredSealProof, minerAddr address.Address) ([]byte, error) {
plen, err := proofType.ProofSize()
if err != nil {
return nil, err
}
proof := make([]byte, plen)
i := copy(proof, mockSealProofPrefix)
binary.BigEndian.PutUint64(proof[i:], uint64(proofType))
i += 8
i += copy(proof[i:], minerAddr.Bytes())
return proof, nil
}
// MockAggregateSealProof generates a mock "seal" aggregate proof tied to the specified proof type,
// the given miner, and the number of proven sectors.
func MockAggregateSealProof(proofType abi.RegisteredSealProof, minerAddr address.Address, count int) ([]byte, error) {
proof := make([]byte, aggProofLen(count))
i := copy(proof, mockAggregateSealProofPrefix)
binary.BigEndian.PutUint64(proof[i:], uint64(proofType))
i += 8
binary.BigEndian.PutUint64(proof[i:], uint64(count))
i += 8
i += copy(proof[i:], minerAddr.Bytes())
return proof, nil
}
// MockWindowPoStProof generates a mock "window post" proof tied to the specified proof type, and the
// given miner.
func MockWindowPoStProof(proofType abi.RegisteredPoStProof, minerAddr address.Address) ([]byte, error) {
plen, err := proofType.ProofSize()
if err != nil {
return nil, err
}
proof := make([]byte, plen)
i := copy(proof, mockPoStProofPrefix)
i += copy(proof[i:], minerAddr.Bytes())
return proof, nil
}
// makeCommR generates a "fake" but valid CommR for a sector. It is unique for the given sector/miner.
func MockCommR(minerAddr address.Address, sno abi.SectorNumber) cid.Cid {
return tutils.MakeCID(fmt.Sprintf("%s:%d", minerAddr, sno), &miner5.SealedCIDPrefix)
}
// TODO: dedup
func aggProofLen(nproofs int) int {
switch {
case nproofs <= 8:
return 11220
case nproofs <= 16:
return 14196
case nproofs <= 32:
return 17172
case nproofs <= 64:
return 20148
case nproofs <= 128:
return 23124
case nproofs <= 256:
return 26100
case nproofs <= 512:
return 29076
case nproofs <= 1024:
return 32052
case nproofs <= 2048:
return 35028
case nproofs <= 4096:
return 38004
case nproofs <= 8192:
return 40980
default:
panic("too many proofs")
}
}