VM: Refactor pricelist to be based on network versions
This commit is contained in:
parent
11db419735
commit
25b2e144b8
@ -467,7 +467,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
nv := filec.sm.GetNetworkVersion(ctx, b.Header.Height)
|
nv := filec.sm.GetNetworkVersion(ctx, b.Header.Height)
|
||||||
pl := vm.PricelistByEpoch(b.Header.Height)
|
pl := vm.PricelistByEpochAndNetworkVersion(b.Header.Height, nv)
|
||||||
var sumGasLimit int64
|
var sumGasLimit int64
|
||||||
checkMsg := func(msg types.ChainMsg) error {
|
checkMsg := func(msg types.ChainMsg) error {
|
||||||
m := msg.VMMessage()
|
m := msg.VMMessage()
|
||||||
|
@ -281,12 +281,11 @@ func (mp *MessagePool) checkMessages(ctx context.Context, msgs []*types.Message,
|
|||||||
// gas checks
|
// gas checks
|
||||||
|
|
||||||
// 4. Min Gas
|
// 4. Min Gas
|
||||||
minGas := vm.PricelistByEpoch(epoch).OnChainMessage(m.ChainLength())
|
minGas := vm.PricelistByEpochAndNetworkVersion(epoch, nv).OnChainMessage(m.ChainLength())
|
||||||
|
|
||||||
check = api.MessageCheckStatus{
|
check = api.MessageCheckStatus{
|
||||||
Cid: m.Cid(),
|
Cid: m.Cid(),
|
||||||
CheckStatus: api.CheckStatus{
|
CheckStatus: api.CheckStatus{Code: api.CheckStatusMessageMinGas,
|
||||||
Code: api.CheckStatusMessageMinGas,
|
|
||||||
Hint: map[string]interface{}{
|
Hint: map[string]interface{}{
|
||||||
"minGas": minGas,
|
"minGas": minGas,
|
||||||
},
|
},
|
||||||
|
@ -629,7 +629,11 @@ func (mp *MessagePool) addLocal(ctx context.Context, m *types.SignedMessage) err
|
|||||||
// a (soft) validation error.
|
// a (soft) validation error.
|
||||||
func (mp *MessagePool) verifyMsgBeforeAdd(m *types.SignedMessage, curTs *types.TipSet, local bool) (bool, error) {
|
func (mp *MessagePool) verifyMsgBeforeAdd(m *types.SignedMessage, curTs *types.TipSet, local bool) (bool, error) {
|
||||||
epoch := curTs.Height() + 1
|
epoch := curTs.Height() + 1
|
||||||
minGas := vm.PricelistByEpoch(epoch).OnChainMessage(m.ChainLength())
|
nv, err := mp.getNtwkVersion(epoch)
|
||||||
|
if err != nil {
|
||||||
|
return false, xerrors.Errorf("getting network version: %w", err)
|
||||||
|
}
|
||||||
|
minGas := vm.PricelistByEpochAndNetworkVersion(epoch, nv).OnChainMessage(m.ChainLength())
|
||||||
|
|
||||||
if err := m.VMMessage().ValidForBlockInclusion(minGas.Total(), build.NewestNetworkVersion); err != nil {
|
if err := m.VMMessage().ValidForBlockInclusion(minGas.Total(), build.NewestNetworkVersion); err != nil {
|
||||||
return false, xerrors.Errorf("message will not be included in a block: %w", err)
|
return false, xerrors.Errorf("message will not be included in a block: %w", err)
|
||||||
|
@ -781,6 +781,7 @@ func (mp *MessagePool) createMessageChains(actor address.Address, mset map[uint6
|
|||||||
// cannot exceed the block limit; drop all messages that exceed the limit
|
// cannot exceed the block limit; drop all messages that exceed the limit
|
||||||
// - the total gasReward cannot exceed the actor's balance; drop all messages that exceed
|
// - the total gasReward cannot exceed the actor's balance; drop all messages that exceed
|
||||||
// the balance
|
// the balance
|
||||||
|
|
||||||
a, err := mp.api.GetActorAfter(actor, ts)
|
a, err := mp.api.GetActorAfter(actor, ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to load actor state, not building chain for %s: %v", actor, err)
|
log.Errorf("failed to load actor state, not building chain for %s: %v", actor, err)
|
||||||
@ -793,6 +794,12 @@ func (mp *MessagePool) createMessageChains(actor address.Address, mset map[uint6
|
|||||||
skip := 0
|
skip := 0
|
||||||
i := 0
|
i := 0
|
||||||
rewards := make([]*big.Int, 0, len(msgs))
|
rewards := make([]*big.Int, 0, len(msgs))
|
||||||
|
|
||||||
|
nv, err := mp.getNtwkVersion(ts.Height())
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("getting network version: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
for i = 0; i < len(msgs); i++ {
|
for i = 0; i < len(msgs); i++ {
|
||||||
m := msgs[i]
|
m := msgs[i]
|
||||||
|
|
||||||
@ -808,7 +815,7 @@ func (mp *MessagePool) createMessageChains(actor address.Address, mset map[uint6
|
|||||||
}
|
}
|
||||||
curNonce++
|
curNonce++
|
||||||
|
|
||||||
minGas := vm.PricelistByEpoch(ts.Height()).OnChainMessage(m.ChainLength()).Total()
|
minGas := vm.PricelistByEpochAndNetworkVersion(ts.Height(), nv).OnChainMessage(m.ChainLength()).Total()
|
||||||
if m.Message.GasLimit < minGas {
|
if m.Message.GasLimit < minGas {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ type FvmExtern struct {
|
|||||||
Rand
|
Rand
|
||||||
blockstore.Blockstore
|
blockstore.Blockstore
|
||||||
epoch abi.ChainEpoch
|
epoch abi.ChainEpoch
|
||||||
|
nv network.Version
|
||||||
lbState LookbackStateGetter
|
lbState LookbackStateGetter
|
||||||
base cid.Cid
|
base cid.Cid
|
||||||
}
|
}
|
||||||
@ -175,7 +176,7 @@ func (x *FvmExtern) workerKeyAtLookback(ctx context.Context, minerId address.Add
|
|||||||
}
|
}
|
||||||
|
|
||||||
cstWithoutGas := cbor.NewCborStore(x.Blockstore)
|
cstWithoutGas := cbor.NewCborStore(x.Blockstore)
|
||||||
cbb := &gasChargingBlocks{gasAdder, PricelistByEpoch(x.epoch), x.Blockstore}
|
cbb := &gasChargingBlocks{gasAdder, PricelistByEpochAndNetworkVersion(x.epoch, x.nv), x.Blockstore}
|
||||||
cstWithGas := cbor.NewCborStore(cbb)
|
cstWithGas := cbor.NewCborStore(cbb)
|
||||||
|
|
||||||
lbState, err := x.lbState(ctx, height)
|
lbState, err := x.lbState(ctx, height)
|
||||||
@ -234,7 +235,7 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fvm, err := ffi.CreateFVM(0,
|
fvm, err := ffi.CreateFVM(0,
|
||||||
&FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore, lbState: opts.LookbackState, base: opts.StateBase, epoch: opts.Epoch},
|
&FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore, lbState: opts.LookbackState, base: opts.StateBase, epoch: opts.Epoch, nv: opts.NetworkVersion},
|
||||||
opts.Epoch, opts.BaseFee, circToReport, opts.NetworkVersion, opts.StateBase,
|
opts.Epoch, opts.BaseFee, circToReport, opts.NetworkVersion, opts.StateBase,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3,6 +3,8 @@ package vm
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
|
|
||||||
vmr "github.com/filecoin-project/specs-actors/v7/actors/runtime"
|
vmr "github.com/filecoin-project/specs-actors/v7/actors/runtime"
|
||||||
proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof"
|
proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof"
|
||||||
|
|
||||||
@ -82,10 +84,7 @@ type Pricelist interface {
|
|||||||
OnVerifyConsensusFault() GasCharge
|
OnVerifyConsensusFault() GasCharge
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prices are the price lists per starting epoch. Public for testing purposes
|
var priceListGenesis = pricelistV0{
|
||||||
// (concretely to allow the test vector runner to rebase prices).
|
|
||||||
var Prices = map[abi.ChainEpoch]Pricelist{
|
|
||||||
abi.ChainEpoch(0): &pricelistV0{
|
|
||||||
computeGasMulti: 1,
|
computeGasMulti: 1,
|
||||||
storageGasMulti: 1000,
|
storageGasMulti: 1000,
|
||||||
|
|
||||||
@ -133,8 +132,9 @@ var Prices = map[abi.ChainEpoch]Pricelist{
|
|||||||
},
|
},
|
||||||
verifyPostDiscount: true,
|
verifyPostDiscount: true,
|
||||||
verifyConsensusFault: 495422,
|
verifyConsensusFault: 495422,
|
||||||
},
|
}
|
||||||
abi.ChainEpoch(build.UpgradeCalicoHeight): &pricelistV0{
|
|
||||||
|
var priceListCalico = pricelistV0{
|
||||||
computeGasMulti: 1,
|
computeGasMulti: 1,
|
||||||
storageGasMulti: 1300,
|
storageGasMulti: 1300,
|
||||||
|
|
||||||
@ -211,16 +211,26 @@ var Prices = map[abi.ChainEpoch]Pricelist{
|
|||||||
verifyConsensusFault: 495422,
|
verifyConsensusFault: 495422,
|
||||||
|
|
||||||
verifyReplicaUpdate: 36316136,
|
verifyReplicaUpdate: 36316136,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PricelistByEpoch finds the latest prices for the given epoch
|
// Prices are the price lists per starting epoch.
|
||||||
func PricelistByEpoch(epoch abi.ChainEpoch) Pricelist {
|
// For network v8 and onwards, this is disregarded; the pricelist is selected by network version.
|
||||||
|
var pricesByEpoch = map[abi.ChainEpoch]Pricelist{
|
||||||
|
abi.ChainEpoch(0): &priceListGenesis,
|
||||||
|
abi.ChainEpoch(build.UpgradeCalicoHeight): &priceListCalico,
|
||||||
|
}
|
||||||
|
|
||||||
|
// PricelistByEpochAndNetworkVersion finds the latest prices for the given epoch
|
||||||
|
func PricelistByEpochAndNetworkVersion(epoch abi.ChainEpoch, nv network.Version) Pricelist {
|
||||||
|
if nv >= network.Version8 {
|
||||||
|
return &priceListCalico
|
||||||
|
}
|
||||||
|
|
||||||
// since we are storing the prices as map or epoch to price
|
// since we are storing the prices as map or epoch to price
|
||||||
// we need to get the price with the highest epoch that is lower or equal to the `epoch` arg
|
// we need to get the price with the highest epoch that is lower or equal to the `epoch` arg
|
||||||
bestEpoch := abi.ChainEpoch(0)
|
bestEpoch := abi.ChainEpoch(0)
|
||||||
bestPrice := Prices[bestEpoch]
|
bestPrice := pricesByEpoch[bestEpoch]
|
||||||
for e, pl := range Prices {
|
for e, pl := range pricesByEpoch {
|
||||||
// if `e` happened after `bestEpoch` and `e` is earlier or equal to the target `epoch`
|
// if `e` happened after `bestEpoch` and `e` is earlier or equal to the target `epoch`
|
||||||
if e > bestEpoch && e <= epoch {
|
if e > bestEpoch && e <= epoch {
|
||||||
bestEpoch = e
|
bestEpoch = e
|
||||||
|
@ -51,7 +51,7 @@ var EmptyObjectCid cid.Cid
|
|||||||
|
|
||||||
// TryCreateAccountActor creates account actors from only BLS/SECP256K1 addresses.
|
// TryCreateAccountActor creates account actors from only BLS/SECP256K1 addresses.
|
||||||
func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, address.Address, aerrors.ActorError) {
|
func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, address.Address, aerrors.ActorError) {
|
||||||
if err := rt.chargeGasSafe(PricelistByEpoch(rt.height).OnCreateActor()); err != nil {
|
if err := rt.chargeGasSafe(PricelistByEpochAndNetworkVersion(rt.height, rt.NetworkVersion()).OnCreateActor()); err != nil {
|
||||||
return nil, address.Undef, err
|
return nil, address.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ func (vm *LegacyVM) makeRuntime(ctx context.Context, msg *types.Message, parent
|
|||||||
gasAvailable: msg.GasLimit,
|
gasAvailable: msg.GasLimit,
|
||||||
depth: 0,
|
depth: 0,
|
||||||
numActorsCreated: 0,
|
numActorsCreated: 0,
|
||||||
pricelist: PricelistByEpoch(vm.blockHeight),
|
pricelist: PricelistByEpochAndNetworkVersion(vm.blockHeight, vm.networkVersion),
|
||||||
allowInternal: true,
|
allowInternal: true,
|
||||||
callerValidated: false,
|
callerValidated: false,
|
||||||
executionTrace: types.ExecutionTrace{Msg: msg},
|
executionTrace: types.ExecutionTrace{Msg: msg},
|
||||||
@ -431,7 +431,7 @@ func (vm *LegacyVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*App
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pl := PricelistByEpoch(vm.blockHeight)
|
pl := PricelistByEpochAndNetworkVersion(vm.blockHeight, vm.networkVersion)
|
||||||
|
|
||||||
msgGas := pl.OnChainMessage(cmsg.ChainLength())
|
msgGas := pl.OnChainMessage(cmsg.ChainLength())
|
||||||
msgGasCost := msgGas.Total()
|
msgGasCost := msgGas.Total()
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -29,7 +28,6 @@ import (
|
|||||||
"github.com/filecoin-project/test-vectors/schema"
|
"github.com/filecoin-project/test-vectors/schema"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/blockstore"
|
"github.com/filecoin-project/lotus/blockstore"
|
||||||
"github.com/filecoin-project/lotus/chain/consensus/filcns"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/vm"
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
)
|
)
|
||||||
@ -53,52 +51,6 @@ var TipsetVectorOpts struct {
|
|||||||
OnTipsetApplied []func(bs blockstore.Blockstore, params *ExecuteTipsetParams, res *ExecuteTipsetResult)
|
OnTipsetApplied []func(bs blockstore.Blockstore, params *ExecuteTipsetParams, res *ExecuteTipsetResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
type GasPricingRestoreFn func()
|
|
||||||
|
|
||||||
// adjustGasPricing adjusts the global gas price mapping to make sure that the
|
|
||||||
// gas pricelist for vector's network version is used at the vector's epoch.
|
|
||||||
// Because it manipulates a global, it returns a function that reverts the
|
|
||||||
// change. The caller MUST invoke this function or the test vector runner will
|
|
||||||
// become invalid.
|
|
||||||
func adjustGasPricing(vectorEpoch abi.ChainEpoch, vectorNv network.Version) GasPricingRestoreFn {
|
|
||||||
// Stash the current pricing mapping.
|
|
||||||
// Ok to take a reference instead of a copy, because we override the map
|
|
||||||
// with a new one below.
|
|
||||||
var old = vm.Prices
|
|
||||||
|
|
||||||
// Resolve the epoch at which the vector network version kicks in.
|
|
||||||
var epoch abi.ChainEpoch = math.MaxInt64
|
|
||||||
if vectorNv == network.Version0 {
|
|
||||||
// genesis is not an upgrade.
|
|
||||||
epoch = 0
|
|
||||||
} else {
|
|
||||||
for _, u := range filcns.DefaultUpgradeSchedule() {
|
|
||||||
if u.Network == vectorNv {
|
|
||||||
epoch = u.Height
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if epoch == math.MaxInt64 {
|
|
||||||
panic(fmt.Sprintf("could not resolve network version %d to height", vectorNv))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the right pricelist for this network version.
|
|
||||||
pricelist := vm.PricelistByEpoch(epoch)
|
|
||||||
|
|
||||||
// Override the pricing mapping by setting the relevant pricelist for the
|
|
||||||
// network version at the epoch where the vector runs.
|
|
||||||
vm.Prices = map[abi.ChainEpoch]vm.Pricelist{
|
|
||||||
vectorEpoch: pricelist,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a function to restore the original mapping.
|
|
||||||
return func() {
|
|
||||||
vm.Prices = old
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExecuteMessageVector executes a message-class test vector.
|
// ExecuteMessageVector executes a message-class test vector.
|
||||||
func ExecuteMessageVector(r Reporter, vector *schema.TestVector, variant *schema.Variant) (diffs []string, err error) {
|
func ExecuteMessageVector(r Reporter, vector *schema.TestVector, variant *schema.Variant) (diffs []string, err error) {
|
||||||
var (
|
var (
|
||||||
@ -117,10 +69,6 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector, variant *schema
|
|||||||
// Create a new Driver.
|
// Create a new Driver.
|
||||||
driver := NewDriver(ctx, vector.Selector, DriverOpts{DisableVMFlush: true})
|
driver := NewDriver(ctx, vector.Selector, DriverOpts{DisableVMFlush: true})
|
||||||
|
|
||||||
// Monkey patch the gas pricing.
|
|
||||||
revertFn := adjustGasPricing(baseEpoch, nv)
|
|
||||||
defer revertFn()
|
|
||||||
|
|
||||||
// Apply every message.
|
// Apply every message.
|
||||||
for i, m := range vector.ApplyMessages {
|
for i, m := range vector.ApplyMessages {
|
||||||
msg, err := types.DecodeMessage(m.Bytes)
|
msg, err := types.DecodeMessage(m.Bytes)
|
||||||
|
Loading…
Reference in New Issue
Block a user