actors: Implement cron actor

This commit is contained in:
Łukasz Magiera 2019-11-22 23:51:44 +01:00
parent 5bfcc307e9
commit 96023d415e
11 changed files with 119 additions and 12 deletions

View File

@ -0,0 +1,48 @@
package actors
import (
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/types"
)
type CronActor struct{}
type callTuple struct {
addr address.Address
method uint64
}
var CronActors = []callTuple{
{StoragePowerAddress, SPAMethods.CheckProofSubmissions},
}
type CronActorState struct{}
type cAMethods struct {
EpochTick uint64
}
var CAMethods = cAMethods{2}
func (ca CronActor) Exports() []interface{} {
return []interface{}{
1: nil,
2: ca.EpochTick,
}
}
func (ca CronActor) EpochTick(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) {
if vmctx.Message().From != CronAddress {
return nil, aerrors.New(1, "EpochTick is only callable as a part of tipset state computation")
}
for _, call := range CronActors {
_, err := vmctx.Send(call.addr, call.method, types.NewInt(0), nil)
if err != nil {
return nil, err // todo: this very bad?
}
}
return nil, nil
}

View File

@ -170,7 +170,7 @@ func IsBuiltinActor(code cid.Cid) bool {
}
func IsSingletonActor(code cid.Cid) bool {
return code == StoragePowerCodeCid || code == StorageMarketCodeCid || code == InitCodeCid
return code == StoragePowerCodeCid || code == StorageMarketCodeCid || code == InitCodeCid || code == CronCodeCid
}
func (ias *InitActorState) AddActor(cst *hamt.CborIpldStore, addr address.Address) (address.Address, error) {

View File

@ -567,8 +567,8 @@ func pledgeCollateralForSize(vmctx types.VMContext, size, totalStorage types.Big
}
func (spa StoragePowerActor) CheckProofSubmissions(act *types.Actor, vmctx types.VMContext, param *struct{}) ([]byte, ActorError) {
if vmctx.Message().From != StoragePowerAddress {
return nil, aerrors.New(1, "CheckProofSubmissions is only callable as a part of tipset state computation")
if vmctx.Message().From != CronAddress {
return nil, aerrors.New(1, "CheckProofSubmissions is only callable from the cron actor")
}
var self StoragePowerState

View File

@ -8,6 +8,7 @@ import (
)
var AccountCodeCid cid.Cid
var CronCodeCid cid.Cid
var StoragePowerCodeCid cid.Cid
var StorageMarketCodeCid cid.Cid
var StorageMinerCodeCid cid.Cid
@ -19,6 +20,7 @@ var InitAddress = mustIDAddress(0)
var NetworkAddress = mustIDAddress(1)
var StoragePowerAddress = mustIDAddress(2)
var StorageMarketAddress = mustIDAddress(3) // TODO: missing from spec
var CronAddress = mustIDAddress(4)
var BurntFundsAddress = mustIDAddress(99)
func mustIDAddress(i uint64) address.Address {
@ -40,6 +42,7 @@ func init() {
}
AccountCodeCid = mustSum("fil/1/account") // TODO: spec
CronCodeCid = mustSum("fil/1/cron")
StoragePowerCodeCid = mustSum("fil/1/power")
StorageMarketCodeCid = mustSum("fil/1/market")
StorageMinerCodeCid = mustSum("fil/1/miner")

View File

@ -3976,3 +3976,32 @@ func (t *CheckMinerParams) UnmarshalCBOR(r io.Reader) error {
}
return nil
}
func (t *CronActorState) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{128}); err != nil {
return err
}
return nil
}
func (t *CronActorState) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 0 {
return fmt.Errorf("cbor input had wrong number of fields")
}
return nil
}

View File

@ -5,7 +5,7 @@ import (
"io"
"github.com/filecoin-project/lotus/chain/types"
cid "github.com/ipfs/go-cid"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)

View File

@ -89,6 +89,15 @@ func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types
return nil, xerrors.Errorf("set init actor: %w", err)
}
cronact, err := SetupCronActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup cron actor: %w", err)
}
if err := state.SetActor(actors.CronAddress, cronact); err != nil {
return nil, xerrors.Errorf("set cron actor: %w", err)
}
spact, err := SetupStoragePowerActor(bs)
if err != nil {
return nil, xerrors.Errorf("setup storage market actor: %w", err)
@ -144,6 +153,23 @@ func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types
return state, nil
}
func SetupCronActor(bs bstore.Blockstore) (*types.Actor, error) {
cst := hamt.CSTFromBstore(bs)
cas := &actors.CronActorState{}
stcid, err := cst.Put(context.TODO(), cas)
if err != nil {
return nil, err
}
return &types.Actor{
Code: actors.CronCodeCid,
Head: stcid,
Nonce: 0,
Balance: types.NewInt(0),
}, nil
}
func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) {
cst := hamt.CSTFromBstore(bs)
nd := hamt.NewNode(cst)

View File

@ -197,21 +197,20 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
}
}
// TODO: this nonce-getting is a ting bit ugly
spa, err := vmi.StateTree().GetActor(actors.StoragePowerAddress)
// TODO: this nonce-getting is a tiny bit ugly
ca, err := vmi.StateTree().GetActor(actors.CronAddress)
if err != nil {
return cid.Undef, cid.Undef, err
}
// TODO: cron actor
ret, err := vmi.ApplyMessage(ctx, &types.Message{
To: actors.StoragePowerAddress,
From: actors.StoragePowerAddress,
Nonce: spa.Nonce,
To: actors.CronAddress,
From: actors.CronAddress,
Nonce: ca.Nonce,
Value: types.NewInt(0),
GasPrice: types.NewInt(0),
GasLimit: types.NewInt(1 << 30), // Make super sure this is never too little
Method: actors.SPAMethods.CheckProofSubmissions,
Method: actors.CAMethods.EpochTick,
Params: nil,
})
if err != nil {

View File

@ -5,7 +5,7 @@ import (
"io"
"math"
cid "github.com/ipfs/go-cid"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)

View File

@ -31,6 +31,7 @@ func newInvoker() *invoker {
// add builtInCode using: register(cid, singleton)
inv.register(actors.InitCodeCid, actors.InitActor{}, actors.InitActorState{})
inv.register(actors.CronCodeCid, actors.CronActor{}, actors.CronActorState{})
inv.register(actors.StoragePowerCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{})
inv.register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{})
inv.register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{})

View File

@ -129,6 +129,7 @@ func main() {
actors.ComputeDataCommitmentParams{},
actors.SectorProveCommitInfo{},
actors.CheckMinerParams{},
actors.CronActorState{},
)
if err != nil {
fmt.Println(err)