Merge pull request #1450 from filecoin-project/asr/gas

Re: #1446: Enable gas tracking in validation tests
This commit is contained in:
Whyrusleeping 2020-03-25 12:53:57 -07:00 committed by GitHub
commit 1aef03bdd7
21 changed files with 194 additions and 200 deletions

View File

@ -9,7 +9,6 @@ import (
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
@ -343,6 +342,6 @@ func (e *calledEvents) Called(check CheckFunc, hnd CalledHandler, rev RevertHand
return nil
}
func (e *calledEvents) CalledMsg(ctx context.Context, hnd CalledHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch, msg store.ChainMsg) error {
func (e *calledEvents) CalledMsg(ctx context.Context, hnd CalledHandler, rev RevertHandler, confidence int, timeout abi.ChainEpoch, msg types.ChainMsg) error {
return e.Called(e.CheckMsg(ctx, msg, hnd), hnd, rev, confidence, timeout, e.MatchMsg(msg.VMMessage()))
}

View File

@ -5,11 +5,10 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
func (e *calledEvents) CheckMsg(ctx context.Context, smsg store.ChainMsg, hnd CalledHandler) CheckFunc {
func (e *calledEvents) CheckMsg(ctx context.Context, smsg types.ChainMsg, hnd CalledHandler) CheckFunc {
msg := smsg.VMMessage()
return func(ts *types.TipSet) (done bool, more bool, err error) {

View File

@ -31,7 +31,7 @@ func doExecValue(ctx context.Context, vm *vm.VM, to, from address.Address, value
return nil, xerrors.Errorf("doExec failed to get from actor: %w", err)
}
ret, err := vm.ApplyMessage(ctx, &types.Message{
ret, err := vm.ApplyImplicitMessage(ctx, &types.Message{
To: to,
From: from,
Method: method,

View File

@ -25,7 +25,6 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/node/modules/dtypes"
@ -109,11 +108,11 @@ func (ms *msgSet) add(m *types.SignedMessage) error {
type Provider interface {
SubscribeHeadChanges(func(rev, app []*types.TipSet) error) *types.TipSet
PutMessage(m store.ChainMsg) (cid.Cid, error)
PutMessage(m types.ChainMsg) (cid.Cid, error)
PubSubPublish(string, []byte) error
StateGetActor(address.Address, *types.TipSet) (*types.Actor, error)
MessagesForBlock(*types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error)
MessagesForTipset(*types.TipSet) ([]store.ChainMsg, error)
MessagesForTipset(*types.TipSet) ([]types.ChainMsg, error)
LoadTipSet(tsk types.TipSetKey) (*types.TipSet, error)
}
@ -131,7 +130,7 @@ func (mpp *mpoolProvider) SubscribeHeadChanges(cb func(rev, app []*types.TipSet)
return mpp.sm.ChainStore().GetHeaviestTipSet()
}
func (mpp *mpoolProvider) PutMessage(m store.ChainMsg) (cid.Cid, error) {
func (mpp *mpoolProvider) PutMessage(m types.ChainMsg) (cid.Cid, error) {
return mpp.sm.ChainStore().PutMessage(m)
}
@ -147,7 +146,7 @@ func (mpp *mpoolProvider) MessagesForBlock(h *types.BlockHeader) ([]*types.Messa
return mpp.sm.ChainStore().MessagesForBlock(h)
}
func (mpp *mpoolProvider) MessagesForTipset(ts *types.TipSet) ([]store.ChainMsg, error) {
func (mpp *mpoolProvider) MessagesForTipset(ts *types.TipSet) ([]types.ChainMsg, error) {
return mpp.sm.ChainStore().MessagesForTipset(ts)
}

View File

@ -5,7 +5,6 @@ import (
"testing"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/mock"
"github.com/filecoin-project/lotus/chain/wallet"
@ -60,7 +59,7 @@ func (tma *testMpoolApi) SubscribeHeadChanges(cb func(rev, app []*types.TipSet)
return nil
}
func (tma *testMpoolApi) PutMessage(m store.ChainMsg) (cid.Cid, error) {
func (tma *testMpoolApi) PutMessage(m types.ChainMsg) (cid.Cid, error) {
return cid.Undef, nil
}
@ -79,7 +78,7 @@ func (tma *testMpoolApi) MessagesForBlock(h *types.BlockHeader) ([]*types.Messag
return nil, tma.bmsgs[h.Cid()], nil
}
func (tma *testMpoolApi) MessagesForTipset(ts *types.TipSet) ([]store.ChainMsg, error) {
func (tma *testMpoolApi) MessagesForTipset(ts *types.TipSet) ([]types.ChainMsg, error) {
if len(ts.Blocks()) != 1 {
panic("cant deal with multiblock tipsets in this test")
}
@ -89,7 +88,7 @@ func (tma *testMpoolApi) MessagesForTipset(ts *types.TipSet) ([]store.ChainMsg,
return nil, err
}
var out []store.ChainMsg
var out []types.ChainMsg
for _, m := range bm {
out = append(out, m)
}

View File

@ -188,7 +188,7 @@ func (st *StateTree) ClearSnapshot() {
st.snapshots = st.snapshots[:len(st.snapshots)-1]
}
func (st *StateTree) RegisterNewAddress(addr address.Address, act *types.Actor) (address.Address, error) {
func (st *StateTree) RegisterNewAddress(addr address.Address) (address.Address, error) {
var out address.Address
err := st.MutateActor(builtin.InitActorAddr, func(initact *types.Actor) error {
var ias init_.State
@ -214,10 +214,6 @@ func (st *StateTree) RegisterNewAddress(addr address.Address, act *types.Actor)
return address.Undef, err
}
if err := st.SetActor(out, act); err != nil {
return address.Undef, err
}
return out, nil
}

View File

@ -52,7 +52,7 @@ func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate
msg.Nonce = fromActor.Nonce
// TODO: maybe just use the invoker directly?
ret, err := vmi.ApplyMessage(ctx, msg)
ret, err := vmi.ApplyImplicitMessage(ctx, msg)
if err != nil {
return nil, xerrors.Errorf("apply message failed: %w", err)
}

View File

@ -140,8 +140,8 @@ func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (c
type BlockMessages struct {
Miner address.Address
BlsMessages []store.ChainMsg
SecpkMessages []store.ChainMsg
BlsMessages []types.ChainMsg
SecpkMessages []types.ChainMsg
TicketCount int64
}
@ -153,23 +153,8 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, pstate cid.Cid, bms []B
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
}
applied := make(map[address.Address]uint64)
balances := make(map[address.Address]types.BigInt)
preloadAddr := func(a address.Address) error {
if _, ok := applied[a]; !ok {
act, err := vmi.StateTree().GetActor(a)
if err != nil {
return err
}
applied[a] = act.Nonce
balances[a] = act.Balance
}
return nil
}
var receipts []cbg.CBORMarshaler
processedMsgs := map[cid.Cid]bool{}
for _, b := range bms {
vmi.SetBlockMiner(b.Miner)
@ -178,33 +163,24 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, pstate cid.Cid, bms []B
for _, cm := range append(b.BlsMessages, b.SecpkMessages...) {
m := cm.VMMessage()
if err := preloadAddr(m.From); err != nil {
return cid.Undef, cid.Undef, err
}
if applied[m.From] != m.Nonce {
if _, found := processedMsgs[m.Cid()]; found {
continue
}
applied[m.From]++
if balances[m.From].LessThan(m.RequiredFunds()) {
continue
}
balances[m.From] = types.BigSub(balances[m.From], m.RequiredFunds())
r, err := vmi.ApplyMessage(ctx, m)
r, err := vmi.ApplyMessage(ctx, cm)
if err != nil {
return cid.Undef, cid.Undef, err
}
receipts = append(receipts, &r.MessageReceipt)
gasReward = big.Add(gasReward, big.NewInt(r.GasUsed))
penalty = big.Add(penalty, r.Penalty)
if cb != nil {
if err := cb(cm.Cid(), m, r); err != nil {
return cid.Undef, cid.Undef, err
}
}
processedMsgs[m.Cid()] = true
}
var err error
@ -233,7 +209,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, pstate cid.Cid, bms []B
Method: builtin.MethodsReward.AwardBlockReward,
Params: params,
}
ret, err := vmi.ApplyMessage(ctx, rwMsg)
ret, err := vmi.ApplyImplicitMessage(ctx, rwMsg)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("failed to apply reward message for miner %s: %w", b.Miner, err)
}
@ -265,7 +241,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, pstate cid.Cid, bms []B
Method: builtin.MethodsCron.EpochTick,
Params: nil,
}
ret, err := vmi.ApplyMessage(ctx, cronMsg)
ret, err := vmi.ApplyImplicitMessage(ctx, cronMsg)
if err != nil {
return cid.Undef, cid.Undef, err
}
@ -335,8 +311,8 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
bm := BlockMessages{
Miner: b.Miner,
BlsMessages: make([]store.ChainMsg, 0, len(bms)),
SecpkMessages: make([]store.ChainMsg, 0, len(sms)),
BlsMessages: make([]types.ChainMsg, 0, len(bms)),
SecpkMessages: make([]types.ChainMsg, 0, len(sms)),
TicketCount: int64(len(b.EPostProof.Proofs)),
}
@ -615,7 +591,7 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, mcid cid.Cid) (*ty
return fts, r, nil
}
func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet, m store.ChainMsg) (*types.TipSet, *types.MessageReceipt, error) {
func (sm *StateManager) searchBackForMsg(ctx context.Context, from *types.TipSet, m types.ChainMsg) (*types.TipSet, *types.MessageReceipt, error) {
cur := from
for {

View File

@ -330,6 +330,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
}
for i, msg := range msgs {
// TODO: Use the signed message length for secp messages
ret, err := vmi.ApplyMessage(ctx, msg)
if err != nil {
return cid.Undef, nil, xerrors.Errorf("applying message %s: %w", msg.Cid(), err)

View File

@ -597,7 +597,7 @@ func (cs *ChainStore) GetGenesis() (*types.BlockHeader, error) {
return types.DecodeBlock(genb.RawData())
}
func (cs *ChainStore) GetCMessage(c cid.Cid) (ChainMsg, error) {
func (cs *ChainStore) GetCMessage(c cid.Cid) (types.ChainMsg, error) {
m, err := cs.GetMessage(c)
if err == nil {
return m, nil
@ -650,13 +650,7 @@ func (cs *ChainStore) readAMTCids(root cid.Cid) ([]cid.Cid, error) {
return cids, nil
}
type ChainMsg interface {
Cid() cid.Cid
VMMessage() *types.Message
ToStorageBlock() (block.Block, error)
}
func (cs *ChainStore) MessagesForTipset(ts *types.TipSet) ([]ChainMsg, error) {
func (cs *ChainStore) MessagesForTipset(ts *types.TipSet) ([]types.ChainMsg, error) {
applied := make(map[address.Address]uint64)
balances := make(map[address.Address]types.BigInt)
@ -679,14 +673,14 @@ func (cs *ChainStore) MessagesForTipset(ts *types.TipSet) ([]ChainMsg, error) {
return nil
}
var out []ChainMsg
var out []types.ChainMsg
for _, b := range ts.Blocks() {
bms, sms, err := cs.MessagesForBlock(b)
if err != nil {
return nil, xerrors.Errorf("failed to get messages for block: %w", err)
}
cmsgs := make([]ChainMsg, 0, len(bms)+len(sms))
cmsgs := make([]types.ChainMsg, 0, len(bms)+len(sms))
for _, m := range bms {
cmsgs = append(cmsgs, m)
}

View File

@ -95,6 +95,7 @@ func (cs *ChainStore) call(ctx context.Context, msg *types.Message, ts *types.Ti
msg.Nonce = fromActor.Nonce
// TODO: maybe just use the invoker directly?
// TODO: use signed message length for secp messages
ret, err := vmi.ApplyMessage(ctx, msg)
if err != nil {
return nil, xerrors.Errorf("apply message failed: %w", err)

View File

@ -12,6 +12,13 @@ import (
"github.com/filecoin-project/go-address"
)
type ChainMsg interface {
Cid() cid.Cid
VMMessage() *Message
ToStorageBlock() (block.Block, error)
ChainLength() int
}
type Message struct {
To address.Address
From address.Address
@ -60,6 +67,14 @@ func (m *Message) Serialize() ([]byte, error) {
return buf.Bytes(), nil
}
func (m *Message) ChainLength() int {
ser, err := m.Serialize()
if err != nil {
panic(err)
}
return len(ser)
}
func (m *Message) ToStorageBlock() (block.Block, error) {
data, err := m.Serialize()
if err != nil {

View File

@ -63,6 +63,14 @@ func (sm *SignedMessage) Serialize() ([]byte, error) {
return buf.Bytes(), nil
}
func (m *SignedMessage) ChainLength() int {
ser, err := m.Serialize()
if err != nil {
panic(err)
}
return len(ser)
}
func (sm *SignedMessage) Size() int {
serdata, err := sm.Serialize()
if err != nil {

View File

@ -41,7 +41,8 @@ func (a *Applier) ApplyMessage(eCtx *vtypes.ExecutionContext, state vstate.VMWra
return vtypes.MessageReceipt{}, err
}
ret, err := lotusVM.ApplyMessage(ctx, toLotusMsg(message))
lm := toLotusMsg(message)
ret, err := lotusVM.ApplyMessage(ctx, lm)
if err != nil {
return vtypes.MessageReceipt{}, err
}
@ -82,7 +83,7 @@ func (a *Applier) ApplyTipSetMessages(state vstate.VMWrapper, blocks []vtypes.Bl
}
for _, m := range b.SECPMessages {
bm.SecpkMessages = append(bm.SecpkMessages, toLotusMsg(&m.Message))
bm.SecpkMessages = append(bm.SecpkMessages, toLotusSignedMsg(m))
}
bms = append(bms, bm)
@ -145,3 +146,10 @@ func toLotusMsg(msg *vtypes.Message) *types.Message {
Params: msg.Params,
}
}
func toLotusSignedMsg(msg *vtypes.SignedMessage) *types.SignedMessage {
return &types.SignedMessage{
Message: *toLotusMsg(&msg.Message),
Signature: msg.Signature,
}
}

View File

@ -39,7 +39,7 @@ func (f *Factories) NewRandomnessSource() vstate.RandomnessSource {
}
func (f *Factories) NewValidationConfig() vstate.ValidationConfig {
trackGas := false
trackGas := true
checkExit := true
checkRet := true
// ignore gas and return value assertions

View File

@ -87,7 +87,8 @@ func (k *KeyManager) newBLSKey() *wallet.Key {
//sk := ffi.PrivateKeyGenerate(s.blsSeed)
// s.blsSeed++
sk := [32]byte{}
sk[0] = uint8(k.blsSeed + 1) // hack to keep gas values determinist
sk[0] = uint8(k.blsSeed) // hack to keep gas values determinist
k.blsSeed++
key, err := wallet.NewKey(types.KeyInfo{
Type: wallet.KTBLS,
PrivateKey: sk[:],

View File

@ -4,7 +4,6 @@ import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
blockstore "github.com/ipfs/go-ipfs-blockstore"
@ -18,7 +17,6 @@ import (
vstate "github.com/filecoin-project/chain-validation/state"
"github.com/filecoin-project/lotus/chain/gen/genesis"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
)
@ -116,17 +114,13 @@ func (s *StateWrapper) SetActorState(addr address.Address, balance abi.TokenAmou
}
func (s *StateWrapper) CreateActor(code cid.Cid, addr address.Address, balance abi.TokenAmount, actorState runtime.CBORMarshaler) (vstate.Actor, address.Address, error) {
if addr == builtin.InitActorAddr || addr == builtin.StoragePowerActorAddr || addr == builtin.StorageMarketActorAddr {
act, err := s.SetupSingletonActor(addr)
if err != nil {
return nil, address.Undef, err
}
return act, addr, nil
}
tree, err := state.LoadStateTree(s.cst, s.Root())
idAddr := addr
tree, err := state.LoadStateTree(s.cst, s.stateRoot)
if err != nil {
return nil, address.Undef, err
}
if addr.Protocol() != address.ID {
actHead, err := tree.Store.Put(context.Background(), actorState)
if err != nil {
return nil, address.Undef, err
@ -137,7 +131,7 @@ func (s *StateWrapper) CreateActor(code cid.Cid, addr address.Address, balance a
Balance: balance,
}}
idAddr, err := tree.RegisterNewAddress(addr, &actr.Actor)
idAddr, err = tree.RegisterNewAddress(addr)
if err != nil {
return nil, address.Undef, xerrors.Errorf("register new address for actor: %w", err)
}
@ -145,8 +139,25 @@ func (s *StateWrapper) CreateActor(code cid.Cid, addr address.Address, balance a
if err := tree.SetActor(addr, &actr.Actor); err != nil {
return nil, address.Undef, xerrors.Errorf("setting new actor for actor: %w", err)
}
}
return actr, idAddr, s.flush(tree)
// store newState
head, err := tree.Store.Put(context.Background(), actorState)
if err != nil {
return nil, address.Undef, err
}
// create and store actor object
a := types.Actor{
Code: code,
Head: head,
Balance: balance,
}
if err := tree.SetActor(idAddr, &a); err != nil {
return nil, address.Undef, err
}
return &actorWrapper{a}, idAddr, s.flush(tree)
}
// Flushes a state tree to storage and sets this state's root to that tree's root CID.
@ -192,46 +203,3 @@ type contextStore struct {
func (s *contextStore) Context() context.Context {
return s.ctx
}
func (s *StateWrapper) SetupSingletonActor(addr address.Address) (vstate.Actor, error) {
tree, err := state.LoadStateTree(s.cst, s.stateRoot)
if err != nil {
return nil, err
}
switch addr {
case builtin.InitActorAddr:
// FIXME this is going to be a problem if go-filecoin and lotus setup their init actors with different netnames
// ideally lotus should use the init actor constructor
initact, err := genesis.SetupInitActor(s.bs, "chain-validation", nil)
if err != nil {
return nil, xerrors.Errorf("setup init actor: %w", err)
}
if err := tree.SetActor(builtin.InitActorAddr, initact); err != nil {
return nil, xerrors.Errorf("set init actor: %w", err)
}
return &actorWrapper{*initact}, s.flush(tree)
case builtin.StorageMarketActorAddr:
smact, err := genesis.SetupStorageMarketActor(s.bs)
if err != nil {
return nil, xerrors.Errorf("setup storage marker actor: %w", err)
}
if err := tree.SetActor(builtin.StorageMarketActorAddr, smact); err != nil {
return nil, xerrors.Errorf("set storage marker actor: %w", err)
}
return &actorWrapper{*smact}, s.flush(tree)
case builtin.StoragePowerActorAddr:
spact, err := genesis.SetupStoragePowerActor(s.bs)
if err != nil {
return nil, xerrors.Errorf("setup storage power actor: %w", err)
}
if err := tree.SetActor(builtin.StoragePowerActorAddr, spact); err != nil {
return nil, xerrors.Errorf("set storage power actor: %w", err)
}
return &actorWrapper{*spact}, s.flush(tree)
default:
return nil, xerrors.Errorf("%v is not a singleton actor address", addr)
}
}

View File

@ -2,9 +2,11 @@ package vm
import (
"context"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/account"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
@ -27,25 +29,50 @@ func init() {
var EmptyObjectCid cid.Cid
// Creates account actors from only BLS/SECP256K1 addresses.
func TryCreateAccountActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
act, err := makeActor(st, addr)
func TryCreateAccountActor(ctx context.Context, rt *Runtime, addr address.Address) (*types.Actor, aerrors.ActorError) {
addrID, err := rt.state.RegisterNewAddress(addr)
if err != nil {
return nil, err
}
if _, err := st.RegisterNewAddress(addr, act); err != nil {
return nil, aerrors.Escalate(err, "registering actor address")
}
if err := rt.chargeGasSafe(PricelistByEpoch(rt.height).OnCreateActor()); err != nil {
return nil, err
}
act, aerr := makeActor(rt.state, addr)
if aerr != nil {
return nil, aerr
}
if err := rt.state.SetActor(addrID, act); err != nil {
return nil, aerrors.Escalate(err, "creating new actor failed")
}
p, err := actors.SerializeParams(&addr)
if err != nil {
return nil, aerrors.Escalate(err, "registering actor address")
}
// call constructor on account
_, aerr = rt.internalSend(builtin.SystemActorAddr, addrID, builtin.MethodsAccount.Constructor, big.Zero(), p)
if aerr != nil {
return nil, aerrors.Fatal("failed to invoke account constructor")
}
act, err = rt.state.GetActor(addrID)
if err != nil {
return nil, aerrors.Escalate(err, "loading newly created actor failed")
}
return act, nil
}
func makeActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
switch addr.Protocol() {
case address.BLS:
return NewBLSAccountActor(st, addr)
return NewBLSAccountActor()
case address.SECP256K1:
return NewSecp256k1AccountActor(st, addr)
return NewSecp256k1AccountActor()
case address.ID:
return nil, aerrors.Newf(1, "no actor with given ID: %s", addr)
case address.Actor:
@ -55,37 +82,21 @@ func makeActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors
}
}
func NewBLSAccountActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
var acstate account.State
acstate.Address = addr
c, err := st.Store.Put(context.TODO(), &acstate)
if err != nil {
return nil, aerrors.Escalate(err, "serializing account actor state")
}
func NewBLSAccountActor() (*types.Actor, aerrors.ActorError) {
nact := &types.Actor{
Code: builtin.AccountActorCodeID,
Balance: types.NewInt(0),
Head: c,
Head: EmptyObjectCid,
}
return nact, nil
}
func NewSecp256k1AccountActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
var acstate account.State
acstate.Address = addr
c, err := st.Store.Put(context.TODO(), &acstate)
if err != nil {
return nil, aerrors.Escalate(err, "serializing account actor state")
}
func NewSecp256k1AccountActor() (*types.Actor, aerrors.ActorError) {
nact := &types.Actor{
Code: builtin.AccountActorCodeID,
Balance: types.NewInt(0),
Head: c,
Head: EmptyObjectCid,
}
return nact, nil

View File

@ -281,7 +281,7 @@ func (rs *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMars
params = buf.Bytes()
}
ret, err := rs.internalSend(to, method, types.BigInt(value), params)
ret, err := rs.internalSend(rs.Message().Receiver(), to, method, types.BigInt(value), params)
if err != nil {
if err.IsFatal() {
panic(err)
@ -292,7 +292,7 @@ func (rs *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMars
return &dumbWrapperType{ret}, 0
}
func (rt *Runtime) internalSend(to address.Address, method abi.MethodNum, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) {
func (rt *Runtime) internalSend(from, to address.Address, method abi.MethodNum, value types.BigInt, params []byte) ([]byte, aerrors.ActorError) {
ctx, span := trace.StartSpan(rt.ctx, "vmc.Send")
defer span.End()
if span.IsRecordingEvents() {
@ -304,7 +304,7 @@ func (rt *Runtime) internalSend(to address.Address, method abi.MethodNum, value
}
msg := &types.Message{
From: rt.Message().Receiver(),
From: from,
To: to,
Method: method,
Value: value,
@ -317,7 +317,6 @@ func (rt *Runtime) internalSend(to address.Address, method abi.MethodNum, value
return nil, aerrors.Fatalf("snapshot failed: %s", err)
}
defer st.ClearSnapshot()
rt.ChargeGas(rt.Pricelist().OnMethodInvocation(value, method))
ret, errSend, subrt := rt.vm.send(ctx, msg, rt, 0)
if errSend != nil {

View File

@ -8,8 +8,6 @@ import (
"testing"
suites "github.com/filecoin-project/chain-validation/suites"
"github.com/filecoin-project/chain-validation/suites/tipset"
factory "github.com/filecoin-project/lotus/chain/validation"
)
@ -36,7 +34,6 @@ func init() {
// initialize the test skipper with tests being skipped
TestSuiteSkipper = TestSkipper{testSkips: []suites.TestCase{
/* tests to skip go here */
tipset.TestMinerRewardsAndPenalties,
}}
}

View File

@ -4,7 +4,6 @@ import (
"bytes"
"context"
"fmt"
"math/big"
"reflect"
"github.com/filecoin-project/specs-actors/actors/builtin"
@ -185,7 +184,7 @@ type Rand interface {
type ApplyRet struct {
types.MessageReceipt
ActorErr aerrors.ActorError
Penalty big.Int
Penalty types.BigInt
InternalExecutions []*ExecutionResult
}
@ -211,25 +210,24 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
}()
}
aerr := rt.chargeGasSafe(rt.Pricelist().OnMethodInvocation(msg.Value, msg.Method))
if aerr != nil {
return nil, aerr, rt
}
toActor, err := st.GetActor(msg.To)
if err != nil {
if xerrors.Is(err, init_.ErrAddressNotFound) {
a, err := TryCreateAccountActor(st, msg.To)
a, err := TryCreateAccountActor(ctx, rt, msg.To)
if err != nil {
return nil, aerrors.Absorb(err, 1, "could not create account"), rt
}
toActor = a
gasUsed += PricelistByEpoch(vm.blockHeight).OnCreateActor()
} else {
return nil, aerrors.Escalate(err, "getting actor"), rt
}
}
aerr := rt.chargeGasSafe(rt.Pricelist().OnMethodInvocation(msg.Value, msg.Method))
if aerr != nil {
return nil, aerr, rt
}
if types.BigCmp(msg.Value, types.NewInt(0)) != 0 {
if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil {
return nil, aerrors.Absorb(err, 1, "failed to transfer funds"), nil
@ -263,9 +261,24 @@ func checkMessage(msg *types.Message) error {
return nil
}
func (vm *VM) ApplyMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) {
func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) {
ret, actorErr, _ := vm.send(ctx, msg, nil, 0)
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.ExitCode(aerrors.RetCode(actorErr)),
Return: ret,
GasUsed: 0,
},
ActorErr: actorErr,
InternalExecutions: nil,
Penalty: types.NewInt(0),
}, actorErr
}
func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) {
ctx, span := trace.StartSpan(ctx, "vm.ApplyMessage")
defer span.End()
msg := cmsg.VMMessage()
if span.IsRecordingEvents() {
span.AddAttributes(
trace.StringAttribute("to", msg.To.String()),
@ -279,42 +292,52 @@ func (vm *VM) ApplyMessage(ctx context.Context, msg *types.Message) (*ApplyRet,
}
pl := PricelistByEpoch(vm.blockHeight)
serMsg, err := msg.Serialize()
if err != nil {
return nil, xerrors.Errorf("could not serialize message: %w", err)
}
msgGasCost := pl.OnChainMessage(len(serMsg))
msgGasCost := pl.OnChainMessage(cmsg.ChainLength())
// TODO: charge miner??
if msgGasCost > msg.GasLimit {
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrOutOfGas,
GasUsed: msg.GasLimit,
GasUsed: 0,
},
Penalty: types.BigMul(msg.GasPrice, types.NewInt(uint64(msgGasCost))),
}, nil
}
st := vm.cstate
minerPenaltyAmount := types.BigMul(msg.GasPrice, types.NewInt(uint64(msgGasCost)))
fromActor, err := st.GetActor(msg.From)
if err != nil {
if xerrors.Is(err, types.ErrActorNotFound) {
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrActorNotFound,
GasUsed: msg.GasLimit,
GasUsed: 0,
},
Penalty: minerPenaltyAmount,
}, nil
}
return nil, xerrors.Errorf("failed to look up from actor: %w", err)
}
if !fromActor.Code.Equals(builtin.AccountActorCodeID) {
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrForbidden,
GasUsed: 0,
},
Penalty: minerPenaltyAmount,
}, nil
}
if msg.Nonce != fromActor.Nonce {
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrInvalidCallSeqNum,
GasUsed: 0,
},
Penalty: minerPenaltyAmount,
}, nil
}
@ -324,8 +347,9 @@ func (vm *VM) ApplyMessage(ctx context.Context, msg *types.Message) (*ApplyRet,
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
ExitCode: exitcode.SysErrInsufficientFunds,
GasUsed: msg.GasLimit,
GasUsed: 0,
},
Penalty: minerPenaltyAmount,
}, nil
}
@ -367,12 +391,11 @@ func (vm *VM) ApplyMessage(ctx context.Context, msg *types.Message) (*ApplyRet,
var gasUsed int64
if errcode = aerrors.RetCode(actorErr); errcode != 0 {
gasUsed = msg.GasLimit
// revert all state changes since snapshot
if err := st.Revert(); err != nil {
return nil, xerrors.Errorf("revert state failed: %w", err)
}
} else {
}
gasUsed = rt.gasUsed
if gasUsed < 0 {
gasUsed = 0
@ -382,7 +405,6 @@ func (vm *VM) ApplyMessage(ctx context.Context, msg *types.Message) (*ApplyRet,
if err := vm.transferFromGasHolder(msg.From, gasHolder, refund); err != nil {
return nil, xerrors.Errorf("failed to refund gas")
}
}
gasReward := types.BigMul(msg.GasPrice, types.NewInt(uint64(gasUsed)))
if err := vm.transferFromGasHolder(builtin.RewardActorAddr, gasHolder, gasReward); err != nil {
@ -401,6 +423,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, msg *types.Message) (*ApplyRet,
},
ActorErr: actorErr,
InternalExecutions: rt.internalExecutions,
Penalty: types.NewInt(0),
}, nil
}