Merge pull request #160 from filecoin-project/feat/gas3

Charge per put and get
This commit is contained in:
Jakub Sztandera 2019-08-27 22:45:38 +02:00 committed by GitHub
commit 24fb5ca624
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 131 deletions

View File

@ -6,7 +6,9 @@ import (
. "github.com/filecoin-project/go-lotus/chain/actors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/stretchr/testify/assert"
)
func TestDumpEmpyStruct(t *testing.T) {
@ -15,121 +17,62 @@ func TestDumpEmpyStruct(t *testing.T) {
}
func TestStorageMarketCreateMiner(t *testing.T) {
h := NewHarness(t)
var sminer address.Address
h.Steps = []Step{
{
M: types.Message{
To: StorageMarketAddress,
From: h.From,
Method: SMAMethods.CreateStorageMiner,
GasPrice: types.NewInt(1),
GasLimit: types.NewInt(1000),
Value: types.NewInt(0),
Params: h.DumpObject(&CreateStorageMinerParams{
Owner: h.From,
Worker: h.Third,
SectorSize: types.NewInt(SectorSize),
PeerID: "fakepeerid",
}),
},
Ret: func(t *testing.T, ret *types.MessageReceipt) {
if ret.ExitCode != 0 {
t.Fatal("invokation failed: ", ret.ExitCode)
}
var ownerAddr, workerAddr address.Address
var err error
sminer, err = address.NewFromBytes(ret.Return)
if err != nil {
t.Fatal(err)
}
if sminer.String() != "t0103" {
t.Fatalf("hold up got: %s", sminer)
}
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: SMAMethods.IsMiner,
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: SMAMethods.PowerLookup,
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()
act, err := state.GetActor(sminer)
if err != nil {
t.Fatal(err)
}
if act.Code != StorageMinerCodeCid {
t.Fatalf("Expected correct code, got %s, instead of %s", act.Code, StorageMinerCodeCid)
}
hblock, err := h.bs.Get(act.Head)
if err != nil {
t.Fatal(err)
opts := []HarnessOpt{
HarnessAddr(&ownerAddr, 10000),
HarnessAddr(&workerAddr, 10000),
}
smas := &StorageMinerActorState{}
err = cbor.DecodeInto(hblock.RawData(), smas)
if err != nil {
t.Fatal(err)
h := NewHarness2(t, opts...)
var minerAddr address.Address
{
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.CreateStorageMiner,
CreateStorageMinerParams{
Owner: ownerAddr,
Worker: workerAddr,
SectorSize: types.NewInt(SectorSize),
PeerID: "fakepeerid",
})
ApplyOK(t, ret)
var err error
minerAddr, err = address.NewFromBytes(ret.Return)
assert.NoError(t, err)
}
iblock, err := h.bs.Get(smas.Info)
if err != nil {
t.Fatal(err)
{
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.IsMiner,
IsMinerParam{Addr: minerAddr})
ApplyOK(t, ret)
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", minerAddr)
}
}
var minfo MinerInfo
if err := cbor.DecodeInto(iblock.RawData(), &minfo); err != nil {
t.Fatal(err)
{
ret, _ := h.Invoke(t, ownerAddr, StorageMarketAddress, SMAMethods.PowerLookup,
PowerLookupParams{Miner: minerAddr})
ApplyOK(t, ret)
power := types.BigFromBytes(ret.Return)
if types.BigCmp(power, types.NewInt(0)) != 0 {
t.Fatalf("power should be zero, is: %s", power)
}
}
if minfo.Owner != h.From {
t.Fatalf("Owner should be %s, but is %s", h.From, minfo.Owner)
{
ret, _ := h.Invoke(t, ownerAddr, minerAddr, MAMethods.GetOwner, nil)
ApplyOK(t, ret)
oA, err := address.NewFromBytes(ret.Return)
assert.NoError(t, err)
assert.Equal(t, ownerAddr, oA, "return from GetOwner should be equal to the owner")
}
}

View File

@ -22,7 +22,7 @@ import (
"github.com/filecoin-project/go-lotus/chain/wallet"
)
const testGasLimit = 100
const testGasLimit = 1000
type HarnessInit struct {
NAddrs uint64

View File

@ -234,7 +234,7 @@ func TestSyncMining(t *testing.T) {
require.NoError(t, tu.mn.LinkAll())
tu.connect(1, 0)
time.Sleep(time.Second * 2)
time.Sleep(time.Second * 4)
tu.checkHeight("client", client, H)

View File

@ -26,6 +26,9 @@ var log = logging.Logger("vm")
const (
gasFundTransfer = 10
gasGetObj = 10
gasPutObj = 20
gasCommit = 50
)
type VMContext struct {
@ -45,8 +48,6 @@ type VMContext struct {
// address that started invokation chain
origin address.Address
storage *storage
}
// Message is the message that kicked off the current invocation
@ -54,41 +55,47 @@ func (vmc *VMContext) Message() *types.Message {
return vmc.msg
}
type storage struct {
// would be great to stop depending on this crap everywhere
// I am my own worst enemy
cst *hamt.CborIpldStore
head cid.Cid
}
// Storage interface
func (s *storage) Put(i interface{}) (cid.Cid, aerrors.ActorError) {
c, err := s.cst.Put(context.TODO(), i)
func (vmc *VMContext) Put(i interface{}) (cid.Cid, aerrors.ActorError) {
if err := vmc.ChargeGas(gasPutObj); err != nil {
return cid.Undef, aerrors.Wrap(err, "out of gas")
}
c, err := vmc.cst.Put(context.TODO(), i)
if err != nil {
return cid.Undef, aerrors.Escalate(err, "putting cid")
}
return c, nil
}
func (s *storage) Get(c cid.Cid, out interface{}) aerrors.ActorError {
return aerrors.Escalate(s.cst.Get(context.TODO(), c, out), "getting cid")
func (vmc *VMContext) Get(c cid.Cid, out interface{}) aerrors.ActorError {
if err := vmc.ChargeGas(gasGetObj); err != nil {
return aerrors.Wrap(err, "out of gas")
}
return aerrors.Escalate(vmc.cst.Get(context.TODO(), c, out), "getting cid")
}
func (s *storage) GetHead() cid.Cid {
return s.head
func (vmc *VMContext) GetHead() cid.Cid {
return vmc.sroot
}
func (s *storage) Commit(oldh, newh cid.Cid) aerrors.ActorError {
if s.head != oldh {
func (vmc *VMContext) Commit(oldh, newh cid.Cid) aerrors.ActorError {
if err := vmc.ChargeGas(gasCommit); err != nil {
return aerrors.Wrap(err, "out of gas")
}
if vmc.sroot != oldh {
return aerrors.New(1, "failed to update, inconsistent base reference")
}
s.head = newh
vmc.sroot = newh
return nil
}
// End of storage interface
// Storage provides access to the VM storage layer
func (vmc *VMContext) Storage() types.Storage {
return vmc.storage
return vmc
}
func (vmc *VMContext) Ipld() *hamt.CborIpldStore {
@ -204,10 +211,6 @@ func (vm *VM) makeVMContext(ctx context.Context, sroot cid.Cid, msg *types.Messa
origin: origin,
height: vm.blockHeight,
cst: vm.cst,
storage: &storage{
cst: vm.cst,
head: sroot,
},
gasUsed: usedGas,
gasAvailable: msg.GasLimit,