diff --git a/chain/consensus/filcns/filecoin.go b/chain/consensus/filcns/filecoin.go index b364ece4f..3aa85c7c5 100644 --- a/chain/consensus/filcns/filecoin.go +++ b/chain/consensus/filcns/filecoin.go @@ -467,7 +467,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl } nv := filec.sm.GetNetworkVersion(ctx, b.Header.Height) - pl := vm.PricelistByEpochAndNetworkVersion(b.Header.Height, nv) + pl := vm.PricelistByEpoch(b.Header.Height) var sumGasLimit int64 checkMsg := func(msg types.ChainMsg) error { m := msg.VMMessage() diff --git a/chain/messagepool/check.go b/chain/messagepool/check.go index 7c7469f76..92cfb458a 100644 --- a/chain/messagepool/check.go +++ b/chain/messagepool/check.go @@ -281,11 +281,12 @@ func (mp *MessagePool) checkMessages(ctx context.Context, msgs []*types.Message, // gas checks // 4. Min Gas - minGas := vm.PricelistByEpochAndNetworkVersion(epoch, nv).OnChainMessage(m.ChainLength()) + minGas := vm.PricelistByEpoch(epoch).OnChainMessage(m.ChainLength()) check = api.MessageCheckStatus{ Cid: m.Cid(), - CheckStatus: api.CheckStatus{Code: api.CheckStatusMessageMinGas, + CheckStatus: api.CheckStatus{ + Code: api.CheckStatusMessageMinGas, Hint: map[string]interface{}{ "minGas": minGas, }, diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 0ff36512c..38c66c38d 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -629,11 +629,7 @@ func (mp *MessagePool) addLocal(ctx context.Context, m *types.SignedMessage) err // a (soft) validation error. func (mp *MessagePool) verifyMsgBeforeAdd(m *types.SignedMessage, curTs *types.TipSet, local bool) (bool, error) { epoch := curTs.Height() + 1 - 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()) + minGas := vm.PricelistByEpoch(epoch).OnChainMessage(m.ChainLength()) 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) diff --git a/chain/messagepool/selection.go b/chain/messagepool/selection.go index b3024b779..633e9b23f 100644 --- a/chain/messagepool/selection.go +++ b/chain/messagepool/selection.go @@ -781,7 +781,6 @@ func (mp *MessagePool) createMessageChains(actor address.Address, mset map[uint6 // 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 balance - a, err := mp.api.GetActorAfter(actor, ts) if err != nil { log.Errorf("failed to load actor state, not building chain for %s: %v", actor, err) @@ -794,12 +793,6 @@ func (mp *MessagePool) createMessageChains(actor address.Address, mset map[uint6 skip := 0 i := 0 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++ { m := msgs[i] @@ -815,7 +808,7 @@ func (mp *MessagePool) createMessageChains(actor address.Address, mset map[uint6 } curNonce++ - minGas := vm.PricelistByEpochAndNetworkVersion(ts.Height(), nv).OnChainMessage(m.ChainLength()).Total() + minGas := vm.PricelistByEpoch(ts.Height()).OnChainMessage(m.ChainLength()).Total() if m.Message.GasLimit < minGas { break } diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index 0262b1baa..2976b63d9 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -43,7 +43,6 @@ type FvmExtern struct { Rand blockstore.Blockstore epoch abi.ChainEpoch - nv network.Version lbState LookbackStateGetter base cid.Cid } @@ -215,7 +214,7 @@ func (x *FvmExtern) workerKeyAtLookback(ctx context.Context, minerId address.Add } cstWithoutGas := cbor.NewCborStore(x.Blockstore) - cbb := &gasChargingBlocks{gasAdder, PricelistByEpochAndNetworkVersion(x.epoch, x.nv), x.Blockstore} + cbb := &gasChargingBlocks{gasAdder, PricelistByEpoch(x.epoch), x.Blockstore} cstWithGas := cbor.NewCborStore(cbb) lbState, err := x.lbState(ctx, height) @@ -275,7 +274,7 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { fvmOpts := ffi.FVMOpts{ FVMVersion: 0, - Externs: &FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore, lbState: opts.LookbackState, base: opts.StateBase, epoch: opts.Epoch, nv: opts.NetworkVersion}, + Externs: &FvmExtern{Rand: opts.Rand, Blockstore: opts.Bstore, lbState: opts.LookbackState, base: opts.StateBase, epoch: opts.Epoch}, Epoch: opts.Epoch, BaseFee: opts.BaseFee, BaseCircSupply: circToReport, @@ -285,6 +284,7 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { } fvm, err := ffi.CreateFVM(&fvmOpts) + if err != nil { return nil, err } diff --git a/chain/vm/gas.go b/chain/vm/gas.go index 90d9ac4e8..5beaae40b 100644 --- a/chain/vm/gas.go +++ b/chain/vm/gas.go @@ -3,8 +3,6 @@ package vm import ( "fmt" - "github.com/filecoin-project/go-state-types/network" - vmr "github.com/filecoin-project/specs-actors/v7/actors/runtime" proof7 "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" @@ -84,153 +82,145 @@ type Pricelist interface { OnVerifyConsensusFault() GasCharge } -var priceListGenesis = pricelistV0{ - computeGasMulti: 1, - storageGasMulti: 1000, +// Prices are the price lists per starting epoch. Public for testing purposes +// (concretely to allow the test vector runner to rebase prices). +var Prices = map[abi.ChainEpoch]Pricelist{ + abi.ChainEpoch(0): &pricelistV0{ + computeGasMulti: 1, + storageGasMulti: 1000, - onChainMessageComputeBase: 38863, - onChainMessageStorageBase: 36, - onChainMessageStoragePerByte: 1, + onChainMessageComputeBase: 38863, + onChainMessageStorageBase: 36, + onChainMessageStoragePerByte: 1, - onChainReturnValuePerByte: 1, + onChainReturnValuePerByte: 1, - sendBase: 29233, - sendTransferFunds: 27500, - sendTransferOnlyPremium: 159672, - sendInvokeMethod: -5377, + sendBase: 29233, + sendTransferFunds: 27500, + sendTransferOnlyPremium: 159672, + sendInvokeMethod: -5377, - ipldGetBase: 75242, - ipldPutBase: 84070, - ipldPutPerByte: 1, + ipldGetBase: 75242, + ipldPutBase: 84070, + ipldPutPerByte: 1, - createActorCompute: 1108454, - createActorStorage: 36 + 40, - deleteActor: -(36 + 40), // -createActorStorage + createActorCompute: 1108454, + createActorStorage: 36 + 40, + deleteActor: -(36 + 40), // -createActorStorage - verifySignature: map[crypto.SigType]int64{ - crypto.SigTypeBLS: 16598605, - crypto.SigTypeSecp256k1: 1637292, + verifySignature: map[crypto.SigType]int64{ + crypto.SigTypeBLS: 16598605, + crypto.SigTypeSecp256k1: 1637292, + }, + + hashingBase: 31355, + computeUnsealedSectorCidBase: 98647, + verifySealBase: 2000, // TODO gas , it VerifySeal syscall is not used + verifyAggregateSealBase: 0, + verifyPostLookup: map[abi.RegisteredPoStProof]scalingCost{ + abi.RegisteredPoStProof_StackedDrgWindow512MiBV1: { + flat: 123861062, + scale: 9226981, + }, + abi.RegisteredPoStProof_StackedDrgWindow32GiBV1: { + flat: 748593537, + scale: 85639, + }, + abi.RegisteredPoStProof_StackedDrgWindow64GiBV1: { + flat: 748593537, + scale: 85639, + }, + }, + verifyPostDiscount: true, + verifyConsensusFault: 495422, }, + abi.ChainEpoch(build.UpgradeCalicoHeight): &pricelistV0{ + computeGasMulti: 1, + storageGasMulti: 1300, - hashingBase: 31355, - computeUnsealedSectorCidBase: 98647, - verifySealBase: 2000, // TODO gas , it VerifySeal syscall is not used - verifyAggregateSealBase: 0, - verifyPostLookup: map[abi.RegisteredPoStProof]scalingCost{ - abi.RegisteredPoStProof_StackedDrgWindow512MiBV1: { - flat: 123861062, - scale: 9226981, + onChainMessageComputeBase: 38863, + onChainMessageStorageBase: 36, + onChainMessageStoragePerByte: 1, + + onChainReturnValuePerByte: 1, + + sendBase: 29233, + sendTransferFunds: 27500, + sendTransferOnlyPremium: 159672, + sendInvokeMethod: -5377, + + ipldGetBase: 114617, + ipldPutBase: 353640, + ipldPutPerByte: 1, + + createActorCompute: 1108454, + createActorStorage: 36 + 40, + deleteActor: -(36 + 40), // -createActorStorage + + verifySignature: map[crypto.SigType]int64{ + crypto.SigTypeBLS: 16598605, + crypto.SigTypeSecp256k1: 1637292, }, - abi.RegisteredPoStProof_StackedDrgWindow32GiBV1: { - flat: 748593537, - scale: 85639, + + hashingBase: 31355, + computeUnsealedSectorCidBase: 98647, + verifySealBase: 2000, // TODO gas, it VerifySeal syscall is not used + + verifyAggregateSealPer: map[abi.RegisteredSealProof]int64{ + abi.RegisteredSealProof_StackedDrg32GiBV1_1: 449900, + abi.RegisteredSealProof_StackedDrg64GiBV1_1: 359272, }, - abi.RegisteredPoStProof_StackedDrgWindow64GiBV1: { - flat: 748593537, - scale: 85639, + verifyAggregateSealSteps: map[abi.RegisteredSealProof]stepCost{ + abi.RegisteredSealProof_StackedDrg32GiBV1_1: { + {4, 103994170}, + {7, 112356810}, + {13, 122912610}, + {26, 137559930}, + {52, 162039100}, + {103, 210960780}, + {205, 318351180}, + {410, 528274980}, + }, + abi.RegisteredSealProof_StackedDrg64GiBV1_1: { + {4, 102581240}, + {7, 110803030}, + {13, 120803700}, + {26, 134642130}, + {52, 157357890}, + {103, 203017690}, + {205, 304253590}, + {410, 509880640}, + }, }, + + verifyPostLookup: map[abi.RegisteredPoStProof]scalingCost{ + abi.RegisteredPoStProof_StackedDrgWindow512MiBV1: { + flat: 117680921, + scale: 43780, + }, + abi.RegisteredPoStProof_StackedDrgWindow32GiBV1: { + flat: 117680921, + scale: 43780, + }, + abi.RegisteredPoStProof_StackedDrgWindow64GiBV1: { + flat: 117680921, + scale: 43780, + }, + }, + verifyPostDiscount: false, + verifyConsensusFault: 495422, + + verifyReplicaUpdate: 36316136, }, - verifyPostDiscount: true, - verifyConsensusFault: 495422, } -var priceListCalico = pricelistV0{ - computeGasMulti: 1, - storageGasMulti: 1300, - - onChainMessageComputeBase: 38863, - onChainMessageStorageBase: 36, - onChainMessageStoragePerByte: 1, - - onChainReturnValuePerByte: 1, - - sendBase: 29233, - sendTransferFunds: 27500, - sendTransferOnlyPremium: 159672, - sendInvokeMethod: -5377, - - ipldGetBase: 114617, - ipldPutBase: 353640, - ipldPutPerByte: 1, - - createActorCompute: 1108454, - createActorStorage: 36 + 40, - deleteActor: -(36 + 40), // -createActorStorage - - verifySignature: map[crypto.SigType]int64{ - crypto.SigTypeBLS: 16598605, - crypto.SigTypeSecp256k1: 1637292, - }, - - hashingBase: 31355, - computeUnsealedSectorCidBase: 98647, - verifySealBase: 2000, // TODO gas, it VerifySeal syscall is not used - - verifyAggregateSealPer: map[abi.RegisteredSealProof]int64{ - abi.RegisteredSealProof_StackedDrg32GiBV1_1: 449900, - abi.RegisteredSealProof_StackedDrg64GiBV1_1: 359272, - }, - verifyAggregateSealSteps: map[abi.RegisteredSealProof]stepCost{ - abi.RegisteredSealProof_StackedDrg32GiBV1_1: { - {4, 103994170}, - {7, 112356810}, - {13, 122912610}, - {26, 137559930}, - {52, 162039100}, - {103, 210960780}, - {205, 318351180}, - {410, 528274980}, - }, - abi.RegisteredSealProof_StackedDrg64GiBV1_1: { - {4, 102581240}, - {7, 110803030}, - {13, 120803700}, - {26, 134642130}, - {52, 157357890}, - {103, 203017690}, - {205, 304253590}, - {410, 509880640}, - }, - }, - - verifyPostLookup: map[abi.RegisteredPoStProof]scalingCost{ - abi.RegisteredPoStProof_StackedDrgWindow512MiBV1: { - flat: 117680921, - scale: 43780, - }, - abi.RegisteredPoStProof_StackedDrgWindow32GiBV1: { - flat: 117680921, - scale: 43780, - }, - abi.RegisteredPoStProof_StackedDrgWindow64GiBV1: { - flat: 117680921, - scale: 43780, - }, - }, - verifyPostDiscount: false, - verifyConsensusFault: 495422, - - verifyReplicaUpdate: 36316136, -} - -// Prices are the price lists per starting epoch. -// 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 - } - +// PricelistByEpoch finds the latest prices for the given epoch +func PricelistByEpoch(epoch abi.ChainEpoch) Pricelist { // 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 bestEpoch := abi.ChainEpoch(0) - bestPrice := pricesByEpoch[bestEpoch] - for e, pl := range pricesByEpoch { + bestPrice := Prices[bestEpoch] + for e, pl := range Prices { // if `e` happened after `bestEpoch` and `e` is earlier or equal to the target `epoch` if e > bestEpoch && e <= epoch { bestEpoch = e diff --git a/chain/vm/mkactor.go b/chain/vm/mkactor.go index 6666f16ad..5716b5006 100644 --- a/chain/vm/mkactor.go +++ b/chain/vm/mkactor.go @@ -51,7 +51,7 @@ var EmptyObjectCid cid.Cid // TryCreateAccountActor creates account actors from only BLS/SECP256K1 addresses. func TryCreateAccountActor(rt *Runtime, addr address.Address) (*types.Actor, address.Address, aerrors.ActorError) { - if err := rt.chargeGasSafe(PricelistByEpochAndNetworkVersion(rt.height, rt.NetworkVersion()).OnCreateActor()); err != nil { + if err := rt.chargeGasSafe(PricelistByEpoch(rt.height).OnCreateActor()); err != nil { return nil, address.Undef, err } diff --git a/chain/vm/vm.go b/chain/vm/vm.go index 4b3fd2105..06c615ac7 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -135,7 +135,7 @@ func (vm *LegacyVM) makeRuntime(ctx context.Context, msg *types.Message, parent gasAvailable: msg.GasLimit, depth: 0, numActorsCreated: 0, - pricelist: PricelistByEpochAndNetworkVersion(vm.blockHeight, vm.networkVersion), + pricelist: PricelistByEpoch(vm.blockHeight), allowInternal: true, callerValidated: false, executionTrace: types.ExecutionTrace{Msg: msg}, @@ -431,7 +431,7 @@ func (vm *LegacyVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*App return nil, err } - pl := PricelistByEpochAndNetworkVersion(vm.blockHeight, vm.networkVersion) + pl := PricelistByEpoch(vm.blockHeight) msgGas := pl.OnChainMessage(cmsg.ChainLength()) msgGasCost := msgGas.Total() diff --git a/conformance/runner.go b/conformance/runner.go index 162c934b9..fd44ecff9 100644 --- a/conformance/runner.go +++ b/conformance/runner.go @@ -7,6 +7,7 @@ import ( "encoding/base64" "fmt" "io/ioutil" + "math" "os" "os/exec" "strconv" @@ -28,6 +29,7 @@ import ( "github.com/filecoin-project/test-vectors/schema" "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/vm" ) @@ -51,6 +53,52 @@ var TipsetVectorOpts struct { 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. func ExecuteMessageVector(r Reporter, vector *schema.TestVector, variant *schema.Variant) (diffs []string, err error) { var ( @@ -69,6 +117,10 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector, variant *schema // Create a new Driver. driver := NewDriver(ctx, vector.Selector, DriverOpts{DisableVMFlush: true}) + // Monkey patch the gas pricing. + revertFn := adjustGasPricing(baseEpoch, nv) + defer revertFn() + // Apply every message. for i, m := range vector.ApplyMessages { msg, err := types.DecodeMessage(m.Bytes)