182 lines
4.5 KiB
Go
182 lines
4.5 KiB
Go
|
package full
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
|
||
|
"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"
|
||
|
|
||
|
"github.com/ipfs/go-cid"
|
||
|
"github.com/ipfs/go-hamt-ipld"
|
||
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||
|
"go.uber.org/fx"
|
||
|
)
|
||
|
|
||
|
type ChainAPI struct {
|
||
|
fx.In
|
||
|
|
||
|
Chain *store.ChainStore
|
||
|
PubSub *pubsub.PubSub
|
||
|
}
|
||
|
|
||
|
func (a *ChainAPI) ChainNotify(ctx context.Context) (<-chan *store.HeadChange, error) {
|
||
|
return a.Chain.SubHeadChanges(ctx), nil
|
||
|
}
|
||
|
|
||
|
func (a *ChainAPI) ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) error {
|
||
|
if err := a.Chain.AddBlock(blk.Header); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
b, err := blk.Serialize()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// TODO: anything else to do here?
|
||
|
return a.PubSub.Publish("/fil/blocks", b)
|
||
|
}
|
||
|
|
||
|
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) ChainWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait, error) {
|
||
|
blkcid, recpt, err := a.Chain.WaitForMessage(ctx, msg)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &api.MsgWait{
|
||
|
InBlock: blkcid,
|
||
|
Receipt: *recpt,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (a *ChainAPI) ChainGetBlock(ctx context.Context, msg cid.Cid) (*types.BlockHeader, error) {
|
||
|
return a.Chain.GetBlock(msg)
|
||
|
}
|
||
|
|
||
|
func (a *ChainAPI) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (*api.BlockMessages, error) {
|
||
|
b, err := a.Chain.GetBlock(msg)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
bmsgs, smsgs, err := a.Chain.MessagesForBlock(b)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &api.BlockMessages{
|
||
|
BlsMessages: bmsgs,
|
||
|
SecpkMessages: smsgs,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (a *ChainAPI) ChainGetBlockReceipts(ctx context.Context, bcid cid.Cid) ([]*types.MessageReceipt, error) {
|
||
|
b, err := a.Chain.GetBlock(bcid)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
// TODO: need to get the number of messages better than this
|
||
|
bm, sm, err := a.Chain.MessagesForBlock(b)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
var out []*types.MessageReceipt
|
||
|
for i := 0; i < len(bm)+len(sm); i++ {
|
||
|
r, err := a.Chain.GetReceipt(b, i)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
out = append(out, r)
|
||
|
}
|
||
|
|
||
|
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) (*chain.BlockMsg, error) {
|
||
|
fblk, err := gen.MinerCreateBlock(ctx, a.Chain, addr, parents, tickets, proof, msgs)
|
||
|
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
|
||
|
}
|