refactor state utilities into StateManager package, implement proper election proofs

This commit is contained in:
whyrusleeping
2019-09-09 19:14:00 -07:00
parent 6e21372ccb
commit ed45d1c2b4
29 changed files with 796 additions and 483 deletions
+2 -78
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
}
+2 -1
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
}
+88 -9
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
}
+4 -4
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) {