Merge pull request #51 from filecoin-project/feat/more-methods

Add more methods (IsMiner, GetPower)
This commit is contained in:
Jakub Sztandera 2019-07-17 20:38:13 +02:00 committed by GitHub
commit 6e24543e57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 149 additions and 27 deletions

View File

@ -89,12 +89,24 @@ type StorageMinerConstructorParams struct {
func (sma StorageMinerActor) Exports() []interface{} { func (sma StorageMinerActor) Exports() []interface{} {
return []interface{}{ return []interface{}{
sma.StorageMinerActor, 0: sma.StorageMinerConstructor,
sma.CommitSector, 1: sma.CommitSector,
//2: sma.SubmitPost,
//3: sma.SlashStorageFault,
//4: sma.GetCurrentProvingSet,
//5: sma.ArbitrateDeal,
//6: sma.DePledge,
//7: sma.GetOwner,
//8: sma.GetWorkerAddr,
9: sma.GetPower,
//10: sma.GetPeerID,
//11: sma.GetSectorSize,
//12: sma.UpdatePeerID,
//13: sma.ChangeWorker,
} }
} }
func (sma StorageMinerActor) StorageMinerActor(act *types.Actor, vmctx types.VMContext, params *StorageMinerConstructorParams) (types.InvokeRet, error) { func (sma StorageMinerActor) StorageMinerConstructor(act *types.Actor, vmctx types.VMContext, params *StorageMinerConstructorParams) (types.InvokeRet, error) {
var self StorageMinerActorState var self StorageMinerActorState
self.Owner = params.Owner self.Owner = params.Owner
self.Worker = params.Worker self.Worker = params.Worker
@ -209,6 +221,17 @@ func (sma StorageMinerActor) CommitSector(act *types.Actor, vmctx types.VMContex
return types.InvokeRet{}, nil return types.InvokeRet{}, nil
} }
func (sma StorageMinerActor) GetPower(act *types.Actor, vmctx types.VMContext, params *struct{}) (types.InvokeRet, error) {
var self StorageMinerActorState
state := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(state, &self); err != nil {
return types.InvokeRet{}, err
}
return types.InvokeRet{
Result: self.Power.Bytes(),
}, nil
}
func SectorIsUnique(cst *hamt.CborIpldStore, sroot cid.Cid, sid types.BigInt) (bool, error) { func SectorIsUnique(cst *hamt.CborIpldStore, sroot cid.Cid, sid types.BigInt) (bool, error) {
nd, err := hamt.LoadNode(context.TODO(), cst, sroot) nd, err := hamt.LoadNode(context.TODO(), cst, sroot)
if err != nil { if err != nil {

View File

@ -6,6 +6,7 @@ import (
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
"golang.org/x/xerrors"
) )
const SectorSize = 1024 const SectorSize = 1024
@ -13,16 +14,22 @@ const SectorSize = 1024
func init() { func init() {
cbor.RegisterCborType(StorageMarketState{}) cbor.RegisterCborType(StorageMarketState{})
cbor.RegisterCborType(CreateStorageMinerParams{}) cbor.RegisterCborType(CreateStorageMinerParams{})
cbor.RegisterCborType(IsMinerParam{})
cbor.RegisterCborType(PowerLookupParams{})
} }
type StorageMarketActor struct{} type StorageMarketActor struct{}
func (sma StorageMarketActor) Exports() []interface{} { func (sma StorageMarketActor) Exports() []interface{} {
return []interface{}{ return []interface{}{
nil, //0: sma.StorageMarketConstructor,
sma.CreateStorageMiner, 1: sma.CreateStorageMiner,
nil, // TODO: slash consensus fault //2: sma.SlashConsensusFault,
sma.UpdateStorage, 3: sma.UpdateStorage,
4: sma.GetTotalStorage,
5: sma.PowerLookup,
6: sma.IsMiner,
//7: sma.StorageCollateralForSize,
} }
} }
@ -61,17 +68,17 @@ func (sma StorageMarketActor) CreateStorageMiner(act *types.Actor, vmctx types.V
return types.InvokeRet{}, err return types.InvokeRet{}, err
} }
naddr, err := address.NewFromBytes(ret)
if err != nil {
return types.InvokeRet{}, err
}
if exit != 0 { if exit != 0 {
return types.InvokeRet{ return types.InvokeRet{
ReturnCode: 2, ReturnCode: 2,
}, nil }, nil
} }
naddr, err := address.NewFromBytes(ret)
if err != nil {
return types.InvokeRet{}, err
}
var self StorageMarketState var self StorageMarketState
old := vmctx.Storage().GetHead() old := vmctx.Storage().GetHead()
if err := vmctx.Storage().Get(old, &self); err != nil { if err := vmctx.Storage().Get(old, &self); err != nil {
@ -123,7 +130,7 @@ func (sma StorageMarketActor) UpdateStorage(act *types.Actor, vmctx types.VMCont
return types.InvokeRet{}, nil return types.InvokeRet{}, nil
} }
func (sma StorageMarketActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params struct{}) (types.InvokeRet, error) { func (sma StorageMarketActor) GetTotalStorage(act *types.Actor, vmctx types.VMContext, params *struct{}) (types.InvokeRet, error) {
var self StorageMarketState var self StorageMarketState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil { if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return types.InvokeRet{}, err return types.InvokeRet{}, err
@ -141,7 +148,7 @@ type PowerLookupParams struct {
func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) (types.InvokeRet, error) { func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContext, params *PowerLookupParams) (types.InvokeRet, error) {
var self StorageMarketState var self StorageMarketState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil { if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return types.InvokeRet{}, err return types.InvokeRet{}, xerrors.Errorf("getting head: %w", err)
} }
if _, ok := self.Miners[params.Miner]; !ok { if _, ok := self.Miners[params.Miner]; !ok {
@ -151,9 +158,9 @@ func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContex
}, nil }, nil
} }
ret, code, err := vmctx.Send(params.Miner, 9999, types.NewInt(0), nil) ret, code, err := vmctx.Send(params.Miner, 9, types.NewInt(0), EmptyStructCBOR)
if err != nil { if err != nil {
return types.InvokeRet{}, err return types.InvokeRet{}, xerrors.Errorf("invoke Miner.GetPower: %w", err)
} }
if code != 0 { if code != 0 {
@ -167,3 +174,22 @@ func (sma StorageMarketActor) PowerLookup(act *types.Actor, vmctx types.VMContex
Result: ret, Result: ret,
}, nil }, nil
} }
type IsMinerParam struct {
Addr address.Address
}
func (sma StorageMarketActor) IsMiner(act *types.Actor, vmctx types.VMContext, param *IsMinerParam) (types.InvokeRet, error) {
var self StorageMarketState
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &self); err != nil {
return types.InvokeRet{}, err
}
_, ok := self.Miners[param.Addr]
out, err := SerializeParams(ok)
if err != nil {
return types.InvokeRet{}, err
}
return types.InvokeRet{
Result: out,
}, nil
}

View File

@ -9,9 +9,14 @@ import (
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
) )
func TestDumpEmpyStruct(t *testing.T) {
res, err := SerializeParams(struct{}{})
t.Logf("res: %x, err: %+v", res, err)
}
func TestStorageMarketCreateMiner(t *testing.T) { func TestStorageMarketCreateMiner(t *testing.T) {
h := NewHarness(t) h := NewHarness(t)
var outaddr address.Address var sminer address.Address
h.Steps = []Step{ h.Steps = []Step{
{ {
M: types.Message{ M: types.Message{
@ -34,19 +39,69 @@ func TestStorageMarketCreateMiner(t *testing.T) {
} }
var err error var err error
outaddr, err = address.NewFromBytes(ret.Return) sminer, err = address.NewFromBytes(ret.Return)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if outaddr.String() != "t0102" { if sminer.String() != "t0102" {
t.Fatal("hold up") t.Fatal("hold up")
} }
h.Steps[1].M.Params = h.DumpObject(&IsMinerParam{Addr: sminer})
h.Steps[2].M.Params = h.DumpObject(&PowerLookupParams{Miner: sminer})
},
},
{
M: types.Message{
To: StorageMarketAddress,
From: h.From,
Method: 6,
GasPrice: types.NewInt(1),
GasLimit: types.NewInt(1),
Value: types.NewInt(0),
Nonce: 1,
// Params is sent in previous set
},
Ret: func(t *testing.T, ret *types.MessageReceipt) {
if ret.ExitCode != 0 {
t.Fatal("invokation failed: ", ret.ExitCode)
}
var output bool
err := cbor.DecodeInto(ret.Return, &output)
if err != nil {
t.Fatalf("error decoding: %+v", err)
}
if !output {
t.Fatalf("%s is miner but IsMiner call returned false", sminer)
}
},
},
{
M: types.Message{
To: StorageMarketAddress,
From: h.From,
Method: 5,
GasPrice: types.NewInt(1),
GasLimit: types.NewInt(1),
Value: types.NewInt(0),
Nonce: 2,
// Params is sent in previous set
},
Ret: func(t *testing.T, ret *types.MessageReceipt) {
if ret.ExitCode != 0 {
t.Fatal("invokation failed: ", ret.ExitCode)
}
power := types.BigFromBytes(ret.Return)
if types.BigCmp(power, types.NewInt(0)) != 0 {
t.Fatalf("power should be zero, is: %s", power)
}
}, },
}, },
} }
state := h.Execute() state := h.Execute()
act, err := state.GetActor(outaddr) act, err := state.GetActor(sminer)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -103,7 +103,7 @@ func (h *Harness) DumpObject(obj interface{}) []byte {
} }
func (h *Harness) NoError(t *testing.T, err error) { func (h *Harness) NoError(t *testing.T, err error) {
if err != nil { if err != nil {
t.Fatalf("Error in step %d: %s", h.currStep, err) t.Fatalf("Error in step %d: %+v", h.currStep, err)
} }
} }

13
chain/actors/params.go Normal file
View File

@ -0,0 +1,13 @@
package actors
import (
cbor "github.com/ipfs/go-ipld-cbor"
)
var (
EmptyStructCBOR = []byte{0xa0}
)
func SerializeParams(i interface{}) ([]byte, error) {
return cbor.DumpObject(i)
}

View File

@ -8,6 +8,7 @@ import (
"github.com/filecoin-project/go-lotus/chain/types" "github.com/filecoin-project/go-lotus/chain/types"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"golang.org/x/xerrors"
) )
type invoker struct { type invoker struct {
@ -34,10 +35,10 @@ func (inv *invoker) Invoke(act *types.Actor, vmctx *VMContext, method uint64, pa
code, ok := inv.builtInCode[act.Code] code, ok := inv.builtInCode[act.Code]
if !ok { if !ok {
return types.InvokeRet{}, fmt.Errorf("no code for actor %s", act.Code) return types.InvokeRet{}, xerrors.Errorf("no code for actor %s", act.Code)
} }
if method >= uint64(len(code)) || code[method] == nil { if method >= uint64(len(code)) || code[method] == nil {
return types.InvokeRet{}, fmt.Errorf("no method %d on actor", method) return types.InvokeRet{}, xerrors.Errorf("no method %d on actor", method)
} }
return code[method](act, vmctx, params) return code[method](act, vmctx, params)
@ -63,7 +64,8 @@ func (*invoker) transform(instance Invokee) (nativeCode, error) {
exports := instance.Exports() exports := instance.Exports()
for i, m := range exports { for i, m := range exports {
i := i i := i
newErr := func(str string) error { newErr := func(format string, args ...interface{}) error {
str := fmt.Sprintf(format, args)
return fmt.Errorf("transform(%s) export(%d): %s", itype.Name(), i, str) return fmt.Errorf("transform(%s) export(%d): %s", itype.Name(), i, str)
} }
if m == nil { if m == nil {
@ -86,7 +88,8 @@ func (*invoker) transform(instance Invokee) (nativeCode, error) {
} }
if t.In(2).Kind() != reflect.Ptr { if t.In(2).Kind() != reflect.Ptr {
return nil, newErr("parameter has to be a pointer to parameter") return nil, newErr("parameter has to be a pointer to parameter, is: %s",
t.In(2).Kind())
} }
if t.NumOut() != 2 { if t.NumOut() != 2 {

View File

@ -30,7 +30,7 @@ type VMContext struct {
// address that started invokation chain // address that started invokation chain
origin address.Address origin address.Address
storage types.Storage storage *storage
} }
// Message is the message that kicked off the current invocation // Message is the message that kicked off the current invocation
@ -215,7 +215,7 @@ func (vm *VM) ApplyMessage(msg *types.Message) (*types.MessageReceipt, error) {
if msg.Method != 0 { if msg.Method != 0 {
ret, errcode, err = vm.Invoke(toActor, vmctx, msg.Method, msg.Params) ret, errcode, err = vm.Invoke(toActor, vmctx, msg.Method, msg.Params)
if err != nil { if err != nil {
return nil, err return nil, xerrors.Errorf("during invoke: %w", err)
} }
if errcode != 0 { if errcode != 0 {
@ -226,6 +226,8 @@ func (vm *VM) ApplyMessage(msg *types.Message) (*types.MessageReceipt, error) {
panic("invariant violated: " + err.Error()) panic("invariant violated: " + err.Error())
} }
} else { } else {
// Update actor head reference
toActor.Head = vmctx.storage.head
// refund unused gas // refund unused gas
refund := types.BigMul(types.BigSub(msg.GasLimit, vmctx.GasUsed()), msg.GasPrice) refund := types.BigMul(types.BigSub(msg.GasLimit, vmctx.GasUsed()), msg.GasPrice)
DepositFunds(fromActor, refund) DepositFunds(fromActor, refund)