refactor state utilities into StateManager package, implement proper election proofs

This commit is contained in:
whyrusleeping 2019-09-06 16:26:02 +10:00
parent 6e21372ccb
commit ed45d1c2b4
29 changed files with 796 additions and 483 deletions

View File

@ -48,16 +48,11 @@ type FullNode interface {
ChainNotify(context.Context) (<-chan *store.HeadChange, error)
ChainHead(context.Context) (*types.TipSet, error) // TODO: check serialization
ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) error // TODO: check serialization
ChainGetRandomness(context.Context, *types.TipSet) ([]byte, error)
ChainGetRandomness(context.Context, *types.TipSet, []*types.Ticket, int) ([]byte, error)
ChainWaitMsg(context.Context, cid.Cid) (*MsgWait, error)
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
ChainGetBlockReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error)
ChainGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error)
ChainReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error)
// if tipset is nil, we'll use heaviest
ChainCall(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error)
// messages
@ -107,6 +102,10 @@ type FullNode interface {
StateMinerProvingSet(context.Context, address.Address) ([]*SectorInfo, error)
StateMinerPower(context.Context, address.Address, *types.TipSet) (MinerPower, error)
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error)
// if tipset is nil, we'll use heaviest
StateCall(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error)
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error)
StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error)
PaychCreate(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error)
PaychList(context.Context) ([]address.Address, error)

View File

@ -39,17 +39,14 @@ type FullNodeStruct struct {
CommonStruct
Internal struct {
ChainNotify func(context.Context) (<-chan *store.HeadChange, error) `perm:"read"`
ChainSubmitBlock func(ctx context.Context, blk *chain.BlockMsg) error `perm:"write"`
ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainGetRandomness func(context.Context, *types.TipSet) ([]byte, error) `perm:"read"`
ChainWaitMsg func(context.Context, cid.Cid) (*MsgWait, error) `perm:"read"`
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"`
ChainGetBlockReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
ChainCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
ChainGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"`
ChainReadState func(context.Context, *types.Actor, *types.TipSet) (*ActorState, error) `perm:"read"`
ChainNotify func(context.Context) (<-chan *store.HeadChange, error) `perm:"read"`
ChainSubmitBlock func(ctx context.Context, blk *chain.BlockMsg) error `perm:"write"`
ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
ChainGetRandomness func(context.Context, *types.TipSet, []*types.Ticket, int) ([]byte, error) `perm:"read"`
ChainWaitMsg func(context.Context, cid.Cid) (*MsgWait, error) `perm:"read"`
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"`
ChainGetBlockReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"`
MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"`
@ -75,10 +72,13 @@ type FullNodeStruct struct {
ClientStartDeal func(ctx context.Context, data cid.Cid, miner address.Address, price types.BigInt, blocksDuration uint64) (*cid.Cid, error) `perm:"admin"`
ClientRetrieve func(ctx context.Context, order RetrievalOrder, path string) error `perm:"admin"`
StateMinerSectors func(context.Context, address.Address) ([]*SectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address) ([]*SectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, *types.TipSet) (MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address) ([]*SectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address) ([]*SectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, *types.TipSet) (MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"`
StateCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"`
StateReadState func(context.Context, *types.Actor, *types.TipSet) (*ActorState, error) `perm:"read"`
PaychCreate func(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error) `perm:"sign"`
PaychList func(context.Context) ([]address.Address, error) `perm:"read"`
@ -204,26 +204,14 @@ func (c *FullNodeStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
return c.Internal.ChainHead(ctx)
}
func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, pts *types.TipSet) ([]byte, error) {
return c.Internal.ChainGetRandomness(ctx, pts)
func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, pts *types.TipSet, ticks []*types.Ticket, lb int) ([]byte, error) {
return c.Internal.ChainGetRandomness(ctx, pts, ticks, lb)
}
func (c *FullNodeStruct) ChainWaitMsg(ctx context.Context, msgc cid.Cid) (*MsgWait, error) {
return c.Internal.ChainWaitMsg(ctx, msgc)
}
func (c *FullNodeStruct) ChainCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
return c.Internal.ChainCall(ctx, msg, ts)
}
func (c *FullNodeStruct) ChainGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) {
return c.Internal.ChainGetActor(ctx, actor, ts)
}
func (c *FullNodeStruct) ChainReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error) {
return c.Internal.ChainReadState(ctx, act, ts)
}
func (c *FullNodeStruct) WalletNew(ctx context.Context, typ string) (address.Address, error) {
return c.Internal.WalletNew(ctx, typ)
}
@ -288,6 +276,18 @@ func (c *FullNodeStruct) StateMinerWorker(ctx context.Context, m address.Address
return c.Internal.StateMinerWorker(ctx, m, ts)
}
func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
return c.Internal.StateCall(ctx, msg, ts)
}
func (c *FullNodeStruct) StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) {
return c.Internal.StateGetActor(ctx, actor, ts)
}
func (c *FullNodeStruct) StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error) {
return c.Internal.StateReadState(ctx, act, ts)
}
func (c *FullNodeStruct) PaychCreate(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error) {
return c.Internal.PaychCreate(ctx, from, to, amt)
}

View File

@ -12,5 +12,6 @@ const PaymentChannelClosingDelay = 6 * 60 * 2 // six hours
const DealVoucherSkewLimit = 10
const ForkLengthThreshold = 20
const RandomnessLookback = 20
// TODO: Move other important consts here

View File

@ -77,7 +77,7 @@ func (h *Handler) sendSignedResponse(resp StorageDealResponse) error {
From: h.actor,
Method: actors.MAMethods.GetWorkerAddr,
}
r, err := h.full.ChainCall(context.TODO(), getworker, nil)
r, err := h.full.StateCall(context.TODO(), getworker, nil)
if err != nil {
return xerrors.Errorf("getting worker address: %w", err)
}

View File

@ -3,19 +3,21 @@ package gen
import (
"bytes"
"context"
"crypto/sha256"
"math/big"
"fmt"
"sync/atomic"
"github.com/ipfs/go-blockservice"
"github.com/ipfs/go-car"
offline "github.com/ipfs/go-ipfs-exchange-offline"
"github.com/ipfs/go-merkledag"
peer "github.com/libp2p/go-libp2p-peer"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/build"
"github.com/filecoin-project/go-lotus/chain"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/stmgr"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/wallet"
@ -41,8 +43,10 @@ type ChainGen struct {
cs *store.ChainStore
genesis *types.BlockHeader
curBlock *types.FullBlock
sm *stmgr.StateManager
genesis *types.BlockHeader
curTipset *store.FullTipSet
w *wallet.Wallet
@ -118,9 +122,17 @@ func NewGenerator() (*ChainGen, error) {
}
}
/*
minercfg := &GenMinerCfg{
Workers: []address.Address{worker, worker},
Owners: []address.Address{worker, worker},
PeerIDs: []peer.ID{"peerID1", "peerID2"},
}
*/
minercfg := &GenMinerCfg{
Worker: worker,
Owner: worker,
Workers: []address.Address{worker},
Owners: []address.Address{worker},
PeerIDs: []peer.ID{"peerID1"},
}
genb, err := MakeGenesisBlock(bs, map[address.Address]types.BigInt{
@ -134,28 +146,32 @@ func NewGenerator() (*ChainGen, error) {
cs := store.NewChainStore(bs, ds)
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)
}
if minercfg.MinerAddr == address.Undef {
if len(minercfg.MinerAddrs) == 0 {
return nil, xerrors.Errorf("MakeGenesisBlock failed to set miner address")
}
sm := stmgr.NewStateManager(cs)
gen := &ChainGen{
bs: bs,
cs: cs,
sm: sm,
msgsPerBlock: msgsPerBlock,
genesis: genb.Genesis,
w: w,
miners: []address.Address{minercfg.MinerAddr},
mworkers: []address.Address{worker},
miners: minercfg.MinerAddrs,
mworkers: minercfg.Workers,
banker: banker,
receivers: receievers,
curBlock: genfb,
curTipset: gents,
r: mr,
lr: lr,
@ -182,19 +198,35 @@ func (cg *ChainGen) GenesisCar() ([]byte, error) {
return out.Bytes(), nil
}
func (cg *ChainGen) nextBlockProof(ctx context.Context) (address.Address, types.ElectionProof, []*types.Ticket, error) {
func (cg *ChainGen) nextBlockProof(ctx context.Context, m address.Address, ticks []*types.Ticket) (types.ElectionProof, *types.Ticket, error) {
pts := cg.curTipset.TipSet()
ticks := cg.curBlock.Header.Tickets
lastTicket := ticks[len(ticks)-1]
fmt.Println("checking winner:", m, ticks)
var lastTicket *types.Ticket
if len(ticks) == 0 {
lastTicket = pts.MinTicket()
} else {
lastTicket = ticks[len(ticks)-1]
}
vrfout, err := ComputeVRF(ctx, cg.w.Sign, cg.mworkers[0], lastTicket.VDFResult)
st, err := cg.sm.TipSetState(pts.Cids())
if err != nil {
return address.Undef, nil, nil, err
return nil, nil, err
}
worker, err := stmgr.GetMinerWorker(ctx, cg.sm, st, m)
if err != nil {
return nil, nil, err
}
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, lastTicket.VDFResult)
if err != nil {
return nil, nil, err
}
out, proof, err := vdf.Run(vrfout)
if err != nil {
return address.Undef, nil, nil, err
return nil, nil, err
}
tick := &types.Ticket{
@ -203,7 +235,15 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context) (address.Address, types.
VDFResult: out,
}
return cg.miners[0], []byte("cat in a box"), []*types.Ticket{tick}, nil
win, eproof, err := IsRoundWinner(ctx, pts, append(ticks, tick), m, &mca{w: cg.w, sm: cg.sm})
if err != nil {
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
}
if !win {
return nil, tick, nil
}
return eproof, tick, nil
}
type MinedTipSet struct {
@ -212,13 +252,64 @@ type MinedTipSet struct {
}
func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
miner, proof, tickets, err := cg.nextBlockProof(context.TODO())
var blks []*types.FullBlock
ticketSets := make([][]*types.Ticket, len(cg.miners))
msgs, err := cg.getRandomMessages()
if err != nil {
return nil, err
}
// make some transfers from banker
for len(blks) == 0 {
for i, m := range cg.miners {
fmt.Println("Checking for winner: ", m)
proof, t, err := cg.nextBlockProof(context.TODO(), m, ticketSets[i])
if err != nil {
return nil, err
}
ticketSets[i] = append(ticketSets[i], t)
if proof != nil {
fmt.Println("WINNER!!!!", m)
fblk, err := cg.makeBlock(m, proof, ticketSets[i], msgs)
if err != nil {
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
}
if err := cg.cs.AddBlock(fblk.Header); err != nil {
return nil, err
}
blks = append(blks, fblk)
}
}
}
fmt.Println("num winners: ", len(blks))
cg.curTipset = store.NewFullTipSet(blks)
return &MinedTipSet{
TipSet: cg.curTipset,
Messages: msgs,
}, nil
}
func (cg *ChainGen) makeBlock(m address.Address, eproof types.ElectionProof, tickets []*types.Ticket, msgs []*types.SignedMessage) (*types.FullBlock, error) {
parents := cg.curTipset.TipSet()
ts := parents.MinTimestamp() + (uint64(len(tickets)) * build.BlockDelay)
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, tickets, eproof, msgs, ts)
if err != nil {
return nil, err
}
return fblk, err
}
func (cg *ChainGen) getRandomMessages() ([]*types.SignedMessage, error) {
msgs := make([]*types.SignedMessage, cg.msgsPerBlock)
for m := range msgs {
msg := types.Message{
@ -255,30 +346,7 @@ func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
}
}
// create block
parents, err := types.NewTipSet([]*types.BlockHeader{cg.curBlock.Header})
if err != nil {
return nil, err
}
ts := parents.MinTimestamp() + (uint64(len(tickets)) * build.BlockDelay)
fblk, err := MinerCreateBlock(context.TODO(), cg.cs, cg.w, miner, parents, tickets, proof, msgs, ts)
if err != nil {
return nil, err
}
if err := cg.cs.AddBlock(fblk.Header); err != nil {
return nil, err
}
cg.curBlock = fblk
return &MinedTipSet{
TipSet: store.NewFullTipSet([]*types.FullBlock{fblk}),
Messages: msgs,
}, nil
return msgs, nil
}
func (cg *ChainGen) YieldRepo() (repo.Repo, error) {
@ -289,7 +357,7 @@ func (cg *ChainGen) YieldRepo() (repo.Repo, error) {
}
type MiningCheckAPI interface {
ChainGetRandomness(context.Context, *types.TipSet) ([]byte, error)
ChainGetRandomness(context.Context, *types.TipSet, []*types.Ticket, int) ([]byte, error)
StateMinerPower(context.Context, address.Address, *types.TipSet) (api.MinerPower, error)
@ -298,12 +366,47 @@ type MiningCheckAPI interface {
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
}
type mca struct {
w *wallet.Wallet
sm *stmgr.StateManager
}
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)
}
func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, ts *types.TipSet) (api.MinerPower, error) {
mpow, tpow, err := chain.GetPower(ctx, mca.sm, ts, maddr)
if err != nil {
return api.MinerPower{}, err
}
return api.MinerPower{
MinerPower: mpow,
TotalPower: tpow,
}, err
}
func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, ts *types.TipSet) (address.Address, error) {
st, err := mca.sm.TipSetState(ts.Cids())
if err != nil {
return address.Undef, err
}
return stmgr.GetMinerWorker(ctx, mca.sm, st, maddr)
}
func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*types.Signature, error) {
return mca.w.Sign(ctx, a, v)
}
func IsRoundWinner(ctx context.Context, ts *types.TipSet, ticks []*types.Ticket, miner address.Address, a MiningCheckAPI) (bool, types.ElectionProof, error) {
r, err := a.ChainGetRandomness(ctx, ts)
r, err := a.ChainGetRandomness(ctx, ts, ticks, build.RandomnessLookback)
if err != nil {
return false, nil, err
}
fmt.Println("chain randomness: ", r)
mworker, err := a.StateMinerWorker(ctx, miner, ts)
if err != nil {
return false, nil, xerrors.Errorf("failed to get miner worker: %w", err)
@ -319,23 +422,20 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, ticks []*types.Ticket,
return false, nil, xerrors.Errorf("failed to check power: %w", err)
}
return PowerCmp(vrfout, pow.MinerPower, pow.TotalPower), vrfout, nil
return types.PowerCmp(vrfout, pow.MinerPower, pow.TotalPower), vrfout, nil
}
func PowerCmp(vrfout []byte, mpow, totpow types.BigInt) bool {
type SignFunc func(context.Context, address.Address, []byte) (*types.Signature, error)
/*
Need to check that
h(vrfout) / 2^256 < minerPower / totalPower
*/
func ComputeVRF(ctx context.Context, sign SignFunc, w address.Address, input []byte) ([]byte, error) {
sig, err := sign(ctx, w, input)
if err != nil {
return nil, err
}
h := sha256.Sum256(vrfout)
if sig.Type != types.KTBLS {
return nil, fmt.Errorf("miner worker address was not a BLS key")
}
// 2^256
rden := types.BigInt{big.NewInt(0).Exp(big.NewInt(2), big.NewInt(256), nil)}
top := types.BigMul(rden, mpow)
out := types.BigDiv(top, totpow)
return types.BigCmp(types.BigFromBytes(h[:]), out) < 0
return sig.Data, nil
}

View File

@ -1,6 +1,7 @@
package gen
import (
"fmt"
"testing"
)
@ -13,11 +14,12 @@ func testGeneration(t testing.TB, n int, msgs int) {
g.msgsPerBlock = msgs
for i := 0; i < n; i++ {
fmt.Println("LOOP: ", i)
mts, err := g.NextTipSet()
if err != nil {
t.Fatalf("error at H:%d, %s", i, err)
}
if mts.TipSet.TipSet().Height() != uint64(i+1) {
if mts.TipSet.TipSet().Height() != uint64(i+len(mts.TipSet.Blocks[0].Header.Tickets)) {
t.Fatal("wrong height")
}
}

View File

@ -11,31 +11,31 @@ import (
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/stmgr"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/vm"
"github.com/filecoin-project/go-lotus/chain/wallet"
)
func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, w *wallet.Wallet, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, timestamp uint64) (*types.FullBlock, error) {
st, err := cs.TipSetState(parents.Cids())
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, timestamp uint64) (*types.FullBlock, error) {
st, err := sm.TipSetState(parents.Cids())
if err != nil {
return nil, errors.Wrap(err, "failed to load tipset state")
}
height := parents.Height() + uint64(len(tickets))
vmi, err := vm.NewVM(st, height, miner, cs)
vmi, err := vm.NewVM(st, height, miner, sm.ChainStore())
if err != nil {
return nil, err
}
owner, err := getMinerOwner(ctx, cs, st, miner)
owner, err := stmgr.GetMinerOwner(ctx, sm, st, miner)
if err != nil {
return nil, xerrors.Errorf("failed to get miner owner: %w", err)
}
worker, err := getMinerWorker(ctx, cs, st, miner)
worker, err := stmgr.GetMinerWorker(ctx, sm, st, miner)
if err != nil {
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
}
@ -46,11 +46,12 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, w *wallet.Walle
}
next := &types.BlockHeader{
Miner: miner,
Parents: parents.Cids(),
Tickets: tickets,
Height: height,
Timestamp: timestamp,
Miner: miner,
Parents: parents.Cids(),
Tickets: tickets,
Height: height,
Timestamp: timestamp,
ElectionProof: proof,
}
var blsMessages []*types.Message
@ -63,7 +64,7 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, w *wallet.Walle
blsSigs = append(blsSigs, msg.Signature)
blsMessages = append(blsMessages, &msg.Message)
c, err := cs.PutMessage(&msg.Message)
c, err := sm.ChainStore().PutMessage(&msg.Message)
if err != nil {
return nil, err
}
@ -93,7 +94,7 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, w *wallet.Walle
receipts = append(receipts, rec.MessageReceipt)
}
cst := hamt.CSTFromBstore(cs.Blockstore())
cst := hamt.CSTFromBstore(sm.ChainStore().Blockstore())
blsmsgroot, err := sharray.Build(context.TODO(), 4, toIfArr(blsMsgCids), cst)
if err != nil {
return nil, err
@ -130,7 +131,7 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, w *wallet.Walle
next.BLSAggregate = aggSig
next.StateRoot = stateRoot
pweight := cs.Weight(parents)
pweight := sm.ChainStore().Weight(parents)
next.ParentWeight = types.NewInt(pweight)
// TODO: set timestamp
@ -161,40 +162,6 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, w *wallet.Walle
return fullBlock, nil
}
func getMinerWorker(ctx context.Context, cs *store.ChainStore, state cid.Cid, maddr address.Address) (address.Address, error) {
rec, err := vm.CallRaw(ctx, cs, &types.Message{
To: maddr,
From: maddr,
Method: actors.MAMethods.GetWorkerAddr,
}, state, 0)
if err != nil {
return address.Undef, err
}
if rec.ExitCode != 0 {
return address.Undef, xerrors.Errorf("getWorker failed with exit code %d", rec.ExitCode)
}
return address.NewFromBytes(rec.Return)
}
func getMinerOwner(ctx context.Context, cs *store.ChainStore, state cid.Cid, maddr address.Address) (address.Address, error) {
rec, err := vm.CallRaw(ctx, cs, &types.Message{
To: maddr,
From: maddr,
Method: actors.MAMethods.GetOwner,
}, state, 0)
if err != nil {
return address.Undef, err
}
if rec.ExitCode != 0 {
return address.Undef, xerrors.Errorf("getOwner failed with exit code %d", rec.ExitCode)
}
return address.NewFromBytes(rec.Return)
}
func aggregateSignatures(sigs []types.Signature) (types.Signature, error) {
var blsSigs []bls.Signature
for _, s := range sigs {

View File

@ -140,16 +140,16 @@ func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) {
}
type GenMinerCfg struct {
Owner address.Address
Worker address.Address
Owners []address.Address
Workers []address.Address
// not quite generating real sectors yet, but this will be necessary
//SectorDir string
// The address of the created miner, this is set by the genesis setup
MinerAddr address.Address
// The addresses of the created miner, this is set by the genesis setup
MinerAddrs []address.Address
PeerID peer.ID
PeerIDs []peer.ID
}
func mustEnc(i interface{}) []byte {
@ -166,67 +166,78 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
}
params := mustEnc(actors.CreateStorageMinerParams{
Owner: gmcfg.Owner,
Worker: gmcfg.Worker,
SectorSize: types.NewInt(build.SectorSize),
PeerID: gmcfg.PeerID,
})
for i := 0; i < len(gmcfg.Workers); i++ {
owner := gmcfg.Owners[i]
worker := gmcfg.Workers[i]
pid := gmcfg.PeerIDs[i]
rval, err := doExec(ctx, vm, actors.StorageMarketAddress, gmcfg.Owner, actors.SMAMethods.CreateStorageMiner, params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
params := mustEnc(actors.CreateStorageMinerParams{
Owner: owner,
Worker: worker,
SectorSize: types.NewInt(build.SectorSize),
PeerID: pid,
})
rval, err := doExec(ctx, vm, actors.StorageMarketAddress, owner, actors.SMAMethods.CreateStorageMiner, params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err)
}
maddr, err := address.NewFromBytes(rval)
if err != nil {
return cid.Undef, err
}
gmcfg.MinerAddrs = append(gmcfg.MinerAddrs, maddr)
params = mustEnc(actors.UpdateStorageParams{Delta: types.NewInt(5000)})
_, err = doExec(ctx, vm, actors.StorageMarketAddress, maddr, actors.SMAMethods.UpdateStorage, params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to update total storage: %w", err)
}
// UGLY HACKY MODIFICATION OF MINER POWER
// we have to flush the vm here because it buffers stuff internally for perf reasons
if _, err := vm.Flush(ctx); err != nil {
return cid.Undef, xerrors.Errorf("vm.Flush failed: %w", err)
}
st := vm.StateTree()
mact, err := st.GetActor(maddr)
if err != nil {
return cid.Undef, xerrors.Errorf("get miner actor failed: %w", err)
}
cst := hamt.CSTFromBstore(cs.Blockstore())
var mstate actors.StorageMinerActorState
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
return cid.Undef, xerrors.Errorf("getting miner actor state failed: %w", err)
}
mstate.Power = types.NewInt(5000)
nstate, err := cst.Put(ctx, mstate)
if err != nil {
return cid.Undef, err
}
mact.Head = nstate
if err := st.SetActor(maddr, mact); err != nil {
return cid.Undef, err
}
// End of super haxx
}
maddr, err := address.NewFromBytes(rval)
if err != nil {
return cid.Undef, err
}
gmcfg.MinerAddr = maddr
params = mustEnc(actors.UpdateStorageParams{Delta: types.NewInt(5000)})
_, err = doExec(ctx, vm, actors.StorageMarketAddress, maddr, actors.SMAMethods.UpdateStorage, params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to update total storage: %w", err)
}
// UGLY HACKY MODIFICATION OF MINER POWER
// we have to flush the vm here because it buffers stuff internally for perf reasons
if _, err := vm.Flush(ctx); err != nil {
return cid.Undef, xerrors.Errorf("vm.Flush failed: %w", err)
}
st := vm.StateTree()
mact, err := st.GetActor(maddr)
if err != nil {
return cid.Undef, xerrors.Errorf("get miner actor failed: %w", err)
}
cst := hamt.CSTFromBstore(cs.Blockstore())
var mstate actors.StorageMinerActorState
if err := cst.Get(ctx, mact.Head, &mstate); err != nil {
return cid.Undef, xerrors.Errorf("getting miner actor state failed: %w", err)
}
mstate.Power = types.NewInt(5000)
nstate, err := cst.Put(ctx, mstate)
if err != nil {
return cid.Undef, err
}
mact.Head = nstate
if err := st.SetActor(maddr, mact); err != nil {
return cid.Undef, err
}
// End of super haxx
return vm.Flush(ctx)
}
func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method uint64, params []byte) ([]byte, error) {
act, err := vm.StateTree().GetActor(from)
if err != nil {
return nil, xerrors.Errorf("doExec failed to get from actor: %w", err)
}
ret, err := vm.ApplyMessage(context.TODO(), &types.Message{
To: to,
From: from,
@ -235,6 +246,7 @@ func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method uin
GasLimit: types.NewInt(1000000),
GasPrice: types.NewInt(0),
Value: types.NewInt(0),
Nonce: act.Nonce,
})
if err != nil {
return nil, err
@ -322,19 +334,3 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B
Genesis: b,
}, nil
}
type SignFunc func(context.Context, address.Address, []byte) (*types.Signature, error)
func ComputeVRF(ctx context.Context, sign SignFunc, w address.Address, input []byte) ([]byte, error) {
sig, err := sign(ctx, w, input)
if err != nil {
return nil, err
}
if sig.Type != types.KTBLS {
return nil, fmt.Errorf("miner worker address was not a BLS key")
}
return sig.Data, nil
}

View File

@ -5,7 +5,7 @@ import (
"sync"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/stmgr"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/pkg/errors"
)
@ -15,7 +15,7 @@ type MessagePool struct {
pending map[address.Address]*msgSet
cs *store.ChainStore
sm *stmgr.StateManager
}
type msgSet struct {
@ -36,12 +36,12 @@ func (ms *msgSet) add(m *types.SignedMessage) {
ms.msgs[m.Message.Nonce] = m
}
func NewMessagePool(cs *store.ChainStore) *MessagePool {
func NewMessagePool(sm *stmgr.StateManager) *MessagePool {
mp := &MessagePool{
pending: make(map[address.Address]*msgSet),
cs: cs,
sm: sm,
}
cs.SubscribeHeadChanges(mp.HeadChange)
sm.ChainStore().SubscribeHeadChanges(mp.HeadChange)
return mp
}
@ -61,7 +61,7 @@ func (mp *MessagePool) Add(m *types.SignedMessage) error {
return err
}
if _, err := mp.cs.PutMessage(m); err != nil {
if _, err := mp.sm.ChainStore().PutMessage(m); err != nil {
return err
}
@ -84,7 +84,7 @@ func (mp *MessagePool) GetNonce(addr address.Address) (uint64, error) {
return mset.startNonce + uint64(len(mset.msgs)), nil
}
act, err := mp.cs.GetActor(addr)
act, err := mp.sm.GetActor(addr)
if err != nil {
return 0, err
}
@ -130,7 +130,7 @@ func (mp *MessagePool) Pending() []*types.SignedMessage {
func (mp *MessagePool) HeadChange(revert []*types.TipSet, apply []*types.TipSet) error {
for _, ts := range revert {
for _, b := range ts.Blocks() {
bmsgs, smsgs, err := mp.cs.MessagesForBlock(b)
bmsgs, smsgs, err := mp.sm.ChainStore().MessagesForBlock(b)
if err != nil {
return errors.Wrapf(err, "failed to get messages for revert block %s(height %d)", b.Cid(), b.Height)
}
@ -155,7 +155,7 @@ func (mp *MessagePool) HeadChange(revert []*types.TipSet, apply []*types.TipSet)
for _, ts := range apply {
for _, b := range ts.Blocks() {
bmsgs, smsgs, err := mp.cs.MessagesForBlock(b)
bmsgs, smsgs, err := mp.sm.ChainStore().MessagesForBlock(b)
if err != nil {
return errors.Wrapf(err, "failed to get messages for apply block %s(height %d) (msgroot = %s)", b.Cid(), b.Height, b.Messages)
}

View File

@ -1,17 +1,18 @@
package vm
package stmgr
import (
"context"
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/vm"
cid "github.com/ipfs/go-cid"
"golang.org/x/xerrors"
)
func CallRaw(ctx context.Context, cs *store.ChainStore, msg *types.Message, bstate cid.Cid, bheight uint64) (*types.MessageReceipt, error) {
vmi, err := NewVM(bstate, bheight, actors.NetworkAddress, cs)
func CallRaw(ctx context.Context, sm *StateManager, msg *types.Message, bstate cid.Cid, bheight uint64) (*types.MessageReceipt, error) {
vmi, err := vm.NewVM(bstate, bheight, actors.NetworkAddress, sm.cs)
if err != nil {
return nil, xerrors.Errorf("failed to set up vm: %w", err)
}
@ -32,7 +33,7 @@ func CallRaw(ctx context.Context, cs *store.ChainStore, msg *types.Message, bsta
}
}
fromActor, err := vmi.cstate.GetActor(msg.From)
fromActor, err := vmi.StateTree().GetActor(msg.From)
if err != nil {
return nil, err
}
@ -52,15 +53,15 @@ func CallRaw(ctx context.Context, cs *store.ChainStore, msg *types.Message, bsta
}
func Call(ctx context.Context, cs *store.ChainStore, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
func Call(ctx context.Context, sm *StateManager, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
if ts == nil {
ts = cs.GetHeaviestTipSet()
ts = sm.cs.GetHeaviestTipSet()
}
state, err := cs.TipSetState(ts.Cids())
state, err := sm.TipSetState(ts.Cids())
if err != nil {
return nil, err
}
return CallRaw(ctx, cs, msg, state, ts.Height())
return CallRaw(ctx, sm, msg, state, ts.Height())
}

129
chain/stmgr/stmgr.go Normal file
View File

@ -0,0 +1,129 @@
package stmgr
import (
"context"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/state"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/vm"
"github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
logging "github.com/ipfs/go-log"
)
var log = logging.Logger("chainstore")
type StateManager struct {
cs *store.ChainStore
}
func NewStateManager(cs *store.ChainStore) *StateManager {
return &StateManager{cs}
}
func (sm *StateManager) TipSetState(cids []cid.Cid) (cid.Cid, error) {
ctx := context.TODO()
ts, err := sm.cs.LoadTipSet(cids)
if err != nil {
log.Error("failed loading tipset: ", cids)
return cid.Undef, err
}
if len(ts.Blocks()) == 1 {
return ts.Blocks()[0].StateRoot, nil
}
pstate, err := sm.TipSetState(ts.Parents())
if err != nil {
return cid.Undef, err
}
vmi, err := vm.NewVM(pstate, ts.Height(), address.Undef, sm.cs)
if err != nil {
return cid.Undef, err
}
applied := make(map[cid.Cid]bool)
for _, b := range ts.Blocks() {
vmi.SetBlockMiner(b.Miner)
bms, sms, err := sm.cs.MessagesForBlock(b)
if err != nil {
return cid.Undef, err
}
for _, m := range bms {
if applied[m.Cid()] {
continue
}
applied[m.Cid()] = true
_, err := vmi.ApplyMessage(ctx, m)
if err != nil {
return cid.Undef, err
}
}
for _, sm := range sms {
if applied[sm.Cid()] {
continue
}
applied[sm.Cid()] = true
_, err := vmi.ApplyMessage(ctx, &sm.Message)
if err != nil {
return cid.Undef, err
}
}
}
return vmi.Flush(ctx)
}
func (sm *StateManager) GetActor(addr address.Address) (*types.Actor, error) {
ts := sm.cs.GetHeaviestTipSet()
stcid, err := sm.TipSetState(ts.Cids())
if err != nil {
return nil, err
}
cst := hamt.CSTFromBstore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, stcid)
if err != nil {
return nil, err
}
return state.GetActor(addr)
}
func (sm *StateManager) GetBalance(addr address.Address) (types.BigInt, error) {
act, err := sm.GetActor(addr)
if err != nil {
return types.BigInt{}, err
}
return act.Balance, nil
}
func (sm *StateManager) ChainStore() *store.ChainStore {
return sm.cs
}
func (sm *StateManager) LoadActorState(ctx context.Context, a address.Address, out interface{}) (*types.Actor, error) {
act, err := sm.GetActor(a)
if err != nil {
return nil, err
}
cst := hamt.CSTFromBstore(sm.cs.Blockstore())
if err := cst.Get(ctx, act.Head, out); err != nil {
return nil, err
}
return act, nil
}

63
chain/stmgr/utils.go Normal file
View File

@ -0,0 +1,63 @@
package stmgr
import (
"context"
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
cid "github.com/ipfs/go-cid"
"golang.org/x/xerrors"
)
func GetMinerWorker(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
recp, err := CallRaw(ctx, sm, &types.Message{
To: maddr,
From: maddr,
Method: actors.MAMethods.GetWorkerAddr,
}, st, 0)
if err != nil {
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
}
if recp.ExitCode != 0 {
return address.Undef, xerrors.Errorf("getting miner worker addr failed (exit code %d)", recp.ExitCode)
}
worker, err := address.NewFromBytes(recp.Return)
if err != nil {
return address.Undef, err
}
if worker.Protocol() == address.ID {
return address.Undef, xerrors.Errorf("need to resolve worker address to a pubkeyaddr")
}
return worker, nil
}
func GetMinerOwner(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
recp, err := CallRaw(ctx, sm, &types.Message{
To: maddr,
From: maddr,
Method: actors.MAMethods.GetOwner,
}, st, 0)
if err != nil {
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
}
if recp.ExitCode != 0 {
return address.Undef, xerrors.Errorf("getting miner owner addr failed (exit code %d)", recp.ExitCode)
}
owner, err := address.NewFromBytes(recp.Return)
if err != nil {
return address.Undef, err
}
if owner.Protocol() == address.ID {
return address.Undef, xerrors.Errorf("need to resolve owner address to a pubkeyaddr")
}
return owner, nil
}

View File

@ -2,12 +2,11 @@ package store
import (
"context"
"crypto/sha256"
"encoding/json"
"fmt"
"sync"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/state"
"github.com/filecoin-project/go-lotus/chain/types"
"golang.org/x/xerrors"
@ -462,21 +461,6 @@ func (cs *ChainStore) GetGenesis() (*types.BlockHeader, error) {
return types.DecodeBlock(genb.RawData())
}
func (cs *ChainStore) TipSetState(cids []cid.Cid) (cid.Cid, error) {
ts, err := cs.LoadTipSet(cids)
if err != nil {
log.Error("failed loading tipset: ", cids)
return cid.Undef, err
}
if len(ts.Blocks()) == 1 {
return ts.Blocks()[0].StateRoot, nil
}
panic("cant handle multiblock tipsets yet")
}
func (cs *ChainStore) GetMessage(c cid.Cid) (*types.Message, error) {
sb, err := cs.bs.Get(c)
if err != nil {
@ -604,31 +588,6 @@ func (cs *ChainStore) LoadSignedMessagesFromCids(cids []cid.Cid) ([]*types.Signe
return msgs, nil
}
func (cs *ChainStore) GetBalance(addr address.Address) (types.BigInt, error) {
act, err := cs.GetActor(addr)
if err != nil {
return types.BigInt{}, err
}
return act.Balance, nil
}
func (cs *ChainStore) GetActor(addr address.Address) (*types.Actor, error) {
ts := cs.GetHeaviestTipSet()
stcid, err := cs.TipSetState(ts.Cids())
if err != nil {
return nil, err
}
cst := hamt.CSTFromBstore(cs.bs)
state, err := state.LoadStateTree(cst, stcid)
if err != nil {
return nil, err
}
return state.GetActor(addr)
}
func (cs *ChainStore) WaitForMessage(ctx context.Context, mcid cid.Cid) (cid.Cid, *types.MessageReceipt, error) {
tsub := cs.SubHeadChanges(ctx)
@ -737,3 +696,44 @@ 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) {
t := tickets[len(tickets)-(1+lb)]
return t.VDFResult, nil
}
nv := lb - len(tickets)
for {
fmt.Println("lookback looping: ", nv)
nts, err := cs.LoadTipSet(pts.Cids())
if err != nil {
return nil, err
}
mtb := nts.MinTicketBlock()
if nv < len(mtb.Tickets) {
t := mtb.Tickets[len(mtb.Tickets)-(1+nv)]
return t.VDFResult, nil
}
nv -= len(mtb.Tickets)
// special case for lookback behind genesis block
// TODO(spec): this is not in the spec, need to sync that
if mtb.Height == 0 {
fmt.Println("Randomness from height 0: ", nv)
t := mtb.Tickets[0]
rval := t.VDFResult
for i := 0; i < nv; i++ {
h := sha256.Sum256(rval)
rval = h[:]
}
return rval, nil
}
}
}

View File

@ -11,6 +11,7 @@ import (
"github.com/filecoin-project/go-lotus/build"
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/stmgr"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/vm"
@ -34,6 +35,9 @@ type Syncer struct {
// The interface for accessing and putting tipsets into local storage
store *store.ChainStore
// the state manager handles making state queries
sm *stmgr.StateManager
// The known Genesis tipset
Genesis *types.TipSet
@ -53,8 +57,8 @@ type Syncer struct {
peerHeadsLk sync.Mutex
}
func NewSyncer(cs *store.ChainStore, bsync *BlockSync, self peer.ID) (*Syncer, error) {
gen, err := cs.GetGenesis()
func NewSyncer(sm *stmgr.StateManager, bsync *BlockSync, self peer.ID) (*Syncer, error) {
gen, err := sm.ChainStore().GetGenesis()
if err != nil {
return nil, err
}
@ -68,7 +72,8 @@ func NewSyncer(cs *store.ChainStore, bsync *BlockSync, self peer.ID) (*Syncer, e
Genesis: gent,
Bsync: bsync,
peerHeads: make(map[peer.ID]*types.TipSet),
store: cs,
store: sm.ChainStore(),
sm: sm,
self: self,
}, nil
}
@ -320,7 +325,7 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
return err
}
ret, err := vm.Call(ctx, syncer.store, &types.Message{
ret, err := stmgr.Call(ctx, syncer.sm, &types.Message{
To: actors.StorageMarketAddress,
From: maddr,
Method: actors.SMAMethods.IsMiner,
@ -353,7 +358,6 @@ func (syncer *Syncer) validateTickets(ctx context.Context, mworker address.Addre
Data: next.VRFProof,
}
log.Infof("About to verify signature: ", sig.Data, mworker, cur.VDFResult)
if err := sig.Verify(mworker, cur.VDFResult); err != nil {
return xerrors.Errorf("invalid ticket, VRFProof invalid: %w", err)
}
@ -369,62 +373,10 @@ func (syncer *Syncer) validateTickets(ctx context.Context, mworker address.Addre
return nil
}
func getMinerWorker(ctx context.Context, cs *store.ChainStore, st cid.Cid, maddr address.Address) (address.Address, error) {
recp, err := vm.CallRaw(ctx, cs, &types.Message{
To: maddr,
From: maddr,
Method: actors.MAMethods.GetWorkerAddr,
}, st, 0)
if err != nil {
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
}
if recp.ExitCode != 0 {
return address.Undef, xerrors.Errorf("getting miner worker addr failed (exit code %d)", recp.ExitCode)
}
worker, err := address.NewFromBytes(recp.Return)
if err != nil {
return address.Undef, err
}
if worker.Protocol() == address.ID {
return address.Undef, xerrors.Errorf("need to resolve worker address to a pubkeyaddr")
}
return worker, nil
}
func getMinerOwner(ctx context.Context, cs *store.ChainStore, st cid.Cid, maddr address.Address) (address.Address, error) {
recp, err := vm.CallRaw(ctx, cs, &types.Message{
To: maddr,
From: maddr,
Method: actors.MAMethods.GetOwner,
}, st, 0)
if err != nil {
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
}
if recp.ExitCode != 0 {
return address.Undef, xerrors.Errorf("getting miner owner addr failed (exit code %d)", recp.ExitCode)
}
owner, err := address.NewFromBytes(recp.Return)
if err != nil {
return address.Undef, err
}
if owner.Protocol() == address.ID {
return address.Undef, xerrors.Errorf("need to resolve owner address to a pubkeyaddr")
}
return owner, nil
}
// Should match up with 'Semantical Validation' in validation.md in the spec
func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) error {
h := b.Header
stateroot, err := syncer.store.TipSetState(h.Parents)
stateroot, err := syncer.sm.TipSetState(h.Parents)
if err != nil {
return xerrors.Errorf("get tipsetstate(%d, %s) failed: %w", h.Height, h.Parents, err)
}
@ -447,21 +399,39 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return xerrors.Errorf("minerIsValid failed: %w", err)
}
waddr, err := getMinerWorker(ctx, syncer.store, stateroot, h.Miner)
waddr, err := stmgr.GetMinerWorker(ctx, syncer.sm, stateroot, h.Miner)
if err != nil {
return xerrors.Errorf("getMinerWorker failed: %w", err)
return xerrors.Errorf("GetMinerWorker failed: %w", err)
}
if err := syncer.validateTickets(ctx, waddr, h.Tickets, baseTs); err != nil {
return xerrors.Errorf("validating block tickets failed: %w", err)
}
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs, h.Tickets, build.RandomnessLookback)
if err != nil {
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
}
if err := VerifyElectionProof(ctx, h.ElectionProof, rand, waddr); err != nil {
return xerrors.Errorf("checking eproof failed: %w", err)
}
mpow, tpow, err := GetPower(ctx, syncer.sm, baseTs, h.Miner)
if err != nil {
return xerrors.Errorf("failed getting power: %w", err)
}
if !types.PowerCmp(h.ElectionProof, mpow, tpow) {
return xerrors.Errorf("miner created a block but was not a winner")
}
vmi, err := vm.NewVM(stateroot, h.Height, h.Miner, syncer.store)
if err != nil {
return xerrors.Errorf("failed to instantiate VM: %w", err)
}
owner, err := getMinerOwner(ctx, syncer.store, stateroot, b.Header.Miner)
owner, err := stmgr.GetMinerOwner(ctx, syncer.sm, stateroot, b.Header.Miner)
if err != nil {
return xerrors.Errorf("getting miner owner for block miner failed: %w", err)
}
@ -572,7 +542,7 @@ func (syncer *Syncer) collectHeaders(from *types.TipSet, to *types.TipSet) ([]*t
func (syncer *Syncer) syncMessagesAndCheckState(headers []*types.TipSet) error {
return syncer.iterFullTipsets(headers, func(fts *store.FullTipSet) error {
log.Warn("validating tipset: ", fts.TipSet().Height())
log.Warnf("validating tipset (heigt=%d, size=%d)", fts.TipSet().Height(), len(fts.TipSet().Cids()))
if err := syncer.ValidateTipSet(context.TODO(), fts); err != nil {
log.Errorf("failed to validate tipset: %s", err)
return xerrors.Errorf("message processing failed: %w", err)
@ -692,3 +662,59 @@ func (syncer *Syncer) collectChain(fts *store.FullTipSet) error {
return nil
}
func VerifyElectionProof(ctx context.Context, eproof []byte, rand []byte, worker address.Address) error {
sig := types.Signature{
Data: eproof,
Type: types.KTBLS,
}
if err := sig.Verify(worker, rand); err != nil {
return xerrors.Errorf("failed to verify election proof signature: %w", err)
}
return nil
}
func GetPower(ctx context.Context, sm *stmgr.StateManager, ts *types.TipSet, maddr address.Address) (types.BigInt, types.BigInt, error) {
var err error
enc, err := actors.SerializeParams(&actors.PowerLookupParams{maddr})
if err != nil {
return types.EmptyInt, types.EmptyInt, err
}
var mpow types.BigInt
if maddr != address.Undef {
ret, err := stmgr.Call(ctx, sm, &types.Message{
From: maddr,
To: actors.StorageMarketAddress,
Method: actors.SMAMethods.PowerLookup,
Params: enc,
}, ts)
if err != nil {
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get miner power from chain: %w", err)
}
if ret.ExitCode != 0 {
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get miner power from chain (exit code %d)", ret.ExitCode)
}
mpow = types.BigFromBytes(ret.Return)
}
ret, err := stmgr.Call(ctx, sm, &types.Message{
From: actors.StorageMarketAddress,
To: actors.StorageMarketAddress,
Method: actors.SMAMethods.GetTotalStorage,
}, ts)
if err != nil {
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err)
}
if ret.ExitCode != 0 {
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain (exit code %d)", ret.ExitCode)
}
tpow := types.BigFromBytes(ret.Return)
return mpow, tpow, nil
}

View File

@ -2,6 +2,8 @@ package types
import (
"bytes"
"crypto/sha256"
"math/big"
block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
@ -87,6 +89,10 @@ func (blk *BlockHeader) Serialize() ([]byte, error) {
return buf.Bytes(), nil
}
func (blk *BlockHeader) LastTicket() *Ticket {
return blk.Tickets[len(blk.Tickets)-1]
}
type MsgMeta struct {
BlsMessages cid.Cid
SecpkMessages cid.Cid
@ -126,3 +132,21 @@ func CidArrsEqual(a, b []cid.Cid) bool {
}
return true
}
func PowerCmp(eproof ElectionProof, mpow, totpow BigInt) bool {
/*
Need to check that
h(vrfout) / 2^256 < minerPower / totalPower
*/
h := sha256.Sum256(eproof)
// 2^256
rden := BigInt{big.NewInt(0).Exp(big.NewInt(2), big.NewInt(256), nil)}
top := BigMul(rden, mpow)
out := BigDiv(top, totpow)
return BigCmp(BigFromBytes(h[:]), out) < 0
}

View File

@ -96,19 +96,13 @@ func (ts *TipSet) Equals(ots *TipSet) bool {
return true
}
func (ts *TipSet) MinTicket() *Ticket {
if len(ts.Blocks()) == 0 {
panic("tipset has no blocks!")
}
var minTicket *Ticket
for _, b := range ts.Blocks() {
lastTicket := b.Tickets[len(b.Tickets)-1]
if minTicket == nil || bytes.Compare(lastTicket.VDFResult, minTicket.VDFResult) < 0 {
minTicket = lastTicket
}
}
func (t *Ticket) Less(o *Ticket) bool {
return bytes.Compare(t.VDFResult, o.VDFResult) < 0
}
return minTicket
func (ts *TipSet) MinTicket() *Ticket {
b := ts.MinTicketBlock()
return b.Tickets[len(b.Tickets)-1]
}
func (ts *TipSet) MinTimestamp() uint64 {
@ -120,3 +114,17 @@ func (ts *TipSet) MinTimestamp() uint64 {
}
return minTs
}
func (ts *TipSet) MinTicketBlock() *BlockHeader {
blks := ts.Blocks()
min := blks[0]
for _, b := range blks[1:] {
if b.LastTicket().Less(min.LastTicket()) {
min = b
}
}
return min
}

View File

@ -41,6 +41,8 @@ func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method uint6
code, ok := inv.builtInCode[act.Code]
if !ok {
fmt.Println("bad code? ", act.Code)
fmt.Println("miner actor code cid: ", actors.StorageMinerCodeCid)
return nil, aerrors.Newf(255, "no code for actor %s", act.Code)
}
if method >= uint64(len(code)) || code[method] == nil {

View File

@ -454,6 +454,10 @@ func (vm *VM) ApplyMessage(ctx context.Context, msg *types.Message) (*ApplyRet,
}, nil
}
func (vm *VM) SetBlockMiner(m address.Address) {
vm.blockMiner = m
}
func (vm *VM) ActorBalance(addr address.Address) (types.BigInt, aerrors.ActorError) {
act, err := vm.cstate.GetActor(addr)
if err != nil {

View File

@ -143,7 +143,7 @@ func configureStorageMiner(ctx context.Context, api api.FullNode, addr address.A
}
// This really just needs to be an api call at this point...
recp, err := api.ChainCall(ctx, &types.Message{
recp, err := api.StateCall(ctx, &types.Message{
To: addr,
From: addr,
Method: actors.MAMethods.GetWorkerAddr,

View File

@ -232,7 +232,7 @@ func (m *Miner) computeVRF(ctx context.Context, input []byte) ([]byte, error) {
}
func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
ret, err := m.api.ChainCall(ctx, &types.Message{
ret, err := m.api.StateCall(ctx, &types.Message{
From: addr,
To: addr,
Method: actors.MAMethods.GetWorkerAddr,

View File

@ -20,6 +20,7 @@ import (
"github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/chain"
"github.com/filecoin-project/go-lotus/chain/deals"
"github.com/filecoin-project/go-lotus/chain/stmgr"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/wallet"
@ -201,6 +202,7 @@ func Online() Option {
Override(HandleIncomingMessagesKey, modules.HandleIncomingMessages),
Override(new(*store.ChainStore), modules.ChainStore),
Override(new(*stmgr.StateManager), stmgr.NewStateManager),
Override(new(*wallet.Wallet), wallet.NewWallet),
Override(new(dtypes.ChainGCLocker), blockstore.NewGCLocker),

View File

@ -5,17 +5,11 @@ import (
"github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/chain"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/gen"
"github.com/filecoin-project/go-lotus/chain/state"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/vm"
"github.com/filecoin-project/go-lotus/lib/bufbstore"
"golang.org/x/xerrors"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"go.uber.org/fx"
)
@ -51,9 +45,8 @@ func (a *ChainAPI) ChainHead(context.Context) (*types.TipSet, error) {
return a.Chain.GetHeaviestTipSet(), nil
}
func (a *ChainAPI) ChainGetRandomness(ctx context.Context, pts *types.TipSet) ([]byte, error) {
// TODO: this needs to look back in the chain for the right random beacon value
return []byte("foo bar random"), nil
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)
}
func (a *ChainAPI) ChainWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait, error) {
@ -113,72 +106,3 @@ func (a *ChainAPI) ChainGetBlockReceipts(ctx context.Context, bcid cid.Cid) ([]*
return out, nil
}
func (a *ChainAPI) ChainCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
return vm.Call(ctx, a.Chain, msg, ts)
}
func (a *ChainAPI) stateForTs(ts *types.TipSet) (*state.StateTree, error) {
if ts == nil {
ts = a.Chain.GetHeaviestTipSet()
}
st, err := a.Chain.TipSetState(ts.Cids())
if err != nil {
return nil, err
}
buf := bufbstore.NewBufferedBstore(a.Chain.Blockstore())
cst := hamt.CSTFromBstore(buf)
return state.LoadStateTree(cst, st)
}
func (a *ChainAPI) ChainGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) {
state, err := a.stateForTs(ts)
if err != nil {
return nil, err
}
return state.GetActor(actor)
}
func (a *ChainAPI) ChainReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*api.ActorState, error) {
state, err := a.stateForTs(ts)
if err != nil {
return nil, err
}
blk, err := state.Store.Blocks.GetBlock(ctx, act.Head)
if err != nil {
return nil, err
}
oif, err := vm.DumpActorState(act.Code, blk.RawData())
if err != nil {
return nil, err
}
return &api.ActorState{
Balance: act.Balance,
State: oif,
}, nil
}
// This is on ChainAPI because miner.Miner requires this, and MinerAPI requires miner.Miner
func (a *ChainAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, ts uint64) (*chain.BlockMsg, error) {
fblk, err := gen.MinerCreateBlock(ctx, a.Chain, a.Wallet, addr, parents, tickets, proof, msgs, ts)
if err != nil {
return nil, err
}
var out chain.BlockMsg
out.Header = fblk.Header
for _, msg := range fblk.BlsMessages {
out.BlsMessages = append(out.BlsMessages, msg.Cid())
}
for _, msg := range fblk.SecpkMessages {
out.SecpkMessages = append(out.SecpkMessages, msg.Cid())
}
return &out, nil
}

View File

@ -35,6 +35,7 @@ type ClientAPI struct {
fx.In
ChainAPI
StateAPI
WalletAPI
PaychAPI
@ -62,7 +63,7 @@ func (a *ClientAPI) ClientStartDeal(ctx context.Context, data cid.Cid, miner add
Method: actors.MAMethods.GetPeerID,
}
r, err := a.ChainCall(ctx, msg, nil)
r, err := a.StateCall(ctx, msg, nil)
if err != nil {
return nil, err
}

View File

@ -5,15 +5,20 @@ import (
"fmt"
"strconv"
"github.com/filecoin-project/go-lotus/chain"
"github.com/filecoin-project/go-lotus/chain/gen"
"github.com/filecoin-project/go-lotus/chain/stmgr"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/vm"
"github.com/filecoin-project/go-lotus/chain/wallet"
"github.com/filecoin-project/go-lotus/lib/bufbstore"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-lotus/api"
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/state"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor"
@ -23,18 +28,23 @@ import (
type StateAPI struct {
fx.In
Chain *store.ChainStore
// TODO: the wallet here is only needed because we have the MinerCreateBlock
// API attached to the state API. It probably should live somewhere better
Wallet *wallet.Wallet
StateManager *stmgr.StateManager
Chain *store.ChainStore
}
func (a *StateAPI) StateMinerSectors(ctx context.Context, addr address.Address) ([]*api.SectorInfo, error) {
ts := a.Chain.GetHeaviestTipSet()
ts := a.StateManager.ChainStore().GetHeaviestTipSet()
stc, err := a.Chain.TipSetState(ts.Cids())
stc, err := a.StateManager.TipSetState(ts.Cids())
if err != nil {
return nil, err
}
cst := hamt.CSTFromBstore(a.Chain.Blockstore())
cst := hamt.CSTFromBstore(a.StateManager.ChainStore().Blockstore())
st, err := state.LoadStateTree(cst, stc)
if err != nil {
@ -87,7 +97,7 @@ func (a *StateAPI) StateMinerSectors(ctx context.Context, addr address.Address)
func (a *StateAPI) StateMinerProvingSet(ctx context.Context, addr address.Address) ([]*api.SectorInfo, error) {
ts := a.Chain.GetHeaviestTipSet()
stc, err := a.Chain.TipSetState(ts.Cids())
stc, err := a.StateManager.TipSetState(ts.Cids())
if err != nil {
return nil, err
}
@ -152,7 +162,7 @@ func (a *StateAPI) StateMinerPower(ctx context.Context, maddr address.Address, t
var mpow types.BigInt
if maddr != address.Undef {
ret, err := vm.Call(ctx, a.Chain, &types.Message{
ret, err := stmgr.Call(ctx, a.StateManager, &types.Message{
From: maddr,
To: actors.StorageMarketAddress,
Method: actors.SMAMethods.PowerLookup,
@ -168,7 +178,7 @@ func (a *StateAPI) StateMinerPower(ctx context.Context, maddr address.Address, t
mpow = types.BigFromBytes(ret.Return)
}
ret, err := vm.Call(ctx, a.Chain, &types.Message{
ret, err := stmgr.Call(ctx, a.StateManager, &types.Message{
From: actors.StorageMarketAddress,
To: actors.StorageMarketAddress,
Method: actors.SMAMethods.GetTotalStorage,
@ -189,7 +199,7 @@ func (a *StateAPI) StateMinerPower(ctx context.Context, maddr address.Address, t
}
func (a *StateAPI) StateMinerWorker(ctx context.Context, m address.Address, ts *types.TipSet) (address.Address, error) {
ret, err := vm.Call(ctx, a.Chain, &types.Message{
ret, err := stmgr.Call(ctx, a.StateManager, &types.Message{
From: m,
To: m,
Method: actors.MAMethods.GetWorkerAddr,
@ -209,3 +219,72 @@ func (a *StateAPI) StateMinerWorker(ctx context.Context, m address.Address, ts *
return w, nil
}
func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
return stmgr.Call(ctx, a.StateManager, msg, ts)
}
func (a *StateAPI) stateForTs(ts *types.TipSet) (*state.StateTree, error) {
if ts == nil {
ts = a.Chain.GetHeaviestTipSet()
}
st, err := a.StateManager.TipSetState(ts.Cids())
if err != nil {
return nil, err
}
buf := bufbstore.NewBufferedBstore(a.Chain.Blockstore())
cst := hamt.CSTFromBstore(buf)
return state.LoadStateTree(cst, st)
}
func (a *StateAPI) StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) {
state, err := a.stateForTs(ts)
if err != nil {
return nil, err
}
return state.GetActor(actor)
}
func (a *StateAPI) StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*api.ActorState, error) {
state, err := a.stateForTs(ts)
if err != nil {
return nil, err
}
blk, err := state.Store.Blocks.GetBlock(ctx, act.Head)
if err != nil {
return nil, err
}
oif, err := vm.DumpActorState(act.Code, blk.RawData())
if err != nil {
return nil, err
}
return &api.ActorState{
Balance: act.Balance,
State: oif,
}, nil
}
// This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, ts uint64) (*chain.BlockMsg, error) {
fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, tickets, proof, msgs, ts)
if err != nil {
return nil, err
}
var out chain.BlockMsg
out.Header = fblk.Header
for _, msg := range fblk.BlsMessages {
out.BlsMessages = append(out.BlsMessages, msg.Cid())
}
for _, msg := range fblk.SecpkMessages {
out.SecpkMessages = append(out.SecpkMessages, msg.Cid())
}
return &out, nil
}

View File

@ -4,7 +4,7 @@ import (
"context"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/stmgr"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/wallet"
@ -15,8 +15,8 @@ import (
type WalletAPI struct {
fx.In
Chain *store.ChainStore
Wallet *wallet.Wallet
StateManager *stmgr.StateManager
Wallet *wallet.Wallet
}
func (a *WalletAPI) WalletNew(ctx context.Context, typ string) (address.Address, error) {
@ -32,7 +32,7 @@ func (a *WalletAPI) WalletList(ctx context.Context) ([]address.Address, error) {
}
func (a *WalletAPI) WalletBalance(ctx context.Context, addr address.Address) (types.BigInt, error) {
return a.Chain.GetBalance(addr)
return a.StateManager.GetBalance(addr)
}
func (a *WalletAPI) WalletSign(ctx context.Context, k address.Address, msg []byte) (*types.Signature, error) {

View File

@ -1,7 +1,7 @@
package modules
import (
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/stmgr"
"github.com/filecoin-project/go-lotus/node/modules/dtypes"
"github.com/filecoin-project/go-lotus/paych"
)
@ -10,6 +10,6 @@ func PaychStore(ds dtypes.MetadataDS) *paych.Store {
return paych.NewStore(ds)
}
func PaymentChannelManager(chain *store.ChainStore, store *paych.Store) (*paych.Manager, error) {
return paych.NewManager(chain, store), nil
func PaymentChannelManager(sm *stmgr.StateManager, store *paych.Store) (*paych.Manager, error) {
return paych.NewManager(sm, store), nil
}

View File

@ -12,6 +12,7 @@ import (
offline "github.com/ipfs/go-ipfs-exchange-offline"
logging "github.com/ipfs/go-log"
"github.com/ipfs/go-merkledag"
peer "github.com/libp2p/go-libp2p-peer"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/gen"
@ -34,8 +35,9 @@ func MakeGenesisMem(out io.Writer) func(bs dtypes.ChainBlockstore, w *wallet.Wal
}
gmc := &gen.GenMinerCfg{
Owner: w,
Worker: w,
Owners: []address.Address{w},
Workers: []address.Address{w},
PeerIDs: []peer.ID{"peerID 1"},
}
alloc := map[address.Address]types.BigInt{
w: types.NewInt(100000),
@ -68,8 +70,9 @@ func MakeGenesis(outFile string) func(bs dtypes.ChainBlockstore, w *wallet.Walle
}
gmc := &gen.GenMinerCfg{
Owner: minerAddr,
Worker: minerAddr,
Owners: []address.Address{minerAddr},
Workers: []address.Address{minerAddr},
PeerIDs: []peer.ID{"peer ID 1"},
}
addrs := map[address.Address]types.BigInt{
@ -81,7 +84,7 @@ func MakeGenesis(outFile string) func(bs dtypes.ChainBlockstore, w *wallet.Walle
return nil, err
}
fmt.Println("GENESIS MINER ADDRESS: ", gmc.MinerAddr.String())
fmt.Println("GENESIS MINER ADDRESS: ", gmc.MinerAddrs[0].String())
f, err := os.OpenFile(outFile, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {

View File

@ -4,28 +4,25 @@ import (
"context"
"fmt"
hamt "github.com/ipfs/go-hamt-ipld"
logging "github.com/ipfs/go-log"
"github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/state"
"github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/stmgr"
"github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/vm"
)
var log = logging.Logger("paych")
type Manager struct {
chain *store.ChainStore
store *Store
sm *stmgr.StateManager
}
func NewManager(chain *store.ChainStore, pchstore *Store) *Manager {
func NewManager(sm *stmgr.StateManager, pchstore *Store) *Manager {
return &Manager{
chain: chain,
store: pchstore,
sm: sm,
}
}
@ -148,7 +145,7 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address
return false, err
}
ret, err := vm.Call(ctx, pm.chain, &types.Message{
ret, err := stmgr.Call(ctx, pm.sm, &types.Message{
From: owner,
To: ch,
Method: actors.PCAMethods.UpdateChannelState,
@ -166,24 +163,9 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address
}
func (pm *Manager) loadPaychState(ctx context.Context, ch address.Address) (*types.Actor, *actors.PaymentChannelActorState, error) {
st, err := pm.chain.TipSetState(pm.chain.GetHeaviestTipSet().Cids())
if err != nil {
return nil, nil, err
}
cst := hamt.CSTFromBstore(pm.chain.Blockstore())
tree, err := state.LoadStateTree(cst, st)
if err != nil {
return nil, nil, err
}
act, err := tree.GetActor(ch)
if err != nil {
return nil, nil, err
}
var pcast actors.PaymentChannelActorState
if err := cst.Get(ctx, act.Head, &pcast); err != nil {
act, err := pm.sm.LoadActorState(ctx, ch, &pcast)
if err != nil {
return nil, nil, err
}
@ -191,7 +173,7 @@ func (pm *Manager) loadPaychState(ctx context.Context, ch address.Address) (*typ
}
func (pm *Manager) getPaychOwner(ctx context.Context, ch address.Address) (address.Address, error) {
ret, err := vm.Call(ctx, pm.chain, &types.Message{
ret, err := stmgr.Call(ctx, pm.sm, &types.Message{
From: ch,
To: ch,
Method: actors.PCAMethods.GetOwner,

View File

@ -41,7 +41,7 @@ type storageMinerApi interface {
//ReadState(ctx context.Context, addr address.Address) (????, error)
// Call a read only method on actors (no interaction with the chain required)
ChainCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error)
StateCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error)
MpoolPush(context.Context, *types.SignedMessage) error
MpoolGetNonce(context.Context, address.Address) (uint64, error)
@ -201,7 +201,7 @@ func (m *Miner) getWorkerAddr(ctx context.Context) (address.Address, error) {
Params: actors.EmptyStructCBOR,
}
recpt, err := m.api.ChainCall(ctx, msg, nil)
recpt, err := m.api.StateCall(ctx, msg, nil)
if err != nil {
return address.Undef, errors.Wrapf(err, "calling getWorker(%s)", m.maddr)
}