Merge pull request #2895 from filecoin-project/feat/fix-tests

Fix
This commit is contained in:
Łukasz Magiera 2020-08-07 18:37:40 +02:00 committed by GitHub
commit e0b86782e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 54 additions and 48 deletions

View File

@ -2,7 +2,7 @@ package build
import "github.com/filecoin-project/lotus/node/modules/dtypes" import "github.com/filecoin-project/lotus/node/modules/dtypes"
var DrandNetwork = DrandTestnet var DrandNetwork = DrandMainnet
func DrandConfig() dtypes.DrandConfig { func DrandConfig() dtypes.DrandConfig {
return DrandConfigs[DrandNetwork] return DrandConfigs[DrandNetwork]

View File

@ -20,9 +20,9 @@ func init() {
BuildType |= Build2k BuildType |= Build2k
} }
const BlockDelaySecs = uint64(2) const BlockDelaySecs = uint64(4)
const PropagationDelaySecs = uint64(3) const PropagationDelaySecs = uint64(1)
// SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after // SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after
// which the miner is slashed // which the miner is slashed

View File

@ -19,11 +19,15 @@ var (
UnixfsChunkSize = uint64(1 << 20) UnixfsChunkSize = uint64(1 << 20)
UnixfsLinksPerLevel = 1024 UnixfsLinksPerLevel = 1024
BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch) BlocksPerEpoch = uint64(builtin.ExpectedLeadersPerEpoch)
BlockMessageLimit = 512 BlockMessageLimit = 512
BlockGasLimit = int64(100_000_000_000) BlockGasLimit = int64(100_000_000_000)
BlockDelaySecs = uint64(builtin.EpochDurationSeconds) BlockGasTarget = int64(BlockGasLimit / 2)
PropagationDelaySecs = uint64(6) BaseFeeMaxChangeDenom = int64(8) // 12.5%
InitialBaseFee = int64(100e6)
MinimumBaseFee = int64(100)
BlockDelaySecs = uint64(builtin.EpochDurationSeconds)
PropagationDelaySecs = uint64(6)
AllowableClockDriftSecs = uint64(1) AllowableClockDriftSecs = uint64(1)

View File

@ -72,7 +72,7 @@ func (f *SlashFilter) MinedBlock(bh *types.BlockHeader, parentEpoch abi.ChainEpo
} }
if !found { if !found {
return xerrors.Errorf("produced block would trigger 'parent-grinding fault' consensus fault; bh: %s, expected parent: %s", bh.Cid(), parent) return xerrors.Errorf("produced block would trigger 'parent-grinding fault' consensus fault; miner: %s; bh: %s, expected parent: %s", bh.Miner, bh.Cid(), parent)
} }
} }
} }
@ -105,7 +105,7 @@ func checkFault(t ds.Datastore, key ds.Key, bh *types.BlockHeader, faultType str
return err return err
} }
return xerrors.Errorf("produced block would trigger '%s' consensus fault; bh: %s, other: %s", faultType, bh.Cid(), other) return xerrors.Errorf("produced block would trigger '%s' consensus fault; miner: %s; bh: %s, other: %s", faultType, bh.Miner, bh.Cid(), other)
} }
return nil return nil

View File

@ -74,7 +74,7 @@ func (mp *MessagePool) selectMessages(curTs, ts *types.TipSet) ([]*types.SignedM
return chains[i].Before(chains[j]) return chains[i].Before(chains[j])
}) })
if len(chains) != 0 && chains[0].gasPerf <= 0 { if len(chains) != 0 && chains[0].gasPerf < 0 {
log.Warnw("all messages in mpool have non-positive gas performance", "bestGasPerf", chains[0].gasPerf) log.Warnw("all messages in mpool have non-positive gas performance", "bestGasPerf", chains[0].gasPerf)
return nil, nil return nil, nil
} }
@ -87,14 +87,14 @@ func (mp *MessagePool) selectMessages(curTs, ts *types.TipSet) ([]*types.SignedM
last := len(chains) last := len(chains)
for i, chain := range chains { for i, chain := range chains {
// does it fit in the block? // does it fit in the block?
if chain.gasLimit <= gasLimit && chain.gasPerf > 0 { if chain.gasLimit <= gasLimit && chain.gasPerf >= 0 {
gasLimit -= chain.gasLimit gasLimit -= chain.gasLimit
result = append(result, chain.msgs...) result = append(result, chain.msgs...)
continue continue
} }
// did we run out of performing chains? // did we run out of performing chains?
if chain.gasPerf <= 0 { if chain.gasPerf < 0 {
break break
} }
@ -131,14 +131,14 @@ tailLoop:
continue continue
} }
// does it fit in the bock? // does it fit in the bock?
if chain.gasLimit <= gasLimit && chain.gasPerf > 0 { if chain.gasLimit <= gasLimit && chain.gasPerf >= 0 {
gasLimit -= chain.gasLimit gasLimit -= chain.gasLimit
result = append(result, chain.msgs...) result = append(result, chain.msgs...)
continue continue
} }
// if gasPerf <= 0 we have no more profitable chains // if gasPerf < 0 we have no more profitable chains
if chain.gasPerf <= 0 { if chain.gasPerf < 0 {
break tailLoop break tailLoop
} }

View File

@ -10,11 +10,11 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
address "github.com/filecoin-project/go-address" address "github.com/filecoin-project/go-address"
blocks "github.com/ipfs/go-block-format"
bserv "github.com/ipfs/go-blockservice"
miner "github.com/filecoin-project/specs-actors/actors/builtin/miner" miner "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
blocks "github.com/ipfs/go-block-format"
bserv "github.com/ipfs/go-blockservice"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2" logging "github.com/ipfs/go-log/v2"

View File

@ -1302,7 +1302,7 @@ loop:
} }
// base is the tipset in the candidate chain at the height equal to our known tipset height. // base is the tipset in the candidate chain at the height equal to our known tipset height.
if base := blockSet[len(blockSet)-1]; !types.CidArrsSubset(base.Parents().Cids(), known.Cids()) { if base := blockSet[len(blockSet)-1]; !types.CidArrsEqual(base.Parents().Cids(), known.Cids()) {
if base.Parents() == known.Parents() { if base.Parents() == known.Parents() {
// common case: receiving a block thats potentially part of the same tipset as our best block // common case: receiving a block thats potentially part of the same tipset as our best block
return blockSet, nil return blockSet, nil

View File

@ -193,7 +193,7 @@ func DumpActorState(code cid.Cid, b []byte) (interface{}, error) {
} }
if err := um.UnmarshalCBOR(bytes.NewReader(b)); err != nil { if err := um.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
return nil, err return nil, xerrors.Errorf("unmarshaling actor state: %w", err)
} }
return rv.Elem().Interface(), nil return rv.Elem().Interface(), nil

View File

@ -52,7 +52,7 @@ class Address extends React.Component {
balance = await this.props.client.call('Filecoin.WalletBalance', [this.props.addr]) balance = await this.props.client.call('Filecoin.WalletBalance', [this.props.addr])
actor = await this.props.client.call('Filecoin.StateGetActor', [this.props.addr, (this.props.ts || {}).Cids]) actor = await this.props.client.call('Filecoin.StateGetActor', [this.props.addr, (this.props.ts || {}).Cids])
actorInfo = await this.actorInfo(actor) actorInfo = await this.actorInfo(actor, this.props.addr)
if(this.props.miner) { if(this.props.miner) {
minerInfo = await this.props.client.call('Filecoin.StateMinerPower', [this.props.addr, (this.props.ts || {}).Cids]) minerInfo = await this.props.client.call('Filecoin.StateMinerPower', [this.props.addr, (this.props.ts || {}).Cids])
} }
@ -70,7 +70,7 @@ class Address extends React.Component {
this.props.mountWindow((onClose) => <State addr={this.props.addr} actor={this.state.actor} client={this.props.client} onClose={onClose} mountWindow={this.props.mountWindow}/>) this.props.mountWindow((onClose) => <State addr={this.props.addr} actor={this.state.actor} client={this.props.client} onClose={onClose} mountWindow={this.props.mountWindow}/>)
} }
async actorInfo(actor) { async actorInfo(actor, addr) {
const c = new CID(actor.Code['/']) const c = new CID(actor.Code['/'])
const mh = multihash.decode(c.multihash) // TODO: check identity const mh = multihash.decode(c.multihash) // TODO: check identity
@ -82,7 +82,7 @@ class Address extends React.Component {
let info = <span>({mh.digest.toString()}{method})</span> let info = <span>({mh.digest.toString()}{method})</span>
switch(mh.digest.toString()) { switch(mh.digest.toString()) {
case 'paych': case 'paych':
const actstate = await this.props.client.call('Filecoin.StateReadState', [actor, (this.props.ts || {}).Cids]) const actstate = await this.props.client.call('Filecoin.StateReadState', [addr, (this.props.ts || {}).Cids])
info = <span>({mh.digest.toString()}{method} to <Address nobalance={true} client={this.props.client} addr={actstate.State.To} mountWindow={this.props.mountWindow}/>)</span> info = <span>({mh.digest.toString()}{method} to <Address nobalance={true} client={this.props.client} addr={actstate.State.To} mountWindow={this.props.mountWindow}/>)</span>
} }
@ -97,10 +97,10 @@ class Address extends React.Component {
render() { render() {
let add20k = <span/> let add20k = <span/>
if(this.props.addN) { if(this.props.addN) {
add20k = <span>&nbsp;<a href="#" onClick={() => this.props.addN(this.props.addr, 200000)}>[+200k]</a></span> add20k = <span>&nbsp;<a href="#" onClick={() => this.props.addN(this.props.addr, 2e+18)}>[+2]</a></span>
if (this.props.add10k) { if (this.props.add10k) {
add20k = <span>{add20k}&nbsp;<a href="#" onClick={() => this.props.addN(this.props.addr, 2000000)}>[+2M]</a></span> add20k = <span>{add20k}&nbsp;<a href="#" onClick={() => this.props.addN(this.props.addr, 20e+18)}>[+20]</a></span>
add20k = <span>{add20k}&nbsp;<a href="#" onClick={() => this.props.addN(this.props.addr, 20000000)}>[+20M]</a></span> add20k = <span>{add20k}&nbsp;<a href="#" onClick={() => this.props.addN(this.props.addr, 200e+18)}>[+200]</a></span>
add20k = <span>{add20k}&nbsp;<a href="#" onClick={() => this.addColl()}>[<abbr title="min collateral">+C</abbr>]</a></span> add20k = <span>{add20k}&nbsp;<a href="#" onClick={() => this.addColl()}>[<abbr title="min collateral">+C</abbr>]</a></span>
} }
} }
@ -138,7 +138,7 @@ class Address extends React.Component {
let minerInfo = <span/> let minerInfo = <span/>
if(this.state.minerInfo) { if(this.state.minerInfo) {
minerInfo = <span>&nbsp;Power: {this.state.minerInfo.MinerPower} ({this.state.minerInfo.MinerPower/this.state.minerInfo.TotalPower*100}%)</span> minerInfo = <span>&nbsp;Power: {this.state.minerInfo.MinerPower.QualityAdjPower} ({this.state.minerInfo.MinerPower.QualityAdjPower/this.state.minerInfo.TotalPower.QualityAdjPower*100}%)</span>
} }
return <span data-tip data-for={this.props.addr}>{addr}{balance}{actInfo}{nonce}{add20k}{transfer}{minerInfo}</span> return <span data-tip data-for={this.props.addr}>{addr}{balance}{actInfo}{nonce}{add20k}{transfer}{minerInfo}</span>

View File

@ -70,6 +70,8 @@ class Block extends React.Component {
<span>&nbsp;<Address client={this.props.conn} short={true} addr="t01" mountWindow={this.props.mountWindow}/></span> <span>&nbsp;<Address client={this.props.conn} short={true} addr="t01" mountWindow={this.props.mountWindow}/></span>
<span>&nbsp;<Address client={this.props.conn} short={true} addr="t02" mountWindow={this.props.mountWindow}/></span> <span>&nbsp;<Address client={this.props.conn} short={true} addr="t02" mountWindow={this.props.mountWindow}/></span>
<span>&nbsp;<Address client={this.props.conn} short={true} addr="t03" mountWindow={this.props.mountWindow}/></span> <span>&nbsp;<Address client={this.props.conn} short={true} addr="t03" mountWindow={this.props.mountWindow}/></span>
<span>&nbsp;<Address client={this.props.conn} short={true} addr="t04" mountWindow={this.props.mountWindow}/></span>
<span>&nbsp;<Address client={this.props.conn} short={true} addr="t05" mountWindow={this.props.mountWindow}/></span>
<span>&nbsp;<Address client={this.props.conn} short={true} addr="t099" mountWindow={this.props.mountWindow}/></span> <span>&nbsp;<Address client={this.props.conn} short={true} addr="t099" mountWindow={this.props.mountWindow}/></span>
</div> </div>
<div>----</div> <div>----</div>

View File

@ -35,7 +35,7 @@ class NodeList extends React.Component {
async mountNode(node) { async mountNode(node) {
const token = await this.props.client.call('Pond.TokenFor', [node.ID]) const token = await this.props.client.call('Pond.TokenFor', [node.ID])
const client = new Client(`ws://127.0.0.1:${node.ApiPort}/rpc/v0?token=${token}`) const client = new Client(`ws://127.0.0.1:${node.APIPort}/rpc/v0?token=${token}`)
client.on('open', async () => { client.on('open', async () => {
const id = await client.call("Filecoin.ID", []) const id = await client.call("Filecoin.ID", [])

View File

@ -22,7 +22,7 @@ class State extends React.Component {
async componentDidMount() { async componentDidMount() {
const tipset = this.props.tipset || await this.props.client.call("Filecoin.ChainHead", []) const tipset = this.props.tipset || await this.props.client.call("Filecoin.ChainHead", [])
const actstate = await this.props.client.call('Filecoin.StateReadState', [this.props.actor, tipset.Cids]) const actstate = await this.props.client.call('Filecoin.StateReadState', [this.props.addr, tipset.Cids])
const c = new CID(this.props.actor.Code['/']) const c = new CID(this.props.actor.Code['/'])
const mh = multihash.decode(c.multihash) const mh = multihash.decode(c.multihash)
@ -80,7 +80,7 @@ class PowerState extends React.Component {
async componentDidMount() { async componentDidMount() {
const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props
const actors = await this.props.client.call("Filecoin.StateListMiners", [tipset.Cids]) const actors = await this.props.client.call("Filecoin.StateListMiners", [tipset.Cids])
const state = await this.props.client.call('Filecoin.StateReadState', [this.props.actor, tipset.Cids]) const state = await this.props.client.call('Filecoin.StateReadState', [this.props.addr, tipset.Cids])
this.setState({actors, state}) this.setState({actors, state})
} }
@ -107,7 +107,7 @@ class MarketState extends React.Component {
const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props
const participants = await this.props.client.call("Filecoin.StateMarketParticipants", [tipset.Cids]) const participants = await this.props.client.call("Filecoin.StateMarketParticipants", [tipset.Cids])
const deals = await this.props.client.call("Filecoin.StateMarketDeals", [tipset.Cids]) const deals = await this.props.client.call("Filecoin.StateMarketDeals", [tipset.Cids])
const state = await this.props.client.call('Filecoin.StateReadState', [this.props.actor, tipset.Cids]) const state = await this.props.client.call('Filecoin.StateReadState', [this.props.addr, tipset.Cids])
this.setState({participants, deals, nextDeal: state.State.NextDealID}) this.setState({participants, deals, nextDeal: state.State.NextDealID})
} }
@ -153,7 +153,7 @@ class MinerState extends React.Component {
async componentDidMount() { async componentDidMount() {
const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props
const state = await this.props.client.call('Filecoin.StateReadState', [this.props.actor, tipset.Cids]) const state = await this.props.client.call('Filecoin.StateReadState', [this.props.addr, tipset.Cids])
const sectorSize = await this.props.client.call("Filecoin.StateMinerSectorSize", [this.props.addr, tipset.Cids]) const sectorSize = await this.props.client.call("Filecoin.StateMinerSectorSize", [this.props.addr, tipset.Cids])
const worker = await this.props.client.call("Filecoin.StateMinerWorker", [this.props.addr, tipset.Cids]) const worker = await this.props.client.call("Filecoin.StateMinerWorker", [this.props.addr, tipset.Cids])

View File

@ -59,7 +59,7 @@ class StorageNode extends React.Component {
token: token, token: token,
})) }))
const client = new Client(`ws://127.0.0.1:${this.props.node.ApiPort}/rpc/v0?token=${token}`) const client = new Client(`ws://127.0.0.1:${this.props.node.APIPort}/rpc/v0?token=${token}`)
client.on('open', async () => { client.on('open', async () => {
this.setState(() => ({ this.setState(() => ({
state: stateConnected, state: stateConnected,
@ -88,8 +88,7 @@ class StorageNode extends React.Component {
const peers = await this.state.client.call("Filecoin.NetPeers", []) const peers = await this.state.client.call("Filecoin.NetPeers", [])
const actor = await this.state.client.call("Filecoin.ActorAddress", []) const actor = await this.state.client.call("Filecoin.ActorAddress", [])
const stActor = await this.props.fullConn.call('Filecoin.StateGetActor', [actor, null]) const actorState = await this.props.fullConn.call('Filecoin.StateReadState', [actor, null])
const actorState = await this.props.fullConn.call('Filecoin.StateReadState', [stActor, null])
this.setState({version: version, peers: peers.length, actor: actor, actorState: actorState}) this.setState({version: version, peers: peers.length, actor: actor, actorState: actorState})
await this.stagedList() await this.stagedList()
@ -98,7 +97,7 @@ class StorageNode extends React.Component {
async stagedList() { async stagedList() {
let stagedList = await this.state.client.call("Filecoin.SectorsList", []) let stagedList = await this.state.client.call("Filecoin.SectorsList", [])
let staged = await stagedList let staged = await stagedList
.map(sector => this.state.client.call("Filecoin.SectorsStatus", [sector])) .map(sector => this.state.client.call("Filecoin.SectorsStatus", [sector, false]))
.reduce(async (p, n) => [...await p, await n], Promise.resolve([])) .reduce(async (p, n) => [...await p, await n], Promise.resolve([]))
let statusCounts = staged.reduce((p, n) => p.map((e, i) => e + (i === n.State ? 1 : 0) ), [0, 0, 0, 0, 0]) let statusCounts = staged.reduce((p, n) => p.map((e, i) => e + (i === n.State ? 1 : 0) ), [0, 0, 0, 0, 0])

View File

@ -3,12 +3,6 @@ import { Buffer } from 'buffer'
import { Tagged } from 'borc' import { Tagged } from 'borc'
async function pushMessage(client, from, inmsg) { async function pushMessage(client, from, inmsg) {
if(!inmsg.GasLimit) {
inmsg.GasLimit = "10000"
}
if(!inmsg.GasPrice) {
inmsg.GasPrice = "0"
}
if(!inmsg.Params) { if(!inmsg.Params) {
inmsg.Params = "oA==" // 0b101_00000: empty cbor map: {} inmsg.Params = "oA==" // 0b101_00000: empty cbor map: {}
} }

View File

@ -20,6 +20,7 @@ import (
"github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/cmd/lotus-seed/seed" "github.com/filecoin-project/lotus/cmd/lotus-seed/seed"
"github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/genesis"
) )
@ -69,6 +70,7 @@ func (api *api) Spawn() (nodeInfo, error) {
Balance: types.FromFil(5000000), Balance: types.FromFil(5000000),
Meta: (&genesis.AccountMeta{Owner: genm.Owner}).ActorMeta(), Meta: (&genesis.AccountMeta{Owner: genm.Owner}).ActorMeta(),
}) })
template.VerifregRootKey = gen.DefaultVerifregRootkeyActor
tb, err := json.Marshal(&template) tb, err := json.Marshal(&template)
if err != nil { if err != nil {

View File

@ -161,6 +161,7 @@ func (m *Miner) mine(ctx context.Context) {
} }
if base != nil && base.TipSet.Height() == prebase.TipSet.Height() && base.NullRounds == prebase.NullRounds { if base != nil && base.TipSet.Height() == prebase.TipSet.Height() && base.NullRounds == prebase.NullRounds {
base = prebase
break break
} }
if base != nil { if base != nil {
@ -396,7 +397,11 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*types.BlockMsg,
tCreateBlock := build.Clock.Now() tCreateBlock := build.Clock.Now()
dur := tCreateBlock.Sub(start) dur := tCreateBlock.Sub(start)
log.Infow("mined new block", "cid", b.Cid(), "height", b.Header.Height, "took", dur) parentMiners := make([]address.Address, len(base.TipSet.Blocks()))
for i, header := range base.TipSet.Blocks() {
parentMiners[i] = header.Miner
}
log.Infow("mined new block", "cid", b.Cid(), "height", b.Header.Height, "miner", b.Header.Miner, "parents", parentMiners, "took", dur)
if dur > time.Second*time.Duration(build.BlockDelaySecs) { if dur > time.Second*time.Duration(build.BlockDelaySecs) {
log.Warnw("CAUTION: block production took longer than the block delay. Your computer may not be fast enough to keep up", log.Warnw("CAUTION: block production took longer than the block delay. Your computer may not be fast enough to keep up",
"tMinerBaseInfo ", tMBI.Sub(start), "tMinerBaseInfo ", tMBI.Sub(start),

View File

@ -125,7 +125,7 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
msg := *msgIn msg := *msgIn
msg.GasLimit = build.BlockGasLimit msg.GasLimit = build.BlockGasLimit
msg.GasFeeCap = types.NewInt(build.MinimumBaseFee + 1) msg.GasFeeCap = types.NewInt(uint64(build.MinimumBaseFee) + 1)
msg.GasPremium = types.NewInt(1) msg.GasPremium = types.NewInt(1)
currTs := a.Chain.GetHeaviestTipSet() currTs := a.Chain.GetHeaviestTipSet()

View File

@ -378,22 +378,22 @@ func (a *StateAPI) StateReadState(ctx context.Context, actor address.Address, ts
} }
state, err := a.stateForTs(ctx, ts) state, err := a.stateForTs(ctx, ts)
if err != nil { if err != nil {
return nil, err return nil, xerrors.Errorf("getting state for tipset: %w", err)
} }
act, err := state.GetActor(actor) act, err := state.GetActor(actor)
if err != nil { if err != nil {
return nil, err return nil, xerrors.Errorf("getting actor: %w", err)
} }
blk, err := state.Store.(*cbor.BasicIpldStore).Blocks.Get(act.Head) blk, err := state.Store.(*cbor.BasicIpldStore).Blocks.Get(act.Head)
if err != nil { if err != nil {
return nil, err return nil, xerrors.Errorf("getting actor head: %w", err)
} }
oif, err := vm.DumpActorState(act.Code, blk.RawData()) oif, err := vm.DumpActorState(act.Code, blk.RawData())
if err != nil { if err != nil {
return nil, err return nil, xerrors.Errorf("dumping actor state (a:%s): %w", actor, err)
} }
return &api.ActorState{ return &api.ActorState{