Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make virtual gas real #2343

Merged
merged 7 commits into from
Jul 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/params_shared_vals.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ const VerifSigCacheSize = 32000

// TODO: If this is gonna stay, it should move to specs-actors
const BlockMessageLimit = 512
const BlockGasLimit = 100_000_000_000
const BlockGasLimit = 7_500_000_000

var DrandConfig = dtypes.DrandConfig{
Servers: []string{
Expand Down
2 changes: 1 addition & 1 deletion chain/gen/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ func getRandomMessages(cg *ChainGen) ([]*types.SignedMessage, error) {

Method: 0,

GasLimit: 10000,
GasLimit: 100_000_000,
GasPrice: types.NewInt(0),
}

Expand Down
2 changes: 1 addition & 1 deletion chain/market/fundmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (fm *FundMgr) EnsureAvailable(ctx context.Context, addr, wallet address.Add
From: wallet,
Value: toAdd,
GasPrice: types.NewInt(0),
GasLimit: 1000000,
GasLimit: 100_000_000,
Method: builtin.MethodsMarket.AddBalance,
Params: params,
})
Expand Down
4 changes: 2 additions & 2 deletions chain/stmgr/forks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func TestForkHeightTriggers(t *testing.T) {
To: builtin.InitActorAddr,
Method: builtin.MethodsInit.Exec,
Params: enc,
GasLimit: 10000,
GasLimit: 100_000_000,
GasPrice: types.NewInt(0),
}
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
Expand All @@ -206,7 +206,7 @@ func TestForkHeightTriggers(t *testing.T) {
Method: 2,
Params: nil,
Nonce: nonce,
GasLimit: 10000,
GasLimit: 100_000_000,
GasPrice: types.NewInt(0),
}
nonce++
Expand Down
2 changes: 1 addition & 1 deletion chain/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestSignedMessageJsonRoundtrip(t *testing.T) {
Method: 1235126,
Value: types.NewInt(123123),
GasPrice: types.NewInt(1234),
GasLimit: 9992969384,
GasLimit: 100_000_000,
Nonce: 123123,
},
}
Expand Down
61 changes: 33 additions & 28 deletions chain/vm/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type Pricelist interface {
OnMethodInvocation(value abi.TokenAmount, methodNum abi.MethodNum) GasCharge

// OnIpldGet returns the gas used for storing an object
OnIpldGet(dataSize int) GasCharge
OnIpldGet() GasCharge
// OnIpldPut returns the gas used for storing an object
OnIpldPut(dataSize int) GasCharge

Expand All @@ -84,30 +84,35 @@ type Pricelist interface {

var prices = map[abi.ChainEpoch]Pricelist{
abi.ChainEpoch(0): &pricelistV0{
onChainMessageBase: 0,
onChainMessagePerByte: 2,
onChainReturnValuePerByte: 8,
sendBase: 5,
sendTransferFunds: 5,
sendInvokeMethod: 10,
ipldGetBase: 10,
ipldGetPerByte: 1,
ipldPutBase: 20,
ipldPutPerByte: 2,
createActorBase: 40, // IPLD put + 20
createActorExtra: 500,
deleteActor: -500, // -createActorExtra
// Dragons: this cost is not persistable, create a LinearCost{a,b} struct that has a `.Cost(x) -> ax + b`
verifySignature: map[crypto.SigType]func(int64) int64{
crypto.SigTypeBLS: func(x int64) int64 { return 3*x + 2 },
crypto.SigTypeSecp256k1: func(x int64) int64 { return 3*x + 2 },
onChainMessageComputeBase: 137137,
onChainMessageStorageBase: 0, // TODO gas
onChainMessageStoragePerByte: 2, // TODO gas

onChainReturnValuePerByte: 8, // TODO gas

sendBase: 97236,
sendTransferFunds: 96812,
sendTransferOnlyPremium: 347806,
sendInvokeMethod: -3110,

ipldGetBase: 417230,
ipldPutBase: 396100,
ipldPutPerByte: 2, // TODO gas

createActorCompute: 750011,
createActorStorage: 500, // TODO gas
deleteActor: -500, // -createActorStorage

verifySignature: map[crypto.SigType]int64{
crypto.SigTypeBLS: 219946580,
crypto.SigTypeSecp256k1: 6726720,
},
hashingBase: 5,
hashingPerByte: 2,
computeUnsealedSectorCidBase: 100,
verifySealBase: 2000,
verifyPostBase: 700,
verifyConsensusFault: 10,

hashingBase: 110685,
computeUnsealedSectorCidBase: 431890,
verifySealBase: 2000, // TODO gas , it VerifySeal syscall is not used
verifyPostBase: 2621447835,
verifyConsensusFault: 495422,
},
}

Expand Down Expand Up @@ -198,14 +203,14 @@ func (ps pricedSyscalls) VerifyConsensusFault(h1 []byte, h2 []byte, extra []byte
}

func (ps pricedSyscalls) BatchVerifySeals(inp map[address.Address][]abi.SealVerifyInfo) (map[address.Address][]bool, error) {
var gasChargeSum GasCharge
gasChargeSum.Name = "BatchVerifySeals"
count := int64(0)
for _, svis := range inp {
count += int64(len(svis))
}
gasChargeSum = gasChargeSum.WithExtra(count).WithVirtual(129778623*count+716683250, 0)
ps.chargeGas(gasChargeSum) // TODO: this is only called by the cron actor. Should we even charge gas?

gasChargeSum := newGasCharge("BatchVerifySeals", 0, 0)
gasChargeSum = gasChargeSum.WithExtra(count).WithVirtual(15075005*count+899741502, 0)
ps.chargeGas(gasChargeSum) // real gas charged by actors
defer ps.chargeGas(gasOnActorExec)

return ps.under.BatchVerifySeals(inp)
Expand Down
80 changes: 34 additions & 46 deletions chain/vm/gas_v0.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ type pricelistV0 struct {
// Together, these account for the cost of message propagation and validation,
// up to but excluding any actual processing by the VM.
// This is the cost a block producer burns when including an invalid message.
onChainMessageBase int64
onChainMessagePerByte int64
onChainMessageComputeBase int64
onChainMessageStorageBase int64
onChainMessageStoragePerByte int64

// Gas cost charged to the originator of a non-nil return value produced
// by an on-chain message is given by:
Expand All @@ -41,15 +42,17 @@ type pricelistV0 struct {
// already accounted for).
sendTransferFunds int64

// Gsa cost charged, in addition to SendBase, if message only transfers funds.
sendTransferOnlyPremium int64

// Gas cost charged, in addition to SendBase, if a message invokes
// a method on the receiver.
// Accounts for the cost of loading receiver code and method dispatch.
sendInvokeMethod int64

// Gas cost (Base + len*PerByte) for any Get operation to the IPLD store
// Gas cost for any Get operation to the IPLD store
// in the runtime VM context.
ipldGetBase int64
ipldGetPerByte int64
ipldGetBase int64

// Gas cost (Base + len*PerByte) for any Put operation to the IPLD store
// in the runtime VM context.
Expand All @@ -64,18 +67,17 @@ type pricelistV0 struct {
//
// Note: this costs assume that the extra will be partially or totally refunded while
// the base is covering for the put.
createActorBase int64
createActorExtra int64
createActorCompute int64
createActorStorage int64

// Gas cost for deleting an actor.
//
// Note: this partially refunds the create cost to incentivise the deletion of the actors.
deleteActor int64

verifySignature map[crypto.SigType]func(len int64) int64
verifySignature map[crypto.SigType]int64

hashingBase int64
hashingPerByte int64
hashingBase int64

computeUnsealedSectorCidBase int64
verifySealBase int64
Expand All @@ -87,57 +89,51 @@ var _ Pricelist = (*pricelistV0)(nil)

// OnChainMessage returns the gas used for storing a message of a given size in the chain.
func (pl *pricelistV0) OnChainMessage(msgSize int) GasCharge {
return newGasCharge("OnChainMessage", 0, pl.onChainMessageBase+pl.onChainMessagePerByte*int64(msgSize)).WithVirtual(77302, 0)
return newGasCharge("OnChainMessage", pl.onChainMessageComputeBase,
pl.onChainMessageStorageBase+pl.onChainMessageStoragePerByte*int64(msgSize))
}

// OnChainReturnValue returns the gas used for storing the response of a message in the chain.
func (pl *pricelistV0) OnChainReturnValue(dataSize int) GasCharge {
return newGasCharge("OnChainReturnValue", 0, int64(dataSize)*pl.onChainReturnValuePerByte).WithVirtual(107294, 0)
return newGasCharge("OnChainReturnValue", 0, int64(dataSize)*pl.onChainReturnValuePerByte)
}

// OnMethodInvocation returns the gas used when invoking a method.
func (pl *pricelistV0) OnMethodInvocation(value abi.TokenAmount, methodNum abi.MethodNum) GasCharge {
ret := pl.sendBase
extra := ""
virtGas := int64(1072944)

if value != abi.NewTokenAmount(0) {
// TODO: fix this, it is comparing pointers instead of values
// see vv
ret += pl.sendTransferFunds
}
if big.Cmp(value, abi.NewTokenAmount(0)) != 0 {
virtGas += 497495
ret += pl.sendTransferFunds
if methodNum == builtin.MethodSend {
// transfer only
virtGas += 973940
ret += pl.sendTransferOnlyPremium
}
extra += "t"
}

if methodNum != builtin.MethodSend {
ret += pl.sendInvokeMethod
extra += "i"
// running actors is cheaper becase we hand over to actors
virtGas += -295779
ret += pl.sendInvokeMethod
}
return newGasCharge("OnMethodInvocation", ret, 0).WithVirtual(virtGas, 0).WithExtra(extra)
return newGasCharge("OnMethodInvocation", ret, 0).WithExtra(extra)
}

// OnIpldGet returns the gas used for storing an object
func (pl *pricelistV0) OnIpldGet(dataSize int) GasCharge {
return newGasCharge("OnIpldGet", pl.ipldGetBase+int64(dataSize)*pl.ipldGetPerByte, 0).
WithExtra(dataSize).WithVirtual(433685, 0)
func (pl *pricelistV0) OnIpldGet() GasCharge {
return newGasCharge("OnIpldGet", pl.ipldGetBase, 0)
}

// OnIpldPut returns the gas used for storing an object
func (pl *pricelistV0) OnIpldPut(dataSize int) GasCharge {
return newGasCharge("OnIpldPut", pl.ipldPutBase, int64(dataSize)*pl.ipldPutPerByte).
WithExtra(dataSize).WithVirtual(88970, 0)
WithExtra(dataSize)
}

// OnCreateActor returns the gas used for creating an actor
func (pl *pricelistV0) OnCreateActor() GasCharge {
return newGasCharge("OnCreateActor", pl.createActorBase, pl.createActorExtra).WithVirtual(65636, 0)
return newGasCharge("OnCreateActor", pl.createActorCompute, pl.createActorStorage)
}

// OnDeleteActor returns the gas used for deleting an actor
Expand All @@ -148,50 +144,42 @@ func (pl *pricelistV0) OnDeleteActor() GasCharge {
// OnVerifySignature

func (pl *pricelistV0) OnVerifySignature(sigType crypto.SigType, planTextSize int) (GasCharge, error) {
costFn, ok := pl.verifySignature[sigType]
cost, ok := pl.verifySignature[sigType]
if !ok {
return GasCharge{}, fmt.Errorf("cost function for signature type %d not supported", sigType)
}
sigName, _ := sigType.Name()
virtGas := int64(0)
switch sigType {
case crypto.SigTypeBLS:
virtGas = 220138570
case crypto.SigTypeSecp256k1:
virtGas = 7053730
}

return newGasCharge("OnVerifySignature", costFn(int64(planTextSize)), 0).
sigName, _ := sigType.Name()
return newGasCharge("OnVerifySignature", cost, 0).
WithExtra(map[string]interface{}{
"type": sigName,
"size": planTextSize,
}).WithVirtual(virtGas, 0), nil
}), nil
}

// OnHashing
func (pl *pricelistV0) OnHashing(dataSize int) GasCharge {
return newGasCharge("OnHashing", pl.hashingBase+int64(dataSize)*pl.hashingPerByte, 0).WithExtra(dataSize).WithVirtual(77300, 0)
return newGasCharge("OnHashing", pl.hashingBase, 0).WithExtra(dataSize)
}

// OnComputeUnsealedSectorCid
func (pl *pricelistV0) OnComputeUnsealedSectorCid(proofType abi.RegisteredSealProof, pieces []abi.PieceInfo) GasCharge {
// TODO: this needs more cost tunning, check with @lotus
return newGasCharge("OnComputeUnsealedSectorCid", pl.computeUnsealedSectorCidBase, 0).WithVirtual(382370, 0)
return newGasCharge("OnComputeUnsealedSectorCid", pl.computeUnsealedSectorCidBase, 0)
}

// OnVerifySeal
func (pl *pricelistV0) OnVerifySeal(info abi.SealVerifyInfo) GasCharge {
// TODO: this needs more cost tunning, check with @lotus
return newGasCharge("OnVerifySeal", pl.verifySealBase, 0).WithVirtual(199954003, 0)
// this is not used
return newGasCharge("OnVerifySeal", pl.verifySealBase, 0)
}

// OnVerifyPost
func (pl *pricelistV0) OnVerifyPost(info abi.WindowPoStVerifyInfo) GasCharge {
// TODO: this needs more cost tunning, check with @lotus
return newGasCharge("OnVerifyPost", pl.verifyPostBase, 0).WithVirtual(2629471704, 0).WithExtra(len(info.ChallengedSectors))
return newGasCharge("OnVerifyPost", pl.verifyPostBase, 0).WithExtra(len(info.ChallengedSectors))
}

// OnVerifyConsensusFault
func (pl *pricelistV0) OnVerifyConsensusFault() GasCharge {
return newGasCharge("OnVerifyConsensusFault", pl.verifyConsensusFault, 0).WithVirtual(551935, 0)
return newGasCharge("OnVerifyConsensusFault", pl.verifyConsensusFault, 0)
}
8 changes: 4 additions & 4 deletions chain/vm/mkactor.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ var EmptyObjectCid cid.Cid

// TryCreateAccountActor creates account actors from only BLS/SECP256K1 addresses.
func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, aerrors.ActorError) {
if err := rt.chargeGasSafe(PricelistByEpoch(rt.height).OnCreateActor()); err != nil {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reorg is safe because the only way we would end up a different amount of gas is if something failed, and then we would end up charging all the gas.

return nil, err
}

addrID, err := rt.state.RegisterNewAddress(addr)
if err != nil {
return nil, aerrors.Escalate(err, "registering actor address")
Expand All @@ -50,10 +54,6 @@ func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, aer
}
// call constructor on account

if err := rt.chargeGasSafe(PricelistByEpoch(rt.height).OnCreateActor()); err != nil {
return nil, err
}

_, aerr = rt.internalSend(builtin.SystemActorAddr, addrID, builtin.MethodsAccount.Constructor, big.Zero(), p)
if aerr != nil {
return nil, aerrors.Wrap(aerr, "failed to invoke account constructor")
Expand Down
Loading