lotus/chain/gen/gen.go

659 lines
17 KiB
Go
Raw Normal View History

2019-07-25 22:15:33 +00:00
package gen
import (
"bytes"
2019-07-25 22:15:33 +00:00
"context"
"fmt"
2019-11-29 03:38:18 +00:00
"io/ioutil"
2019-07-30 13:20:40 +00:00
"sync/atomic"
"time"
2019-07-25 22:15:33 +00:00
2020-02-23 20:00:47 +00:00
"github.com/filecoin-project/go-address"
2020-02-08 02:18:32 +00:00
"github.com/filecoin-project/specs-actors/actors/abi"
2020-07-24 09:22:50 +00:00
"github.com/filecoin-project/specs-actors/actors/abi/big"
2020-05-12 16:58:43 +00:00
saminer "github.com/filecoin-project/specs-actors/actors/builtin/miner"
2020-02-12 23:52:36 +00:00
"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"
2020-02-23 20:00:47 +00:00
format "github.com/ipfs/go-ipld-format"
logging "github.com/ipfs/go-log/v2"
"github.com/ipfs/go-merkledag"
"github.com/ipld/go-car"
2020-03-26 19:34:38 +00:00
"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"
2020-02-11 20:48:03 +00:00
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"
2019-11-29 03:38:18 +00:00
"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"
2020-03-27 23:00:21 +00:00
"github.com/filecoin-project/sector-storage/ffiwrapper"
2019-07-25 22:15:33 +00:00
)
var log = logging.Logger("gen")
2019-10-08 00:28:13 +00:00
const msgsPerBlock = 20
2019-07-30 13:20:40 +00:00
var ValidWpostForTesting = []abi.PoStProof{{
ProofBytes: []byte("valid proof"),
}}
2019-07-25 22:15:33 +00:00
type ChainGen struct {
msgsPerBlock int
bs blockstore.Blockstore
cs *store.ChainStore
2020-04-08 22:12:36 +00:00
beacon beacon.RandomBeacon
sm *stmgr.StateManager
genesis *types.BlockHeader
CurTipset *store.FullTipSet
2019-07-25 22:15:33 +00:00
2020-02-08 02:18:32 +00:00
Timestamper func(*types.TipSet, abi.ChainEpoch) uint64
2019-10-10 03:04:10 +00:00
GetMessages func(*ChainGen) ([]*types.SignedMessage, error)
2019-07-30 13:20:40 +00:00
w *wallet.Wallet
2020-04-10 21:07:18 +00:00
eppProvs map[address.Address]WinningPoStProver
Miners []address.Address
2019-07-30 13:20:40 +00:00
receivers []address.Address
banker address.Address
bankerNonce uint64
2019-07-29 19:34:09 +00:00
r repo.Repo
2019-07-29 19:34:09 +00:00
lr repo.LockedRepo
2019-07-25 22:15:33 +00:00
}
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
}
2020-07-24 09:22:50 +00:00
var rootkey, _ = address.NewIDAddress(80)
var rootkeyMultisig = genesis.MultisigMeta{
Signers: []address.Address{rootkey},
Threshold: 1,
VestingDuration: 0,
VestingStart: 0,
}
var DefaultVerifregRootkeyActor = genesis.Actor{
Type: genesis.TMultisig,
Balance: big.NewInt(0),
Meta: rootkeyMultisig.ActorMeta(),
}
2020-05-01 00:54:41 +00:00
func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) {
2020-06-15 16:30:49 +00:00
saminer.SupportedProofTypes = map[abi.RegisteredSealProof]struct{}{
abi.RegisteredSealProof_StackedDrg2KiBV1: {},
2020-05-12 16:58:43 +00:00
}
2019-07-25 22:15:33 +00:00
mr := repo.NewMemory(nil)
2019-11-12 17:59:38 +00:00
lr, err := mr.Lock(repo.StorageMiner)
2019-07-25 22:15:33 +00:00
if err != nil {
2019-08-15 18:45:32 +00:00
return nil, xerrors.Errorf("taking mem-repo lock failed: %w", err)
2019-07-25 22:15:33 +00:00
}
2019-07-29 19:34:09 +00:00
ds, err := lr.Datastore("/metadata")
if err != nil {
2019-08-15 18:45:32 +00:00
return nil, xerrors.Errorf("failed to get metadata datastore: %w", err)
2019-07-29 19:34:09 +00:00
}
bds, err := lr.Datastore("/chain")
2019-07-25 22:15:33 +00:00
if err != nil {
2019-08-15 18:45:32 +00:00
return nil, xerrors.Errorf("failed to get blocks datastore: %w", err)
2019-07-25 22:15:33 +00:00
}
2019-07-29 19:34:09 +00:00
bs := mybs{blockstore.NewBlockstore(bds)}
2019-07-25 22:15:33 +00:00
ks, err := lr.KeyStore()
if err != nil {
2019-08-15 18:45:32 +00:00
return nil, xerrors.Errorf("getting repo keystore failed: %w", err)
2019-07-25 22:15:33 +00:00
}
w, err := wallet.NewWallet(ks)
if err != nil {
2019-08-15 18:45:32 +00:00
return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err)
2019-07-25 22:15:33 +00:00
}
2020-02-12 23:52:36 +00:00
banker, err := w.GenerateKey(crypto.SigTypeSecp256k1)
2019-07-25 22:15:33 +00:00
if err != nil {
2019-08-15 18:45:32 +00:00
return nil, xerrors.Errorf("failed to generate banker key: %w", err)
2019-07-25 22:15:33 +00:00
}
2019-07-30 13:20:40 +00:00
receievers := make([]address.Address, msgsPerBlock)
for r := range receievers {
2020-02-12 23:52:36 +00:00
receievers[r], err = w.GenerateKey(crypto.SigTypeBLS)
2019-07-30 13:20:40 +00:00
if err != nil {
2019-08-15 18:45:32 +00:00
return nil, xerrors.Errorf("failed to generate receiver key: %w", err)
2019-07-30 13:20:40 +00:00
}
}
maddr1 := genesis2.MinerAddress(0)
2019-11-29 03:38:18 +00:00
m1temp, err := ioutil.TempDir("", "preseal")
if err != nil {
return nil, err
}
2020-07-03 01:29:06 +00:00
genm1, k1, err := seed.PreSeal(maddr1, abi.RegisteredSealProof_StackedDrg2KiBV1, 0, numSectors, m1temp, []byte("some randomness"), nil, true)
2019-11-29 03:38:18 +00:00
if err != nil {
return nil, err
}
maddr2 := genesis2.MinerAddress(1)
m2temp, err := ioutil.TempDir("", "preseal")
if err != nil {
return nil, err
}
2020-07-03 01:29:06 +00:00
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{
2020-02-13 00:15:33 +00:00
Accounts: []genesis.Actor{
{
Type: genesis.TAccount,
2020-07-17 21:34:18 +00:00
Balance: types.FromFil(20_000_000),
Meta: (&genesis.AccountMeta{Owner: mk1}).ActorMeta(),
},
{
Type: genesis.TAccount,
2020-07-17 21:34:18 +00:00
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(),
},
},
2020-02-13 00:15:33 +00:00
Miners: []genesis.Miner{
*genm1,
*genm2,
2019-11-29 03:38:18 +00:00
},
2020-07-24 09:22:50 +00:00
VerifregRootKey: DefaultVerifregRootkeyActor,
NetworkName: "",
Timestamp: uint64(build.Clock.Now().Add(-500 * time.Duration(build.BlockDelaySecs) * time.Second).Unix()),
2019-09-06 20:03:28 +00:00
}
genb, err := genesis2.MakeGenesisBlock(context.TODO(), bs, sys, tpl)
2019-07-25 22:15:33 +00:00
if err != nil {
2019-08-15 18:45:32 +00:00
return nil, xerrors.Errorf("make genesis block failed: %w", err)
2019-07-25 22:15:33 +00:00
}
2020-01-13 20:47:27 +00:00
cs := store.NewChainStore(bs, ds, sys)
2019-07-25 22:15:33 +00:00
genfb := &types.FullBlock{Header: genb.Genesis}
gents := store.NewFullTipSet([]*types.FullBlock{genfb})
2019-07-25 22:15:33 +00:00
2019-07-26 12:19:27 +00:00
if err := cs.SetGenesis(genb.Genesis); err != nil {
2019-08-15 18:45:32 +00:00
return nil, xerrors.Errorf("set genesis failed: %w", err)
2019-07-26 12:19:27 +00:00
}
2020-04-10 21:07:18 +00:00
mgen := make(map[address.Address]WinningPoStProver)
for i := range tpl.Miners {
2020-04-10 21:07:18 +00:00
mgen[genesis2.MinerAddress(uint64(i))] = &wppProvider{}
2019-11-21 22:21:45 +00:00
}
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)
//}
2019-07-25 22:15:33 +00:00
gen := &ChainGen{
bs: bs,
cs: cs,
sm: sm,
2019-07-25 22:15:33 +00:00
msgsPerBlock: msgsPerBlock,
genesis: genb.Genesis,
beacon: beac,
2019-07-30 13:20:40 +00:00
w: w,
GetMessages: getRandomMessages,
Miners: miners,
eppProvs: mgen,
banker: banker,
receivers: receievers,
2019-07-30 13:20:40 +00:00
CurTipset: gents,
2019-07-29 19:34:09 +00:00
r: mr,
2019-07-29 19:34:09 +00:00
lr: lr,
2019-07-25 22:15:33 +00:00
}
return gen, nil
}
2020-05-01 00:54:41 +00:00
func NewGenerator() (*ChainGen, error) {
return NewGeneratorWithSectors(1)
}
2020-08-09 00:20:37 +00:00
func (cg *ChainGen) StateManager() *stmgr.StateManager {
return cg.sm
}
func (cg *ChainGen) SetStateManager(sm *stmgr.StateManager) {
cg.sm = sm
}
func (cg *ChainGen) ChainStore() *store.ChainStore {
return cg.cs
}
2019-07-25 22:15:33 +00:00
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)
2020-02-21 19:27:29 +00:00
if err := car.WriteCarWithWalker(context.TODO(), dserv, []cid.Cid{cg.Genesis().Cid()}, out, CarWalkFunc); err != nil {
2019-11-21 22:21:45 +00:00
return nil, xerrors.Errorf("genesis car write car failed: %w", err)
}
return out.Bytes(), nil
}
2020-02-21 19:27:29 +00:00
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 {
2020-02-21 19:27:29 +00:00
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) {
2020-04-30 22:11:14 +00:00
mc := &mca{w: cg.w, sm: cg.sm, pv: ffiwrapper.ProofVerifier, bcn: cg.beacon}
2020-04-09 17:13:09 +00:00
mbi, err := mc.MinerGetBaseInfo(ctx, m, round, pts.Key())
if err != nil {
2020-04-09 17:13:09 +00:00
return nil, nil, nil, xerrors.Errorf("get miner base info: %w", err)
}
2020-04-09 17:13:09 +00:00
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)
}
2020-04-09 17:13:09 +00:00
rbase := prev
if len(entries) > 0 {
rbase = entries[len(entries)-1]
}
2020-04-09 17:13:09 +00:00
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)
}
2020-04-29 22:25:48 +00:00
if len(entries) == 0 {
buf.Write(pts.MinTicket().VRFProof)
}
ticketRand, err := store.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_TicketProduction, round-build.TicketRandomnessLookback, buf.Bytes())
2020-02-23 20:00:47 +00:00
if err != nil {
return nil, nil, nil, err
2020-02-23 20:00:47 +00:00
}
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)
}
2019-08-16 04:40:59 +00:00
2020-02-23 20:00:47 +00:00
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, ticketRand)
if err != nil {
return nil, nil, nil, xerrors.Errorf("compute VRF: %w", err)
2019-08-15 02:30:21 +00:00
}
return entries, eproof, &types.Ticket{VRFProof: vrfout}, nil
2019-07-25 22:15:33 +00:00
}
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) {
2020-08-09 00:20:37 +00:00
ms, err := cg.GetMessages(cg)
2019-07-25 22:15:33 +00:00
if err != nil {
return nil, xerrors.Errorf("get random messages: %w", err)
2019-07-25 22:15:33 +00:00
}
2020-08-09 00:20:37 +00:00
msgs := make([][]*types.SignedMessage, len(miners))
for i := range msgs {
msgs[i] = ms
}
fts, err := cg.NextTipSetFromMinersWithMessages(base, miners, msgs)
if err != nil {
return nil, err
}
return &MinedTipSet{
TipSet: fts,
Messages: ms,
}, nil
}
func (cg *ChainGen) NextTipSetFromMinersWithMessages(base *types.TipSet, miners []address.Address, msgs [][]*types.SignedMessage) (*store.FullTipSet, error) {
var blks []*types.FullBlock
2020-04-08 15:11:42 +00:00
for round := base.Height() + 1; len(blks) == 0; round++ {
2020-08-09 00:20:37 +00:00
for mi, 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 {
2020-04-17 20:44:13 +00:00
// 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
}
2020-08-09 00:20:37 +00:00
fblk, err := cg.makeBlock(base, m, ticket, et, bvals, round, wpost, msgs[mi])
if err != nil {
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
}
2019-11-12 10:18:46 +00:00
if err := cg.cs.PersistBlockHeaders(fblk.Header); err != nil {
return nil, xerrors.Errorf("chainstore AddBlock: %w", err)
}
blks = append(blks, fblk)
}
}
}
2020-08-09 00:20:37 +00:00
return store.NewFullTipSet(blks), nil
}
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, vrfticket *types.Ticket,
eticket *types.ElectionProof, bvals []types.BeaconEntry, height abi.ChainEpoch,
2020-04-17 20:44:13 +00:00
wpost []abi.PoStProof, msgs []*types.SignedMessage) (*types.FullBlock, error) {
2019-10-10 03:04:10 +00:00
var ts uint64
if cg.Timestamper != nil {
ts = cg.Timestamper(parents, height-parents.Height())
2019-10-10 03:04:10 +00:00
} else {
2020-06-30 21:56:13 +00:00
ts = parents.MinTimestamp() + uint64(height-parents.Height())*build.BlockDelaySecs
2019-10-10 03:04:10 +00:00
}
2020-04-09 00:24:10 +00:00
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, &api.BlockTemplate{
2020-04-17 20:44:13 +00:00
Miner: m,
Parents: parents.Key(),
Ticket: vrfticket,
Eproof: eticket,
BeaconValues: bvals,
Messages: msgs,
Epoch: height,
Timestamp: ts,
WinningPoStProof: wpost,
2020-04-09 00:24:10 +00:00
})
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 {
2020-07-17 14:21:00 +00:00
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) {
2019-07-30 13:20:40 +00:00
msgs := make([]*types.SignedMessage, cg.msgsPerBlock)
for m := range msgs {
msg := types.Message{
To: cg.receivers[m%len(cg.receivers)],
2019-07-30 13:20:40 +00:00
From: cg.banker,
Nonce: atomic.AddUint64(&cg.bankerNonce, 1) - 1,
Value: types.NewInt(uint64(m + 1)),
Method: 0,
GasLimit: 100_000_000,
GasFeeCap: types.NewInt(0),
GasPremium: types.NewInt(0),
2019-07-30 13:20:40 +00:00
}
sig, err := cg.w.Sign(context.TODO(), cg.banker, msg.Cid().Bytes())
2019-07-30 13:20:40 +00:00
if err != nil {
return nil, err
2019-07-30 13:20:40 +00:00
}
msgs[m] = &types.SignedMessage{
Message: msg,
Signature: *sig,
}
}
return msgs, nil
2019-07-25 22:15:33 +00:00
}
2019-07-29 19:34:09 +00:00
func (cg *ChainGen) YieldRepo() (repo.Repo, error) {
if err := cg.lr.Close(); err != nil {
return nil, err
}
return cg.r, nil
}
type MiningCheckAPI interface {
2020-02-23 20:00:47 +00:00
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)
2019-11-25 04:45:13 +00:00
2020-02-12 23:52:36 +00:00
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error)
}
type mca struct {
2020-04-30 22:11:14 +00:00
w *wallet.Wallet
sm *stmgr.StateManager
pv ffiwrapper.Verifier
bcn beacon.RandomBeacon
}
2020-02-23 20:00:47 +00:00
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)
}
2020-04-08 15:11:42 +00:00
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) {
2020-04-30 22:11:14 +00:00
return stmgr.MinerGetBaseInfo(ctx, mca.sm, mca.bcn, tsk, epoch, maddr, mca.pv)
2019-11-25 04:45:13 +00:00
}
2020-02-12 23:52:36 +00:00
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*crypto.Signature, error) {
return mca.w.Sign(ctx, a, v)
}
2020-04-10 21:07:18 +00:00
type WinningPoStProver interface {
GenerateCandidates(context.Context, abi.PoStRandomness, uint64) ([]uint64, error)
ComputeProof(context.Context, []abi.SectorInfo, abi.PoStRandomness) ([]abi.PoStProof, error)
2019-11-21 22:21:45 +00:00
}
2020-04-10 21:07:18 +00:00
type wppProvider struct{}
2019-11-21 22:21:45 +00:00
2020-04-10 21:07:18 +00:00
func (wpp *wppProvider) GenerateCandidates(ctx context.Context, _ abi.PoStRandomness, _ uint64) ([]uint64, error) {
return []uint64{0}, nil
2019-11-21 22:21:45 +00:00
}
func (wpp *wppProvider) ComputeProof(context.Context, []abi.SectorInfo, abi.PoStRandomness) ([]abi.PoStProof, error) {
return ValidWpostForTesting, nil
2019-11-21 22:21:45 +00:00
}
2020-04-08 15:11:42 +00:00
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch,
2020-04-09 17:13:09 +00:00
miner address.Address, brand types.BeaconEntry, mbi *api.MiningBaseInfo, a MiningCheckAPI) (*types.ElectionProof, error) {
2020-04-08 15:11:42 +00:00
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)
}
2020-04-16 17:17:56 +00:00
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
2020-04-08 15:11:42 +00:00
}
return ep, nil
2019-12-03 18:25:56 +00:00
}
2020-02-12 23:52:36 +00:00
type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error)
2020-02-23 20:00:47 +00:00
func VerifyVRF(ctx context.Context, worker address.Address, vrfBase, vrfproof []byte) error {
2019-12-02 12:51:16 +00:00
_, span := trace.StartSpan(ctx, "VerifyVRF")
2019-11-21 22:21:45 +00:00
defer span.End()
2020-02-12 23:52:36 +00:00
sig := &crypto.Signature{
Type: crypto.SigTypeBLS,
2019-11-21 22:21:45 +00:00
Data: vrfproof,
}
if err := sigs.Verify(sig, worker, vrfBase); err != nil {
2019-11-21 22:21:45 +00:00
return xerrors.Errorf("vrf was invalid: %w", err)
}
return nil
}
2020-02-23 20:00:47 +00:00
func ComputeVRF(ctx context.Context, sign SignFunc, worker address.Address, sigInput []byte) ([]byte, error) {
2019-11-21 22:21:45 +00:00
sig, err := sign(ctx, worker, sigInput)
if err != nil {
return nil, err
}
2020-02-12 23:52:36 +00:00
if sig.Type != crypto.SigTypeBLS {
return nil, fmt.Errorf("miner worker address was not a BLS key")
}
return sig.Data, nil
}
type genFakeVerifier struct{}
2020-03-26 02:50:56 +00:00
var _ ffiwrapper.Verifier = (*genFakeVerifier)(nil)
2020-02-27 21:45:31 +00:00
func (m genFakeVerifier) VerifySeal(svi abi.SealVerifyInfo) (bool, error) {
return true, nil
}
2020-04-10 21:07:18 +00:00
func (m genFakeVerifier) VerifyWinningPoSt(ctx context.Context, info abi.WinningPoStVerifyInfo) (bool, error) {
2020-04-17 14:47:19 +00:00
panic("not supported")
2020-04-10 21:07:18 +00:00
}
func (m genFakeVerifier) VerifyWindowPoSt(ctx context.Context, info abi.WindowPoStVerifyInfo) (bool, error) {
2020-04-17 14:47:19 +00:00
panic("not supported")
}
2020-06-15 16:30:49 +00:00
func (m genFakeVerifier) GenerateWinningPoStSectorChallenge(ctx context.Context, proof abi.RegisteredPoStProof, id abi.ActorID, randomness abi.PoStRandomness, u uint64) ([]uint64, error) {
2020-04-17 14:47:19 +00:00
panic("not supported")
}