lotus/conformance/chaos/actor.go

306 lines
9.4 KiB
Go
Raw Normal View History

2020-09-08 20:50:25 +00:00
package chaos
import (
2022-06-14 15:00:51 +00:00
"github.com/ipfs/go-cid"
2020-09-08 20:50:25 +00:00
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
2020-09-08 20:50:25 +00:00
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/rt"
2020-10-08 01:09:33 +00:00
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
runtime2 "github.com/filecoin-project/specs-actors/v2/actors/runtime"
2022-06-14 15:00:51 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin"
2020-09-08 20:50:25 +00:00
)
//go:generate go run ./gen
// Actor is a chaos actor. It implements a variety of illegal behaviours that
// trigger violations of VM invariants. These behaviours are not found in
// production code, but are important to test that the VM constraints are
// properly enforced.
//
// The chaos actor is being incubated and its behaviour and ABI be standardised
// shortly. Its CID is ChaosActorCodeCID, and its singleton address is 98 (Address).
// It cannot be instantiated via the init actor, and its constructor panics.
//
// Test vectors relying on the chaos actor being deployed will carry selector
// "chaos_actor:true".
type Actor struct{}
// CallerValidationBranch is an enum used to select a branch in the
// CallerValidation method.
type CallerValidationBranch int64
const (
2020-09-14 11:41:00 +00:00
// CallerValidationBranchNone causes no caller validation to take place.
2020-09-08 20:50:25 +00:00
CallerValidationBranchNone CallerValidationBranch = iota
2020-09-14 11:41:00 +00:00
// CallerValidationBranchTwice causes Runtime.ValidateImmediateCallerAcceptAny to be called twice.
2020-09-08 20:50:25 +00:00
CallerValidationBranchTwice
2020-09-15 14:47:11 +00:00
// CallerValidationBranchIsAddress causes caller validation against CallerValidationArgs.Addrs.
CallerValidationBranchIsAddress
// CallerValidationBranchIsType causes caller validation against CallerValidationArgs.Types.
CallerValidationBranchIsType
2020-09-08 20:50:25 +00:00
)
// MutateStateBranch is an enum used to select the type of state mutation to attempt.
type MutateStateBranch int64
const (
// MutateInTransaction legally mutates state within a transaction.
MutateInTransaction MutateStateBranch = iota
// MutateReadonly ILLEGALLY mutates readonly state.
MutateReadonly
// MutateAfterTransaction ILLEGALLY mutates state after a transaction.
MutateAfterTransaction
)
const (
_ = 0 // skip zero iota value; first usage of iota gets 1.
MethodCallerValidation = builtin.MethodConstructor + iota
2020-09-08 20:50:25 +00:00
MethodCreateActor
MethodResolveAddress
// MethodDeleteActor is the identifier for the method that deletes this actor.
MethodDeleteActor
// MethodSend is the identifier for the method that sends a message to another actor.
MethodSend
// MethodMutateState is the identifier for the method that attempts to mutate
// a state value in the actor.
MethodMutateState
2020-09-10 11:06:00 +00:00
// MethodAbortWith is the identifier for the method that panics optionally with
2020-09-09 10:40:30 +00:00
// a passed exit code.
2020-09-10 11:06:00 +00:00
MethodAbortWith
// MethodInspectRuntime is the identifier for the method that returns the
// current runtime values.
MethodInspectRuntime
2020-11-17 22:17:08 +00:00
// MethodCreateState is the identifier for the method that creates the chaos actor's state.
MethodCreateState
2020-09-08 20:50:25 +00:00
)
// Exports defines the methods this actor exposes publicly.
func (a Actor) Exports() []interface{} {
return []interface{}{
builtin.MethodConstructor: a.Constructor,
MethodCallerValidation: a.CallerValidation,
MethodCreateActor: a.CreateActor,
MethodResolveAddress: a.ResolveAddress,
MethodDeleteActor: a.DeleteActor,
MethodSend: a.Send,
MethodMutateState: a.MutateState,
MethodAbortWith: a.AbortWith,
MethodInspectRuntime: a.InspectRuntime,
2020-11-17 22:17:08 +00:00
MethodCreateState: a.CreateState,
2020-09-08 20:50:25 +00:00
}
}
func (a Actor) Code() cid.Cid { return ChaosActorCodeCID }
func (a Actor) State() cbor.Er { return new(State) }
func (a Actor) IsSingleton() bool { return true }
var _ rt.VMActor = Actor{}
2020-09-08 20:50:25 +00:00
// SendArgs are the arguments for the Send method.
type SendArgs struct {
To address.Address
Value abi.TokenAmount
Method abi.MethodNum
Params []byte
}
// SendReturn is the return values for the Send method.
type SendReturn struct {
2020-10-08 01:09:33 +00:00
Return builtin2.CBORBytes
2020-09-08 20:50:25 +00:00
Code exitcode.ExitCode
}
// Send requests for this actor to send a message to an actor with the
// passed parameters.
2020-10-08 01:09:33 +00:00
func (a Actor) Send(rt runtime2.Runtime, args *SendArgs) *SendReturn {
2020-09-08 20:50:25 +00:00
rt.ValidateImmediateCallerAcceptAny()
2020-10-08 01:09:33 +00:00
var out builtin2.CBORBytes
code := rt.Send(
2020-09-08 20:50:25 +00:00
args.To,
args.Method,
2020-10-08 01:09:33 +00:00
builtin2.CBORBytes(args.Params),
2020-09-08 20:50:25 +00:00
args.Value,
&out,
2020-09-08 20:50:25 +00:00
)
return &SendReturn{
Return: out,
Code: code,
}
}
// Constructor will panic because the Chaos actor is a singleton.
2020-10-08 01:09:33 +00:00
func (a Actor) Constructor(_ runtime2.Runtime, _ *abi.EmptyValue) *abi.EmptyValue {
2020-09-08 20:50:25 +00:00
panic("constructor should not be called; the Chaos actor is a singleton actor")
}
2020-09-14 11:41:00 +00:00
// CallerValidationArgs are the arguments to Actor.CallerValidation.
type CallerValidationArgs struct {
Branch CallerValidationBranch
Addrs []address.Address
Types []cid.Cid
}
2020-09-08 20:50:25 +00:00
// CallerValidation violates VM call validation constraints.
//
2022-08-29 14:25:30 +00:00
// CallerValidationBranchNone performs no validation.
// CallerValidationBranchTwice validates twice.
// CallerValidationBranchIsAddress validates caller against CallerValidationArgs.Addrs.
// CallerValidationBranchIsType validates caller against CallerValidationArgs.Types.
2020-10-08 01:09:33 +00:00
func (a Actor) CallerValidation(rt runtime2.Runtime, args *CallerValidationArgs) *abi.EmptyValue {
2020-09-14 11:41:00 +00:00
switch args.Branch {
2020-09-08 20:50:25 +00:00
case CallerValidationBranchNone:
case CallerValidationBranchTwice:
rt.ValidateImmediateCallerAcceptAny()
rt.ValidateImmediateCallerAcceptAny()
2020-09-15 14:47:11 +00:00
case CallerValidationBranchIsAddress:
2020-09-14 11:41:00 +00:00
rt.ValidateImmediateCallerIs(args.Addrs...)
2020-09-15 14:47:11 +00:00
case CallerValidationBranchIsType:
2020-09-14 11:41:00 +00:00
rt.ValidateImmediateCallerType(args.Types...)
2020-09-08 20:50:25 +00:00
default:
panic("invalid branch passed to CallerValidation")
}
return nil
}
// CreateActorArgs are the arguments to CreateActor.
type CreateActorArgs struct {
// UndefActorCID instructs us to use cid.Undef; we can't pass cid.Undef
// in ActorCID because it doesn't serialize.
UndefActorCID bool
ActorCID cid.Cid
// UndefAddress is the same as UndefActorCID but for Address.
UndefAddress bool
Address address.Address
}
// CreateActor creates an actor with the supplied CID and Address.
2020-10-08 01:09:33 +00:00
func (a Actor) CreateActor(rt runtime2.Runtime, args *CreateActorArgs) *abi.EmptyValue {
2020-09-08 20:50:25 +00:00
rt.ValidateImmediateCallerAcceptAny()
var (
acid = args.ActorCID
addr = args.Address
)
if args.UndefActorCID {
acid = cid.Undef
}
if args.UndefAddress {
addr = address.Undef
}
rt.CreateActor(acid, addr)
return nil
}
// ResolveAddressResponse holds the response of a call to runtime.ResolveAddress
type ResolveAddressResponse struct {
Address address.Address
Success bool
}
2020-10-08 01:09:33 +00:00
func (a Actor) ResolveAddress(rt runtime2.Runtime, args *address.Address) *ResolveAddressResponse {
2020-09-08 20:50:25 +00:00
rt.ValidateImmediateCallerAcceptAny()
resolvedAddr, ok := rt.ResolveAddress(*args)
if !ok {
invalidAddr, _ := address.NewIDAddress(0)
resolvedAddr = invalidAddr
}
return &ResolveAddressResponse{resolvedAddr, ok}
}
// DeleteActor deletes the executing actor from the state tree, transferring any
// balance to beneficiary.
2020-10-08 01:09:33 +00:00
func (a Actor) DeleteActor(rt runtime2.Runtime, beneficiary *address.Address) *abi.EmptyValue {
2020-09-08 20:50:25 +00:00
rt.ValidateImmediateCallerAcceptAny()
rt.DeleteActor(*beneficiary)
return nil
}
// MutateStateArgs specify the value to set on the state and the way in which
// it should be attempted to be set.
type MutateStateArgs struct {
Value string
Branch MutateStateBranch
}
2020-11-17 22:17:08 +00:00
// CreateState creates the chaos actor's state
func (a Actor) CreateState(rt runtime2.Runtime, _ *abi.EmptyValue) *abi.EmptyValue {
rt.ValidateImmediateCallerAcceptAny()
rt.StateCreate(&State{})
return nil
}
2020-09-08 20:50:25 +00:00
// MutateState attempts to mutate a state value in the actor.
2020-10-08 01:09:33 +00:00
func (a Actor) MutateState(rt runtime2.Runtime, args *MutateStateArgs) *abi.EmptyValue {
2020-09-08 20:50:25 +00:00
rt.ValidateImmediateCallerAcceptAny()
var st State
switch args.Branch {
case MutateInTransaction:
rt.StateTransaction(&st, func() {
2020-09-08 20:50:25 +00:00
st.Value = args.Value
})
case MutateReadonly:
rt.StateReadonly(&st)
2020-09-08 20:50:25 +00:00
st.Value = args.Value
case MutateAfterTransaction:
rt.StateTransaction(&st, func() {
2020-09-08 20:50:25 +00:00
st.Value = args.Value + "-in"
})
st.Value = args.Value
default:
panic("unknown mutation type")
}
return nil
}
2020-09-09 10:40:30 +00:00
2020-09-10 11:03:13 +00:00
// AbortWithArgs are the arguments to the Actor.AbortWith method, specifying the
// exit code to (optionally) abort with and the message.
type AbortWithArgs struct {
Code exitcode.ExitCode
Message string
Uncontrolled bool
2020-09-09 10:40:30 +00:00
}
2020-09-10 11:03:13 +00:00
// AbortWith simply causes a panic with the passed exit code.
2020-10-08 01:09:33 +00:00
func (a Actor) AbortWith(rt runtime2.Runtime, args *AbortWithArgs) *abi.EmptyValue {
2020-09-10 11:03:13 +00:00
if args.Uncontrolled { // uncontrolled abort: directly panic
2020-09-09 10:40:30 +00:00
panic(args.Message)
}
rt.Abortf(args.Code, args.Message)
2020-09-09 10:40:30 +00:00
return nil
}
// InspectRuntimeReturn is the return value for the Actor.InspectRuntime method.
type InspectRuntimeReturn struct {
Caller address.Address
Receiver address.Address
ValueReceived abi.TokenAmount
CurrEpoch abi.ChainEpoch
CurrentBalance abi.TokenAmount
State State
}
// InspectRuntime returns a copy of the serializable values available in the Runtime.
2020-10-08 01:09:33 +00:00
func (a Actor) InspectRuntime(rt runtime2.Runtime, _ *abi.EmptyValue) *InspectRuntimeReturn {
rt.ValidateImmediateCallerAcceptAny()
var st State
rt.StateReadonly(&st)
return &InspectRuntimeReturn{
Caller: rt.Caller(),
Receiver: rt.Receiver(),
ValueReceived: rt.ValueReceived(),
CurrEpoch: rt.CurrEpoch(),
CurrentBalance: rt.CurrentBalance(),
State: st,
}
}