fix some gas charge bugs, and make our new account actor creation follow GFC
This commit is contained in:
parent
08ca60cfa8
commit
09a46e5d80
@ -188,7 +188,7 @@ func (st *StateTree) ClearSnapshot() {
|
|||||||
st.snapshots = st.snapshots[:len(st.snapshots)-1]
|
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
|
var out address.Address
|
||||||
err := st.MutateActor(builtin.InitActorAddr, func(initact *types.Actor) error {
|
err := st.MutateActor(builtin.InitActorAddr, func(initact *types.Actor) error {
|
||||||
var ias init_.State
|
var ias init_.State
|
||||||
@ -214,10 +214,6 @@ func (st *StateTree) RegisterNewAddress(addr address.Address, act *types.Actor)
|
|||||||
return address.Undef, err
|
return address.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := st.SetActor(out, act); err != nil {
|
|
||||||
return address.Undef, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ func (s *StateWrapper) CreateActor(code cid.Cid, addr address.Address, balance a
|
|||||||
Balance: balance,
|
Balance: balance,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
idAddr, err := tree.RegisterNewAddress(addr, &actr.Actor)
|
idAddr, err := tree.RegisterNewAddress(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, address.Undef, xerrors.Errorf("register new address for actor: %w", err)
|
return nil, address.Undef, xerrors.Errorf("register new address for actor: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,10 @@ package vm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"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"
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
|
|
||||||
@ -27,25 +28,46 @@ func init() {
|
|||||||
var EmptyObjectCid cid.Cid
|
var EmptyObjectCid cid.Cid
|
||||||
|
|
||||||
// Creates account actors from only BLS/SECP256K1 addresses.
|
// Creates account actors from only BLS/SECP256K1 addresses.
|
||||||
func TryCreateAccountActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
|
func TryCreateAccountActor(ctx context.Context, rt *Runtime, addr address.Address) (*types.Actor, aerrors.ActorError) {
|
||||||
act, err := makeActor(st, addr)
|
addrID, err := rt.state.RegisterNewAddress(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := st.RegisterNewAddress(addr, act); err != nil {
|
|
||||||
return nil, aerrors.Escalate(err, "registering actor address")
|
return nil, aerrors.Escalate(err, "registering actor address")
|
||||||
}
|
}
|
||||||
|
rt.gasUsed += PricelistByEpoch(rt.height).OnCreateActor()
|
||||||
|
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
|
return act, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
|
func makeActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
|
||||||
switch addr.Protocol() {
|
switch addr.Protocol() {
|
||||||
case address.BLS:
|
case address.BLS:
|
||||||
return NewBLSAccountActor(st, addr)
|
return NewBLSAccountActor()
|
||||||
case address.SECP256K1:
|
case address.SECP256K1:
|
||||||
return NewSecp256k1AccountActor(st, addr)
|
return NewSecp256k1AccountActor()
|
||||||
case address.ID:
|
case address.ID:
|
||||||
return nil, aerrors.Newf(1, "no actor with given ID: %s", addr)
|
return nil, aerrors.Newf(1, "no actor with given ID: %s", addr)
|
||||||
case address.Actor:
|
case address.Actor:
|
||||||
@ -55,37 +77,21 @@ func makeActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBLSAccountActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
|
func NewBLSAccountActor() (*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")
|
|
||||||
}
|
|
||||||
|
|
||||||
nact := &types.Actor{
|
nact := &types.Actor{
|
||||||
Code: builtin.AccountActorCodeID,
|
Code: builtin.AccountActorCodeID,
|
||||||
Balance: types.NewInt(0),
|
Balance: types.NewInt(0),
|
||||||
Head: c,
|
Head: EmptyObjectCid,
|
||||||
}
|
}
|
||||||
|
|
||||||
return nact, nil
|
return nact, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSecp256k1AccountActor(st *state.StateTree, addr address.Address) (*types.Actor, aerrors.ActorError) {
|
func NewSecp256k1AccountActor() (*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")
|
|
||||||
}
|
|
||||||
|
|
||||||
nact := &types.Actor{
|
nact := &types.Actor{
|
||||||
Code: builtin.AccountActorCodeID,
|
Code: builtin.AccountActorCodeID,
|
||||||
Balance: types.NewInt(0),
|
Balance: types.NewInt(0),
|
||||||
Head: c,
|
Head: EmptyObjectCid,
|
||||||
}
|
}
|
||||||
|
|
||||||
return nact, nil
|
return nact, nil
|
||||||
|
@ -281,7 +281,7 @@ func (rs *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMars
|
|||||||
params = buf.Bytes()
|
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 != nil {
|
||||||
if err.IsFatal() {
|
if err.IsFatal() {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -292,7 +292,7 @@ func (rs *Runtime) Send(to address.Address, method abi.MethodNum, m vmr.CBORMars
|
|||||||
return &dumbWrapperType{ret}, 0
|
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")
|
ctx, span := trace.StartSpan(rt.ctx, "vmc.Send")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
if span.IsRecordingEvents() {
|
if span.IsRecordingEvents() {
|
||||||
@ -304,7 +304,7 @@ func (rt *Runtime) internalSend(to address.Address, method abi.MethodNum, value
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg := &types.Message{
|
msg := &types.Message{
|
||||||
From: rt.Message().Receiver(),
|
From: from,
|
||||||
To: to,
|
To: to,
|
||||||
Method: method,
|
Method: method,
|
||||||
Value: value,
|
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)
|
return nil, aerrors.Fatalf("snapshot failed: %s", err)
|
||||||
}
|
}
|
||||||
defer st.ClearSnapshot()
|
defer st.ClearSnapshot()
|
||||||
rt.ChargeGas(rt.Pricelist().OnMethodInvocation(value, method))
|
|
||||||
|
|
||||||
ret, errSend, subrt := rt.vm.send(ctx, msg, rt, 0)
|
ret, errSend, subrt := rt.vm.send(ctx, msg, rt, 0)
|
||||||
if errSend != nil {
|
if errSend != nil {
|
||||||
|
@ -211,25 +211,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)
|
toActor, err := st.GetActor(msg.To)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if xerrors.Is(err, init_.ErrAddressNotFound) {
|
if xerrors.Is(err, init_.ErrAddressNotFound) {
|
||||||
a, err := TryCreateAccountActor(st, msg.To)
|
a, err := TryCreateAccountActor(ctx, rt, msg.To)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, aerrors.Absorb(err, 1, "could not create account"), rt
|
return nil, aerrors.Absorb(err, 1, "could not create account"), rt
|
||||||
}
|
}
|
||||||
toActor = a
|
toActor = a
|
||||||
gasUsed += PricelistByEpoch(vm.blockHeight).OnCreateActor()
|
|
||||||
} else {
|
} else {
|
||||||
return nil, aerrors.Escalate(err, "getting actor"), rt
|
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 types.BigCmp(msg.Value, types.NewInt(0)) != 0 {
|
||||||
if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil {
|
if err := vm.transfer(msg.From, msg.To, msg.Value); err != nil {
|
||||||
return nil, aerrors.Absorb(err, 1, "failed to transfer funds"), nil
|
return nil, aerrors.Absorb(err, 1, "failed to transfer funds"), nil
|
||||||
|
Loading…
Reference in New Issue
Block a user