Merge pull request #1450 from filecoin-project/asr/gas
Re: #1446: Enable gas tracking in validation tests
This commit is contained in:
commit
1aef03bdd7
@ -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()))
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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[:],
|
||||
|
@ -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,37 +114,50 @@ 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)
|
||||
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
|
||||
}
|
||||
return act, addr, nil
|
||||
actr := &actorWrapper{types.Actor{
|
||||
Code: code,
|
||||
Head: actHead,
|
||||
Balance: balance,
|
||||
}}
|
||||
|
||||
idAddr, err = tree.RegisterNewAddress(addr)
|
||||
if err != nil {
|
||||
return nil, address.Undef, xerrors.Errorf("register new address for actor: %w", err)
|
||||
}
|
||||
|
||||
if err := tree.SetActor(addr, &actr.Actor); err != nil {
|
||||
return nil, address.Undef, xerrors.Errorf("setting new actor for actor: %w", err)
|
||||
}
|
||||
}
|
||||
tree, err := state.LoadStateTree(s.cst, s.Root())
|
||||
|
||||
// store newState
|
||||
head, err := tree.Store.Put(context.Background(), actorState)
|
||||
if err != nil {
|
||||
return nil, address.Undef, err
|
||||
}
|
||||
actHead, err := tree.Store.Put(context.Background(), actorState)
|
||||
if err != nil {
|
||||
return nil, address.Undef, err
|
||||
}
|
||||
actr := &actorWrapper{types.Actor{
|
||||
|
||||
// create and store actor object
|
||||
a := types.Actor{
|
||||
Code: code,
|
||||
Head: actHead,
|
||||
Head: head,
|
||||
Balance: balance,
|
||||
}}
|
||||
|
||||
idAddr, err := tree.RegisterNewAddress(addr, &actr.Actor)
|
||||
if err != nil {
|
||||
return nil, address.Undef, xerrors.Errorf("register new address for actor: %w", err)
|
||||
}
|
||||
if err := tree.SetActor(idAddr, &a); err != nil {
|
||||
return nil, address.Undef, err
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
}}
|
||||
}
|
||||
|
||||
|
@ -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,21 +391,19 @@ 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
|
||||
}
|
||||
// refund unused gas
|
||||
refund := types.BigMul(types.NewInt(uint64(msg.GasLimit-gasUsed)), msg.GasPrice)
|
||||
if err := vm.transferFromGasHolder(msg.From, gasHolder, refund); err != nil {
|
||||
return nil, xerrors.Errorf("failed to refund gas")
|
||||
}
|
||||
}
|
||||
gasUsed = rt.gasUsed
|
||||
if gasUsed < 0 {
|
||||
gasUsed = 0
|
||||
}
|
||||
// refund unused gas
|
||||
refund := types.BigMul(types.NewInt(uint64(msg.GasLimit-gasUsed)), msg.GasPrice)
|
||||
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)))
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user