b7a4dbb07f
And use the new CidBuilder from the spec actors. This patch does not switch over to inline CIDs by default, but paves the way.
625 lines
16 KiB
Go
625 lines
16 KiB
Go
package gen
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/filecoin-project/go-address"
|
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
|
saminer "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
|
"github.com/filecoin-project/specs-actors/actors/crypto"
|
|
block "github.com/ipfs/go-block-format"
|
|
"github.com/ipfs/go-blockservice"
|
|
"github.com/ipfs/go-cid"
|
|
offline "github.com/ipfs/go-ipfs-exchange-offline"
|
|
format "github.com/ipfs/go-ipld-format"
|
|
logging "github.com/ipfs/go-log/v2"
|
|
"github.com/ipfs/go-merkledag"
|
|
"github.com/ipld/go-car"
|
|
"go.opencensus.io/trace"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/filecoin-project/lotus/api"
|
|
"github.com/filecoin-project/lotus/build"
|
|
"github.com/filecoin-project/lotus/chain/beacon"
|
|
genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis"
|
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
|
"github.com/filecoin-project/lotus/chain/store"
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
"github.com/filecoin-project/lotus/chain/vm"
|
|
"github.com/filecoin-project/lotus/chain/wallet"
|
|
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
|
|
"github.com/filecoin-project/lotus/genesis"
|
|
"github.com/filecoin-project/lotus/lib/blockstore"
|
|
"github.com/filecoin-project/lotus/lib/sigs"
|
|
"github.com/filecoin-project/lotus/node/repo"
|
|
"github.com/filecoin-project/sector-storage/ffiwrapper"
|
|
)
|
|
|
|
var log = logging.Logger("gen")
|
|
|
|
const msgsPerBlock = 20
|
|
|
|
var ValidWpostForTesting = []abi.PoStProof{{
|
|
ProofBytes: []byte("valid proof"),
|
|
}}
|
|
|
|
type ChainGen struct {
|
|
msgsPerBlock int
|
|
|
|
bs blockstore.Blockstore
|
|
|
|
cs *store.ChainStore
|
|
|
|
beacon beacon.RandomBeacon
|
|
|
|
sm *stmgr.StateManager
|
|
|
|
genesis *types.BlockHeader
|
|
CurTipset *store.FullTipSet
|
|
|
|
Timestamper func(*types.TipSet, abi.ChainEpoch) uint64
|
|
|
|
GetMessages func(*ChainGen) ([]*types.SignedMessage, error)
|
|
|
|
w *wallet.Wallet
|
|
|
|
eppProvs map[address.Address]WinningPoStProver
|
|
Miners []address.Address
|
|
receivers []address.Address
|
|
banker address.Address
|
|
bankerNonce uint64
|
|
|
|
r repo.Repo
|
|
lr repo.LockedRepo
|
|
}
|
|
|
|
type mybs struct {
|
|
blockstore.Blockstore
|
|
}
|
|
|
|
func (m mybs) Get(c cid.Cid) (block.Block, error) {
|
|
b, err := m.Blockstore.Get(c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return b, nil
|
|
}
|
|
|
|
func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
|
|
saminer.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
|
|
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
|
|
}
|
|
|
|
mr := repo.NewMemory(nil)
|
|
lr, err := mr.Lock(repo.StorageMiner)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("taking mem-repo lock failed: %w", err)
|
|
}
|
|
|
|
ds, err := lr.Datastore("/metadata")
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get metadata datastore: %w", err)
|
|
}
|
|
|
|
bds, err := lr.Datastore("/chain")
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get blocks datastore: %w", err)
|
|
}
|
|
|
|
bs := mybs{blockstore.NewBlockstore(bds)}
|
|
|
|
ks, err := lr.KeyStore()
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("getting repo keystore failed: %w", err)
|
|
}
|
|
|
|
w, err := wallet.NewWallet(ks)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err)
|
|
}
|
|
|
|
banker, err := w.GenerateKey(crypto.SigTypeSecp256k1)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to generate banker key: %w", err)
|
|
}
|
|
|
|
receievers := make([]address.Address, msgsPerBlock)
|
|
for r := range receievers {
|
|
receievers[r], err = w.GenerateKey(crypto.SigTypeBLS)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to generate receiver key: %w", err)
|
|
}
|
|
}
|
|
|
|
maddr1 := genesis2.MinerAddress(0)
|
|
|
|
m1temp, err := ioutil.TempDir("", "preseal")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
genm1, k1, err := seed.PreSeal(maddr1, abi.RegisteredSealProof_StackedDrg2KiBV1, 0, numSectors, m1temp, []byte("some randomness"), nil, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
maddr2 := genesis2.MinerAddress(1)
|
|
|
|
m2temp, err := ioutil.TempDir("", "preseal")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
genm2, k2, err := seed.PreSeal(maddr2, abi.RegisteredSealProof_StackedDrg2KiBV1, 0, numSectors, m2temp, []byte("some randomness"), nil, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
mk1, err := w.Import(k1)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
mk2, err := w.Import(k2)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sys := vm.Syscalls(&genFakeVerifier{})
|
|
|
|
tpl := genesis.Template{
|
|
Accounts: []genesis.Actor{
|
|
{
|
|
Type: genesis.TAccount,
|
|
Balance: types.FromFil(20_000_000),
|
|
Meta: (&genesis.AccountMeta{Owner: mk1}).ActorMeta(),
|
|
},
|
|
{
|
|
Type: genesis.TAccount,
|
|
Balance: types.FromFil(20_000_000),
|
|
Meta: (&genesis.AccountMeta{Owner: mk2}).ActorMeta(),
|
|
},
|
|
{
|
|
Type: genesis.TAccount,
|
|
Balance: types.FromFil(50000),
|
|
Meta: (&genesis.AccountMeta{Owner: banker}).ActorMeta(),
|
|
},
|
|
},
|
|
Miners: []genesis.Miner{
|
|
*genm1,
|
|
*genm2,
|
|
},
|
|
NetworkName: "",
|
|
Timestamp: uint64(build.Clock.Now().Add(-500 * time.Duration(build.BlockDelaySecs) * time.Second).Unix()),
|
|
}
|
|
|
|
genb, err := genesis2.MakeGenesisBlock(context.TODO(), bs, sys, tpl)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("make genesis block failed: %w", err)
|
|
}
|
|
|
|
cs := store.NewChainStore(bs, ds, sys)
|
|
|
|
genfb := &types.FullBlock{Header: genb.Genesis}
|
|
gents := store.NewFullTipSet([]*types.FullBlock{genfb})
|
|
|
|
if err := cs.SetGenesis(genb.Genesis); err != nil {
|
|
return nil, xerrors.Errorf("set genesis failed: %w", err)
|
|
}
|
|
|
|
mgen := make(map[address.Address]WinningPoStProver)
|
|
for i := range tpl.Miners {
|
|
mgen[genesis2.MinerAddress(uint64(i))] = &wppProvider{}
|
|
}
|
|
|
|
sm := stmgr.NewStateManager(cs)
|
|
|
|
miners := []address.Address{maddr1, maddr2}
|
|
|
|
beac := beacon.NewMockBeacon(time.Second)
|
|
//beac, err := drand.NewDrandBeacon(tpl.Timestamp, build.BlockDelaySecs)
|
|
//if err != nil {
|
|
//return nil, xerrors.Errorf("creating drand beacon: %w", err)
|
|
//}
|
|
|
|
gen := &ChainGen{
|
|
bs: bs,
|
|
cs: cs,
|
|
sm: sm,
|
|
msgsPerBlock: msgsPerBlock,
|
|
genesis: genb.Genesis,
|
|
beacon: beac,
|
|
w: w,
|
|
|
|
GetMessages: getRandomMessages,
|
|
Miners: miners,
|
|
eppProvs: mgen,
|
|
banker: banker,
|
|
receivers: receievers,
|
|
|
|
CurTipset: gents,
|
|
|
|
r: mr,
|
|
lr: lr,
|
|
}
|
|
|
|
return gen, nil
|
|
}
|
|
|
|
func NewGenerator() (*ChainGen, error) {
|
|
return NewGeneratorWithSectors(1)
|
|
}
|
|
|
|
func (cg *ChainGen) SetStateManager(sm *stmgr.StateManager) {
|
|
cg.sm = sm
|
|
}
|
|
|
|
func (cg *ChainGen) ChainStore() *store.ChainStore {
|
|
return cg.cs
|
|
}
|
|
|
|
func (cg *ChainGen) Genesis() *types.BlockHeader {
|
|
return cg.genesis
|
|
}
|
|
|
|
func (cg *ChainGen) GenesisCar() ([]byte, error) {
|
|
offl := offline.Exchange(cg.bs)
|
|
blkserv := blockservice.New(cg.bs, offl)
|
|
dserv := merkledag.NewDAGService(blkserv)
|
|
|
|
out := new(bytes.Buffer)
|
|
|
|
if err := car.WriteCarWithWalker(context.TODO(), dserv, []cid.Cid{cg.Genesis().Cid()}, out, CarWalkFunc); err != nil {
|
|
return nil, xerrors.Errorf("genesis car write car failed: %w", err)
|
|
}
|
|
|
|
return out.Bytes(), nil
|
|
}
|
|
|
|
func CarWalkFunc(nd format.Node) (out []*format.Link, err error) {
|
|
for _, link := range nd.Links() {
|
|
if link.Cid.Prefix().Codec == cid.FilCommitmentSealed || link.Cid.Prefix().Codec == cid.FilCommitmentUnsealed {
|
|
continue
|
|
}
|
|
out = append(out, link)
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round abi.ChainEpoch) ([]types.BeaconEntry, *types.ElectionProof, *types.Ticket, error) {
|
|
mc := &mca{w: cg.w, sm: cg.sm, pv: ffiwrapper.ProofVerifier, bcn: cg.beacon}
|
|
|
|
mbi, err := mc.MinerGetBaseInfo(ctx, m, round, pts.Key())
|
|
if err != nil {
|
|
return nil, nil, nil, xerrors.Errorf("get miner base info: %w", err)
|
|
}
|
|
|
|
prev := mbi.PrevBeaconEntry
|
|
|
|
entries, err := beacon.BeaconEntriesForBlock(ctx, cg.beacon, round, prev)
|
|
if err != nil {
|
|
return nil, nil, nil, xerrors.Errorf("get beacon entries for block: %w", err)
|
|
}
|
|
|
|
rbase := prev
|
|
if len(entries) > 0 {
|
|
rbase = entries[len(entries)-1]
|
|
}
|
|
|
|
eproof, err := IsRoundWinner(ctx, pts, round, m, rbase, mbi, mc)
|
|
if err != nil {
|
|
return nil, nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
|
|
}
|
|
|
|
buf := new(bytes.Buffer)
|
|
if err := m.MarshalCBOR(buf); err != nil {
|
|
return nil, nil, nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
|
|
}
|
|
|
|
if len(entries) == 0 {
|
|
buf.Write(pts.MinTicket().VRFProof)
|
|
}
|
|
|
|
ticketRand, err := store.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_TicketProduction, round-build.TicketRandomnessLookback, buf.Bytes())
|
|
if err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
st := pts.ParentState()
|
|
|
|
worker, err := stmgr.GetMinerWorkerRaw(ctx, cg.sm, st, m)
|
|
if err != nil {
|
|
return nil, nil, nil, xerrors.Errorf("get miner worker: %w", err)
|
|
}
|
|
|
|
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, ticketRand)
|
|
if err != nil {
|
|
return nil, nil, nil, xerrors.Errorf("compute VRF: %w", err)
|
|
}
|
|
|
|
return entries, eproof, &types.Ticket{VRFProof: vrfout}, nil
|
|
}
|
|
|
|
type MinedTipSet struct {
|
|
TipSet *store.FullTipSet
|
|
Messages []*types.SignedMessage
|
|
}
|
|
|
|
func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
|
|
mts, err := cg.NextTipSetFromMiners(cg.CurTipset.TipSet(), cg.Miners)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cg.CurTipset = mts.TipSet
|
|
return mts, nil
|
|
}
|
|
|
|
func (cg *ChainGen) SetWinningPoStProver(m address.Address, wpp WinningPoStProver) {
|
|
cg.eppProvs[m] = wpp
|
|
}
|
|
|
|
func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Address) (*MinedTipSet, error) {
|
|
var blks []*types.FullBlock
|
|
|
|
msgs, err := cg.GetMessages(cg)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("get random messages: %w", err)
|
|
}
|
|
|
|
for round := base.Height() + 1; len(blks) == 0; round++ {
|
|
for _, m := range miners {
|
|
bvals, et, ticket, err := cg.nextBlockProof(context.TODO(), base, m, round)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("next block proof: %w", err)
|
|
}
|
|
|
|
if et != nil {
|
|
// TODO: maybe think about passing in more real parameters to this?
|
|
wpost, err := cg.eppProvs[m].ComputeProof(context.TODO(), nil, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
fblk, err := cg.makeBlock(base, m, ticket, et, bvals, round, wpost, msgs)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
|
|
}
|
|
|
|
if err := cg.cs.PersistBlockHeaders(fblk.Header); err != nil {
|
|
return nil, xerrors.Errorf("chainstore AddBlock: %w", err)
|
|
}
|
|
|
|
blks = append(blks, fblk)
|
|
}
|
|
}
|
|
}
|
|
|
|
fts := store.NewFullTipSet(blks)
|
|
|
|
return &MinedTipSet{
|
|
TipSet: fts,
|
|
Messages: msgs,
|
|
}, nil
|
|
}
|
|
|
|
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, vrfticket *types.Ticket,
|
|
eticket *types.ElectionProof, bvals []types.BeaconEntry, height abi.ChainEpoch,
|
|
wpost []abi.PoStProof, msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
|
|
|
var ts uint64
|
|
if cg.Timestamper != nil {
|
|
ts = cg.Timestamper(parents, height-parents.Height())
|
|
} else {
|
|
ts = parents.MinTimestamp() + uint64(height-parents.Height())*build.BlockDelaySecs
|
|
}
|
|
|
|
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, &api.BlockTemplate{
|
|
Miner: m,
|
|
Parents: parents.Key(),
|
|
Ticket: vrfticket,
|
|
Eproof: eticket,
|
|
BeaconValues: bvals,
|
|
Messages: msgs,
|
|
Epoch: height,
|
|
Timestamp: ts,
|
|
WinningPoStProof: wpost,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return fblk, err
|
|
}
|
|
|
|
// ResyncBankerNonce is used for dealing with messages made when
|
|
// simulating forks
|
|
func (cg *ChainGen) ResyncBankerNonce(ts *types.TipSet) error {
|
|
var act types.Actor
|
|
err := cg.sm.WithParentState(ts, cg.sm.WithActor(cg.banker, stmgr.GetActor(&act)))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cg.bankerNonce = act.Nonce
|
|
return nil
|
|
}
|
|
|
|
func (cg *ChainGen) Banker() address.Address {
|
|
return cg.banker
|
|
}
|
|
|
|
func (cg *ChainGen) Wallet() *wallet.Wallet {
|
|
return cg.w
|
|
}
|
|
|
|
func getRandomMessages(cg *ChainGen) ([]*types.SignedMessage, error) {
|
|
msgs := make([]*types.SignedMessage, cg.msgsPerBlock)
|
|
for m := range msgs {
|
|
msg := types.Message{
|
|
To: cg.receivers[m%len(cg.receivers)],
|
|
From: cg.banker,
|
|
|
|
Nonce: atomic.AddUint64(&cg.bankerNonce, 1) - 1,
|
|
|
|
Value: types.NewInt(uint64(m + 1)),
|
|
|
|
Method: 0,
|
|
|
|
GasLimit: 100_000_000,
|
|
GasPrice: types.NewInt(0),
|
|
}
|
|
|
|
sig, err := cg.w.Sign(context.TODO(), cg.banker, msg.Cid().Bytes())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
msgs[m] = &types.SignedMessage{
|
|
Message: msg,
|
|
Signature: *sig,
|
|
}
|
|
}
|
|
|
|
return msgs, nil
|
|
}
|
|
|
|
func (cg *ChainGen) YieldRepo() (repo.Repo, error) {
|
|
if err := cg.lr.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
return cg.r, nil
|
|
}
|
|
|
|
type MiningCheckAPI interface {
|
|
ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error)
|
|
|
|
MinerGetBaseInfo(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*api.MiningBaseInfo, error)
|
|
|
|
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
|
}
|
|
|
|
type mca struct {
|
|
w *wallet.Wallet
|
|
sm *stmgr.StateManager
|
|
pv ffiwrapper.Verifier
|
|
bcn beacon.RandomBeacon
|
|
}
|
|
|
|
func (mca mca) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) {
|
|
pts, err := mca.sm.ChainStore().LoadTipSet(tsk)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("loading tipset key: %w", err)
|
|
}
|
|
|
|
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), personalization, randEpoch, entropy)
|
|
}
|
|
|
|
func (mca mca) MinerGetBaseInfo(ctx context.Context, maddr address.Address, epoch abi.ChainEpoch, tsk types.TipSetKey) (*api.MiningBaseInfo, error) {
|
|
return stmgr.MinerGetBaseInfo(ctx, mca.sm, mca.bcn, tsk, epoch, maddr, mca.pv)
|
|
}
|
|
|
|
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*crypto.Signature, error) {
|
|
return mca.w.Sign(ctx, a, v)
|
|
}
|
|
|
|
type WinningPoStProver interface {
|
|
GenerateCandidates(context.Context, abi.PoStRandomness, uint64) ([]uint64, error)
|
|
ComputeProof(context.Context, []abi.SectorInfo, abi.PoStRandomness) ([]abi.PoStProof, error)
|
|
}
|
|
|
|
type wppProvider struct{}
|
|
|
|
func (wpp *wppProvider) GenerateCandidates(ctx context.Context, _ abi.PoStRandomness, _ uint64) ([]uint64, error) {
|
|
return []uint64{0}, nil
|
|
}
|
|
|
|
func (wpp *wppProvider) ComputeProof(context.Context, []abi.SectorInfo, abi.PoStRandomness) ([]abi.PoStProof, error) {
|
|
return ValidWpostForTesting, nil
|
|
}
|
|
|
|
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch,
|
|
miner address.Address, brand types.BeaconEntry, mbi *api.MiningBaseInfo, a MiningCheckAPI) (*types.ElectionProof, error) {
|
|
|
|
buf := new(bytes.Buffer)
|
|
if err := miner.MarshalCBOR(buf); err != nil {
|
|
return nil, xerrors.Errorf("failed to cbor marshal address: %w")
|
|
}
|
|
|
|
electionRand, err := store.DrawRandomness(brand.Data, crypto.DomainSeparationTag_ElectionProofProduction, round, buf.Bytes())
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to draw randomness: %w", err)
|
|
}
|
|
|
|
vrfout, err := ComputeVRF(ctx, a.WalletSign, mbi.WorkerKey, electionRand)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
|
}
|
|
|
|
ep := &types.ElectionProof{VRFProof: vrfout}
|
|
j := ep.ComputeWinCount(mbi.MinerPower, mbi.NetworkPower)
|
|
ep.WinCount = j
|
|
if j < 1 {
|
|
return nil, nil
|
|
}
|
|
|
|
return ep, nil
|
|
}
|
|
|
|
type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
|
|
|
func VerifyVRF(ctx context.Context, worker address.Address, vrfBase, vrfproof []byte) error {
|
|
_, span := trace.StartSpan(ctx, "VerifyVRF")
|
|
defer span.End()
|
|
|
|
sig := &crypto.Signature{
|
|
Type: crypto.SigTypeBLS,
|
|
Data: vrfproof,
|
|
}
|
|
|
|
if err := sigs.Verify(sig, worker, vrfBase); err != nil {
|
|
return xerrors.Errorf("vrf was invalid: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func ComputeVRF(ctx context.Context, sign SignFunc, worker address.Address, sigInput []byte) ([]byte, error) {
|
|
sig, err := sign(ctx, worker, sigInput)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if sig.Type != crypto.SigTypeBLS {
|
|
return nil, fmt.Errorf("miner worker address was not a BLS key")
|
|
}
|
|
|
|
return sig.Data, nil
|
|
}
|
|
|
|
type genFakeVerifier struct{}
|
|
|
|
var _ ffiwrapper.Verifier = (*genFakeVerifier)(nil)
|
|
|
|
func (m genFakeVerifier) VerifySeal(svi abi.SealVerifyInfo) (bool, error) {
|
|
return true, nil
|
|
}
|
|
|
|
func (m genFakeVerifier) VerifyWinningPoSt(ctx context.Context, info abi.WinningPoStVerifyInfo) (bool, error) {
|
|
panic("not supported")
|
|
}
|
|
|
|
func (m genFakeVerifier) VerifyWindowPoSt(ctx context.Context, info abi.WindowPoStVerifyInfo) (bool, error) {
|
|
panic("not supported")
|
|
}
|
|
|
|
func (m genFakeVerifier) GenerateWinningPoStSectorChallenge(ctx context.Context, proof abi.RegisteredPoStProof, id abi.ActorID, randomness abi.PoStRandomness, u uint64) ([]uint64, error) {
|
|
panic("not supported")
|
|
}
|