Merge pull request #214 from filecoin-project/feat/rand-refactor

refactor to use 'randomness' as input to new vm creation
This commit is contained in:
Whyrusleeping 2019-09-19 23:21:19 -07:00 committed by GitHub
commit 5ba7307ab9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 62 additions and 32 deletions

View File

@ -51,7 +51,8 @@ func setupVMTestEnv(t *testing.T) (*vm.VM, []address.Address) {
cs := store.NewChainStore(bs, nil)
vm, err := vm.NewVM(stateroot, 1, maddr, cs)
// TODO: should probabaly mock out the randomness bit, nil works for now
vm, err := vm.NewVM(stateroot, 1, nil, maddr, cs)
if err != nil {
t.Fatal(err)
}

View File

@ -158,7 +158,7 @@ func NewHarness(t *testing.T, options ...HarnessOpt) *Harness {
t.Fatal(err)
}
h.cs = store.NewChainStore(h.bs, nil)
h.vm, err = vm.NewVM(stateroot, 1, h.HI.Miner, h.cs)
h.vm, err = vm.NewVM(stateroot, 1, nil, h.HI.Miner, h.cs)
if err != nil {
t.Fatal(err)
}

View File

@ -360,7 +360,7 @@ type mca struct {
}
func (mca mca) ChainGetRandomness(ctx context.Context, pts *types.TipSet, ticks []*types.Ticket, lb int) ([]byte, error) {
return mca.sm.ChainStore().GetRandomness(ctx, pts, ticks, lb)
return mca.sm.ChainStore().GetRandomness(ctx, pts, ticks, int64(lb))
}
func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, ts *types.TipSet) (api.MinerPower, error) {

View File

@ -27,7 +27,8 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
height := parents.Height() + uint64(len(tickets))
vmi, err := vm.NewVM(st, height, miner, sm.ChainStore())
r := vm.NewChainRand(sm.ChainStore(), parents, tickets)
vmi, err := vm.NewVM(st, height, r, miner, sm.ChainStore())
if err != nil {
return nil, err
}

View File

@ -169,7 +169,7 @@ func mustEnc(i cbg.CBORMarshaler) []byte {
}
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, error) {
vm, err := vm.NewVM(sroot, 0, actors.NetworkAddress, cs)
vm, err := vm.NewVM(sroot, 0, nil, actors.NetworkAddress, cs)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
}

View File

@ -11,8 +11,8 @@ import (
"golang.org/x/xerrors"
)
func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate cid.Cid, bheight uint64) (*types.MessageReceipt, error) {
vmi, err := vm.NewVM(bstate, bheight, actors.NetworkAddress, sm.cs)
func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate cid.Cid, r vm.Rand, bheight uint64) (*types.MessageReceipt, error) {
vmi, err := vm.NewVM(bstate, bheight, r, actors.NetworkAddress, sm.cs)
if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err)
}
@ -57,5 +57,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
return nil, err
}
return sm.CallRaw(ctx, msg, state, ts.Height())
r := vm.NewChainRand(sm.cs, ts, nil)
return sm.CallRaw(ctx, msg, state, r, ts.Height())
}

View File

@ -78,7 +78,9 @@ func (sm *StateManager) computeTipSetState(cids []cid.Cid) (cid.Cid, error) {
return cid.Undef, xerrors.Errorf("recursive TipSetState failed: %w", err)
}
vmi, err := vm.NewVM(pstate, ts.Height(), address.Undef, sm.cs)
r := vm.NewChainRand(sm.cs, ts, nil)
vmi, err := vm.NewVM(pstate, ts.Height(), r, address.Undef, sm.cs)
if err != nil {
return cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
}

View File

@ -22,7 +22,7 @@ func GetMinerWorker(ctx context.Context, sm *StateManager, st cid.Cid, maddr add
To: maddr,
From: maddr,
Method: actors.MAMethods.GetWorkerAddr,
}, st, 0)
}, st, nil, 0)
if err != nil {
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
}
@ -48,7 +48,7 @@ func GetMinerOwner(ctx context.Context, sm *StateManager, st cid.Cid, maddr addr
To: maddr,
From: maddr,
Method: actors.MAMethods.GetOwner,
}, st, 0)
}, st, nil, 0)
if err != nil {
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
}

View File

@ -702,16 +702,20 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
return NewFullTipSet(out), nil
}
func (cs *ChainStore) GetRandomness(ctx context.Context, pts *types.TipSet, tickets []*types.Ticket, lb int) ([]byte, error) {
if lb < len(tickets) {
func (cs *ChainStore) GetRandomness(ctx context.Context, pts *types.TipSet, tickets []*types.Ticket, lb int64) ([]byte, error) {
if lb < 0 {
return nil, fmt.Errorf("negative lookback parameters are not valid (got %d)", lb)
}
lt := int64(len(tickets))
if lb < lt {
log.Warn("self sampling randomness. this should be extremely rare, if you see this often it may be a bug")
t := tickets[len(tickets)-(1+lb)]
t := tickets[lt-(1+lb)]
return t.VDFResult, nil
}
nv := lb - len(tickets)
nv := lb - lt
nextCids := pts.Cids()
for {
@ -721,13 +725,14 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, pts *types.TipSet, tick
}
mtb := nts.MinTicketBlock()
if nv < len(mtb.Tickets) {
t := mtb.Tickets[len(mtb.Tickets)-(1+nv)]
log.Infof("Returning randomness: H:%d, t:%d, mtb:%s", nts.Height(), len(mtb.Tickets)-(1+nv), mtb.Cid())
lt := int64(len(mtb.Tickets))
if nv < lt {
t := mtb.Tickets[lt-(1+nv)]
log.Infof("Returning randomness: H:%d, t:%d, mtb:%s", nts.Height(), lt-(1+nv), mtb.Cid())
return t.VDFResult, nil
}
nv -= len(mtb.Tickets)
nv -= lt
// special case for lookback behind genesis block
// TODO(spec): this is not in the spec, need to sync that
@ -736,7 +741,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, pts *types.TipSet, tick
t := mtb.Tickets[0]
rval := t.VDFResult
for i := 0; i < nv; i++ {
for i := int64(0); i < nv; i++ {
h := sha256.Sum256(rval)
rval = h[:]
}

View File

@ -313,7 +313,7 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet)
for _, b := range fts.Blocks {
if err := syncer.ValidateBlock(ctx, b); err != nil {
return err
return xerrors.Errorf("validating block %s: %w", b.Cid(), err)
}
}
return nil
@ -440,7 +440,8 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return xerrors.Errorf("miner created a block but was not a winner")
}
vmi, err := vm.NewVM(stateroot, h.Height, h.Miner, syncer.store)
r := vm.NewChainRand(syncer.store, baseTs, h.Tickets)
vmi, err := vm.NewVM(stateroot, h.Height, r, h.Miner, syncer.store)
if err != nil {
return xerrors.Errorf("failed to instantiate VM: %w", err)
}

View File

@ -67,14 +67,8 @@ func (vmc *VMContext) Message() *types.Message {
}
func (vmc *VMContext) GetRandomness(height uint64) ([]byte, aerrors.ActorError) {
hts := vmc.vm.cs.GetHeaviestTipSet()
relHeight := int(hts.Height() - height)
if relHeight < 0 {
return nil, aerrors.Newf(1, "negative relHeight in GetRandomness: %d", relHeight)
}
res, err := vmc.vm.cs.GetRandomness(vmc.ctx, hts, nil, relHeight)
res, err := vmc.vm.rand.GetRandomness(vmc.ctx, int64(height))
if err != nil {
return nil, aerrors.Escalate(err, "could not get randomness")
}
@ -294,9 +288,10 @@ type VM struct {
blockHeight uint64
blockMiner address.Address
inv *invoker
rand Rand
}
func NewVM(base cid.Cid, height uint64, maddr address.Address, cs *store.ChainStore) (*VM, error) {
func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cs *store.ChainStore) (*VM, error) {
buf := bufbstore.NewBufferedBstore(cs.Blockstore())
cst := hamt.CSTFromBstore(buf)
state, err := state.LoadStateTree(cst, base)
@ -313,9 +308,33 @@ func NewVM(base cid.Cid, height uint64, maddr address.Address, cs *store.ChainSt
blockHeight: height,
blockMiner: maddr,
inv: newInvoker(),
rand: r,
}, nil
}
type Rand interface {
GetRandomness(ctx context.Context, h int64) ([]byte, error)
}
type chainRand struct {
cs *store.ChainStore
pts *types.TipSet
tickets []*types.Ticket
}
func NewChainRand(cs *store.ChainStore, pts *types.TipSet, tickets []*types.Ticket) Rand {
return &chainRand{
cs: cs,
pts: pts,
tickets: tickets,
}
}
func (cr *chainRand) GetRandomness(ctx context.Context, h int64) ([]byte, error) {
lb := (int64(cr.pts.Height()) + int64(len(cr.tickets))) - h
return cr.cs.GetRandomness(ctx, cr.pts, cr.tickets, lb)
}
type ApplyRet struct {
types.MessageReceipt
ActorErr aerrors.ActorError

1
go.sum
View File

@ -68,7 +68,6 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/filecoin-project/go-amt-ipld v0.0.0-20190917221444-2ed85149c65d/go.mod h1:lKjJYPg2kwbav5f78i5YA8kGccnZn18IySbpneXvaQs=
github.com/filecoin-project/go-amt-ipld v0.0.0-20190919045431-3650716fff16 h1:NzojcJU1VbS6zdLG13JMYis/cQy/MrN3rxmZRq56jKA=
github.com/filecoin-project/go-amt-ipld v0.0.0-20190919045431-3650716fff16/go.mod h1:lKjJYPg2kwbav5f78i5YA8kGccnZn18IySbpneXvaQs=
github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543 h1:aMJGfgqe1QDhAVwxRg5fjCRF533xHidiKsugk7Vvzug=

View File

@ -45,7 +45,7 @@ func (a *ChainAPI) ChainHead(context.Context) (*types.TipSet, error) {
}
func (a *ChainAPI) ChainGetRandomness(ctx context.Context, pts *types.TipSet, tickets []*types.Ticket, lb int) ([]byte, error) {
return a.Chain.GetRandomness(ctx, pts, tickets, lb)
return a.Chain.GetRandomness(ctx, pts, tickets, int64(lb))
}
func (a *ChainAPI) ChainWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait, error) {