Merge pull request #154 from filecoin-project/feat/gas2
Introduce gas tracking in harness
This commit is contained in:
commit
b4e25701af
@ -22,6 +22,10 @@ var log = logging.Logger("actors")
|
|||||||
|
|
||||||
var EmptyCBOR cid.Cid
|
var EmptyCBOR cid.Cid
|
||||||
|
|
||||||
|
const (
|
||||||
|
GasCreateActor = 100
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cbor.RegisterCborType(ExecParams{})
|
cbor.RegisterCborType(ExecParams{})
|
||||||
cbor.RegisterCborType(struct{}{})
|
cbor.RegisterCborType(struct{}{})
|
||||||
@ -82,6 +86,10 @@ func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := vmctx.ChargeGas(GasCreateActor); err != nil {
|
||||||
|
return nil, aerrors.Wrap(err, "run out of gas")
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure that only the actors defined in the spec can be launched.
|
// Make sure that only the actors defined in the spec can be launched.
|
||||||
if !IsBuiltinActor(p.Code) {
|
if !IsBuiltinActor(p.Code) {
|
||||||
return nil, aerrors.New(1,
|
return nil, aerrors.New(1,
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
package actors_test
|
package actors_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"go.opencensus.io/trace"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
"github.com/filecoin-project/go-lotus/chain/vm"
|
"github.com/filecoin-project/go-lotus/chain/vm"
|
||||||
"github.com/filecoin-project/go-lotus/tracing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMultiSigCreate(t *testing.T) {
|
func TestMultiSigCreate(t *testing.T) {
|
||||||
@ -44,15 +41,9 @@ func ApplyOK(t testing.TB, ret *vm.ApplyRet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMultiSigOps(t *testing.T) {
|
func TestMultiSigOps(t *testing.T) {
|
||||||
je := tracing.SetupJaegerTracing("test")
|
|
||||||
defer je.Flush()
|
|
||||||
ctx, span := trace.StartSpan(context.Background(), "/test-"+t.Name())
|
|
||||||
defer span.End()
|
|
||||||
|
|
||||||
var creatorAddr, sig1Addr, sig2Addr, outsideAddr address.Address
|
var creatorAddr, sig1Addr, sig2Addr, outsideAddr address.Address
|
||||||
var multSigAddr address.Address
|
var multSigAddr address.Address
|
||||||
opts := []HarnessOpt{
|
opts := []HarnessOpt{
|
||||||
HarnessCtx(ctx),
|
|
||||||
HarnessAddr(&creatorAddr, 100000),
|
HarnessAddr(&creatorAddr, 100000),
|
||||||
HarnessAddr(&sig1Addr, 100000),
|
HarnessAddr(&sig1Addr, 100000),
|
||||||
HarnessAddr(&sig2Addr, 100000),
|
HarnessAddr(&sig2Addr, 100000),
|
||||||
@ -66,25 +57,24 @@ func TestMultiSigOps(t *testing.T) {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
curVal := types.NewInt(2000)
|
|
||||||
h := NewHarness2(t, opts...)
|
h := NewHarness2(t, opts...)
|
||||||
{
|
{
|
||||||
|
const chargeVal = 2000
|
||||||
// Send funds into the multisig
|
// Send funds into the multisig
|
||||||
ret, state := h.SendFunds(t, creatorAddr, multSigAddr, curVal)
|
ret, _ := h.SendFunds(t, creatorAddr, multSigAddr, types.NewInt(chargeVal))
|
||||||
ApplyOK(t, ret)
|
ApplyOK(t, ret)
|
||||||
ms, err := state.GetActor(multSigAddr)
|
h.AssertBalanceChange(t, creatorAddr, -chargeVal)
|
||||||
assert.NoError(t, err)
|
h.AssertBalanceChange(t, multSigAddr, chargeVal)
|
||||||
assert.Equal(t, curVal, ms.Balance)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// Transfer funds outside of multsig
|
// Transfer funds outside of multsig
|
||||||
sendVal := types.NewInt(1000)
|
const sendVal = 1000
|
||||||
ret, _ := h.Invoke(t, creatorAddr, multSigAddr, actors.MultiSigMethods.Propose,
|
ret, _ := h.Invoke(t, creatorAddr, multSigAddr, actors.MultiSigMethods.Propose,
|
||||||
|
|
||||||
actors.MultiSigProposeParams{
|
actors.MultiSigProposeParams{
|
||||||
To: outsideAddr,
|
To: outsideAddr,
|
||||||
Value: sendVal,
|
Value: types.NewInt(sendVal),
|
||||||
})
|
})
|
||||||
ApplyOK(t, ret)
|
ApplyOK(t, ret)
|
||||||
var txIDParam actors.MultiSigTxID
|
var txIDParam actors.MultiSigTxID
|
||||||
@ -94,19 +84,14 @@ func TestMultiSigOps(t *testing.T) {
|
|||||||
ret, _ = h.Invoke(t, outsideAddr, multSigAddr, actors.MultiSigMethods.Approve,
|
ret, _ = h.Invoke(t, outsideAddr, multSigAddr, actors.MultiSigMethods.Approve,
|
||||||
txIDParam)
|
txIDParam)
|
||||||
assert.Equal(t, uint8(1), ret.ExitCode, "outsideAddr should not approve")
|
assert.Equal(t, uint8(1), ret.ExitCode, "outsideAddr should not approve")
|
||||||
|
h.AssertBalanceChange(t, multSigAddr, 0)
|
||||||
|
|
||||||
ret2, state := h.Invoke(t, sig1Addr, multSigAddr, actors.MultiSigMethods.Approve,
|
ret2, _ := h.Invoke(t, sig1Addr, multSigAddr, actors.MultiSigMethods.Approve,
|
||||||
txIDParam)
|
txIDParam)
|
||||||
ApplyOK(t, ret2)
|
ApplyOK(t, ret2)
|
||||||
curVal = types.BigSub(curVal, sendVal)
|
|
||||||
|
|
||||||
outAct, err := state.GetActor(outsideAddr)
|
h.AssertBalanceChange(t, outsideAddr, sendVal)
|
||||||
assert.NoError(t, err)
|
h.AssertBalanceChange(t, multSigAddr, -sendVal)
|
||||||
assert.Equal(t, types.NewInt(uint64(1000+1000-ret.GasUsed.Int64())), outAct.Balance)
|
|
||||||
|
|
||||||
msAct, err := state.GetActor(multSigAddr)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, curVal, msAct.Balance)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,6 @@ func TestPaychUpdate(t *testing.T) {
|
|||||||
ret, _ = h.Invoke(t, targetAddr, pch, actors.PCAMethods.Collect, struct{}{})
|
ret, _ = h.Invoke(t, targetAddr, pch, actors.PCAMethods.Collect, struct{}{})
|
||||||
ApplyOK(t, ret)
|
ApplyOK(t, ret)
|
||||||
|
|
||||||
h.AssertBalance(t, targetAddr, 10100-2*10 /*gas cost*/)
|
h.AssertBalanceChange(t, targetAddr, 100)
|
||||||
h.AssertBalance(t, creatorAddr, 9900-10)
|
h.AssertBalanceChange(t, creatorAddr, -100)
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ func TestStorageMarketCreateMiner(t *testing.T) {
|
|||||||
From: h.From,
|
From: h.From,
|
||||||
Method: SMAMethods.CreateStorageMiner,
|
Method: SMAMethods.CreateStorageMiner,
|
||||||
GasPrice: types.NewInt(1),
|
GasPrice: types.NewInt(1),
|
||||||
GasLimit: types.NewInt(1),
|
GasLimit: types.NewInt(1000),
|
||||||
Value: types.NewInt(0),
|
Value: types.NewInt(0),
|
||||||
Params: h.DumpObject(&CreateStorageMinerParams{
|
Params: h.DumpObject(&CreateStorageMinerParams{
|
||||||
Owner: h.From,
|
Owner: h.From,
|
||||||
|
@ -81,7 +81,7 @@ func TestVMInvokeMethod(t *testing.T) {
|
|||||||
Method: IAMethods.Exec,
|
Method: IAMethods.Exec,
|
||||||
Params: enc,
|
Params: enc,
|
||||||
GasPrice: types.NewInt(1),
|
GasPrice: types.NewInt(1),
|
||||||
GasLimit: types.NewInt(1),
|
GasLimit: types.NewInt(1000),
|
||||||
Value: types.NewInt(0),
|
Value: types.NewInt(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ func TestStorageMarketActorCreateMiner(t *testing.T) {
|
|||||||
Method: SMAMethods.CreateStorageMiner,
|
Method: SMAMethods.CreateStorageMiner,
|
||||||
Params: enc,
|
Params: enc,
|
||||||
GasPrice: types.NewInt(1),
|
GasPrice: types.NewInt(1),
|
||||||
GasLimit: types.NewInt(1),
|
GasLimit: types.NewInt(1000),
|
||||||
Value: types.NewInt(0),
|
Value: types.NewInt(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +40,12 @@ const (
|
|||||||
type HarnessOpt func(testing.TB, *Harness2) error
|
type HarnessOpt func(testing.TB, *Harness2) error
|
||||||
|
|
||||||
type Harness2 struct {
|
type Harness2 struct {
|
||||||
HI HarnessInit
|
HI HarnessInit
|
||||||
Stage HarnessStage
|
Stage HarnessStage
|
||||||
Nonces map[address.Address]uint64
|
Nonces map[address.Address]uint64
|
||||||
|
GasCharges map[address.Address]types.BigInt
|
||||||
|
|
||||||
|
lastBalanceCheck map[address.Address]types.BigInt
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
bs blockstore.Blockstore
|
bs blockstore.Blockstore
|
||||||
@ -130,10 +133,12 @@ func NewHarness2(t *testing.T, options ...HarnessOpt) *Harness2 {
|
|||||||
blsaddr(0): HarnessMinerFunds,
|
blsaddr(0): HarnessMinerFunds,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
GasCharges: make(map[address.Address]types.BigInt),
|
||||||
|
|
||||||
w: w,
|
lastBalanceCheck: make(map[address.Address]types.BigInt),
|
||||||
ctx: context.Background(),
|
w: w,
|
||||||
bs: bstore.NewBlockstore(dstore.NewMapDatastore()),
|
ctx: context.Background(),
|
||||||
|
bs: bstore.NewBlockstore(dstore.NewMapDatastore()),
|
||||||
}
|
}
|
||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
err := opt(t, h)
|
err := opt(t, h)
|
||||||
@ -178,6 +183,15 @@ func (h *Harness2) Apply(t testing.TB, msg types.Message) (*vm.ApplyRet, *state.
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Applying message: %+v", err)
|
t.Fatalf("Applying message: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ret != nil {
|
||||||
|
if prev, ok := h.GasCharges[msg.From]; ok {
|
||||||
|
h.GasCharges[msg.From] = types.BigAdd(prev, ret.GasUsed)
|
||||||
|
} else {
|
||||||
|
h.GasCharges[msg.From] = ret.GasUsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stateroot, err := h.vm.Flush(context.TODO())
|
stateroot, err := h.vm.Flush(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Flushing VM: %+v", err)
|
t.Fatalf("Flushing VM: %+v", err)
|
||||||
@ -249,6 +263,40 @@ func (h *Harness2) AssertBalance(t testing.TB, addr address.Address, amt uint64)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Harness2) AssertBalanceChange(t testing.TB, addr address.Address, amt int64) {
|
||||||
|
t.Helper()
|
||||||
|
lastBalance, ok := h.lastBalanceCheck[addr]
|
||||||
|
if !ok {
|
||||||
|
lastBalance, ok = h.HI.Addrs[addr]
|
||||||
|
if !ok {
|
||||||
|
lastBalance = types.NewInt(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var expected types.BigInt
|
||||||
|
|
||||||
|
if amt >= 0 {
|
||||||
|
expected = types.BigAdd(lastBalance, types.NewInt(uint64(amt)))
|
||||||
|
} else {
|
||||||
|
expected = types.BigSub(lastBalance, types.NewInt(uint64(-amt)))
|
||||||
|
}
|
||||||
|
|
||||||
|
h.lastBalanceCheck[addr] = expected
|
||||||
|
|
||||||
|
if gasUsed, ok := h.GasCharges[addr]; ok {
|
||||||
|
expected = types.BigSub(expected, gasUsed)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := h.vm.ActorBalance(addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if types.BigCmp(expected, b) != 0 {
|
||||||
|
t.Errorf("expected %s to have balanced of %d. Instead has %s", addr, amt, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func DumpObject(t testing.TB, obj interface{}) []byte {
|
func DumpObject(t testing.TB, obj interface{}) []byte {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
enc, err := cbor.DumpObject(obj)
|
enc, err := cbor.DumpObject(obj)
|
||||||
|
@ -127,7 +127,7 @@ func TestVMInvokeHarness(t *testing.T) {
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
GasPrice: types.NewInt(1),
|
GasPrice: types.NewInt(1),
|
||||||
GasLimit: types.NewInt(1),
|
GasLimit: types.NewInt(1000),
|
||||||
Value: types.NewInt(0),
|
Value: types.NewInt(0),
|
||||||
},
|
},
|
||||||
Ret: func(t *testing.T, ret *types.MessageReceipt) {
|
Ret: func(t *testing.T, ret *types.MessageReceipt) {
|
||||||
|
@ -150,7 +150,13 @@ func (vmc *VMContext) StateTree() (types.StateTree, aerrors.ActorError) {
|
|||||||
return vmc.state, nil
|
return vmc.state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GasVerifySignature = 50
|
||||||
|
|
||||||
func (vmctx *VMContext) VerifySignature(sig *types.Signature, act address.Address, data []byte) aerrors.ActorError {
|
func (vmctx *VMContext) VerifySignature(sig *types.Signature, act address.Address, data []byte) aerrors.ActorError {
|
||||||
|
if err := vmctx.ChargeGas(GasVerifySignature); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if act.Protocol() == address.ID {
|
if act.Protocol() == address.ID {
|
||||||
kaddr, err := vmctx.resolveToKeyAddr(act)
|
kaddr, err := vmctx.resolveToKeyAddr(act)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user