Skip to content

Commit

Permalink
Merge pull request #4148 from filecoin-project/asr/circ-supply
Browse files Browse the repository at this point in the history
Add a StateExactCirculatingSupply command
  • Loading branch information
arajasek committed Oct 12, 2020
2 parents 49155ac + 83624a8 commit 195d96c
Show file tree
Hide file tree
Showing 16 changed files with 236 additions and 65 deletions.
8 changes: 6 additions & 2 deletions api/api_full.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,12 @@ type FullNode interface {
// can issue. It takes the deal size and verified status as parameters.
StateDealProviderCollateralBounds(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (DealCollateralBounds, error)

// StateCirculatingSupply returns the circulating supply of Filecoin at the given tipset
StateCirculatingSupply(context.Context, types.TipSetKey) (CirculatingSupply, error)
// StateCirculatingSupply returns the exact circulating supply of Filecoin at the given tipset.
// This is not used anywhere in the protocol itself, and is only for external consumption.
StateCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error)
// StateVMCirculatingSupplyInternal returns an approximation of the circulating supply of Filecoin at the given tipset.
// This is the value reported by the runtime interface to actors code.
StateVMCirculatingSupplyInternal(context.Context, types.TipSetKey) (CirculatingSupply, error)
// StateNetworkVersion returns the network version at the given tipset
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)

Expand Down
9 changes: 7 additions & 2 deletions api/apistruct/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ type FullNodeStruct struct {
StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"`
StateVerifiedRegistryRootKey func(ctx context.Context, tsk types.TipSetKey) (address.Address, error) `perm:"read"`
StateDealProviderCollateralBounds func(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (api.DealCollateralBounds, error) `perm:"read"`
StateCirculatingSupply func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"`
StateCirculatingSupply func(context.Context, types.TipSetKey) (abi.TokenAmount, error) `perm:"read"`
StateVMCirculatingSupplyInternal func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"`
StateNetworkVersion func(context.Context, types.TipSetKey) (stnetwork.Version, error) `perm:"read"`

MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
Expand Down Expand Up @@ -963,10 +964,14 @@ func (c *FullNodeStruct) StateDealProviderCollateralBounds(ctx context.Context,
return c.Internal.StateDealProviderCollateralBounds(ctx, size, verified, tsk)
}

func (c *FullNodeStruct) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
func (c *FullNodeStruct) StateCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) {
return c.Internal.StateCirculatingSupply(ctx, tsk)
}

func (c *FullNodeStruct) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) {
return c.Internal.StateVMCirculatingSupplyInternal(ctx, tsk)
}

func (c *FullNodeStruct) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (stnetwork.Version, error) {
return c.Internal.StateNetworkVersion(ctx, tsk)
}
Expand Down
9 changes: 6 additions & 3 deletions chain/actors/builtin/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,28 @@ package builtin

import (
"github.com/filecoin-project/go-address"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"

builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"

"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"

"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"

builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing"
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing"
)

var SystemActorAddr = builtin0.SystemActorAddr
var BurntFundsActorAddr = builtin0.BurntFundsActorAddr
var CronActorAddr = builtin0.CronActorAddr
var SaftAddress = makeAddress("t0122")
var ReserveAddress = makeAddress("t090")
var RootVerifierAddress = makeAddress("t080")

Expand Down
5 changes: 5 additions & 0 deletions chain/actors/builtin/miner/miner.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package miner

import (
"github.com/filecoin-project/go-state-types/big"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
Expand Down Expand Up @@ -196,3 +197,7 @@ type LockedFunds struct {
InitialPledgeRequirement abi.TokenAmount
PreCommitDeposits abi.TokenAmount
}

func (lf LockedFunds) TotalLockedFunds() abi.TokenAmount {
return big.Add(lf.VestingFunds, big.Add(lf.InitialPledgeRequirement, lf.PreCommitDeposits))
}
12 changes: 10 additions & 2 deletions chain/actors/builtin/miner/v0.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,16 @@ type partition0 struct {
store adt.Store
}

func (s *state0) AvailableBalance(bal abi.TokenAmount) (abi.TokenAmount, error) {
return s.GetAvailableBalance(bal), nil
func (s *state0) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmount, err error) {
defer func() {
if r := recover(); r != nil {
err = xerrors.Errorf("failed to get available balance: %w", r)
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
available = s.GetAvailableBalance(bal)
return available, err
}

func (s *state0) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) {
Expand Down
12 changes: 10 additions & 2 deletions chain/actors/builtin/miner/v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,16 @@ type partition2 struct {
store adt.Store
}

func (s *state2) AvailableBalance(bal abi.TokenAmount) (abi.TokenAmount, error) {
return s.GetAvailableBalance(bal)
func (s *state2) AvailableBalance(bal abi.TokenAmount) (available abi.TokenAmount, err error) {
defer func() {
if r := recover(); r != nil {
err = xerrors.Errorf("failed to get available balance: %w", r)
available = abi.NewTokenAmount(0)
}
}()
// this panics if the miner doesnt have enough funds to cover their locked pledge
available, err = s.GetAvailableBalance(bal)
return available, err
}

func (s *state2) VestedFunds(epoch abi.ChainEpoch) (abi.TokenAmount, error) {
Expand Down
4 changes: 2 additions & 2 deletions chain/stmgr/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
Rand: store.NewChainRand(sm.cs, ts.Cids()),
Bstore: sm.cs.Blockstore(),
Syscalls: sm.cs.VMSys(),
CircSupplyCalc: sm.GetCirculatingSupply,
CircSupplyCalc: sm.GetVMCirculatingSupply,
NtwkVersion: sm.GetNtwkVersion,
BaseFee: types.NewInt(0),
}
Expand Down Expand Up @@ -174,7 +174,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
Rand: r,
Bstore: sm.cs.Blockstore(),
Syscalls: sm.cs.VMSys(),
CircSupplyCalc: sm.GetCirculatingSupply,
CircSupplyCalc: sm.GetVMCirculatingSupply,
NtwkVersion: sm.GetNtwkVersion,
BaseFee: ts.Blocks()[0].ParentBaseFee,
}
Expand Down
26 changes: 8 additions & 18 deletions chain/stmgr/forks.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,6 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
return cid.Undef, xerrors.Errorf("loading state tree failed: %w", err)
}

ReserveAddress, err := address.NewFromString("t090")
if err != nil {
return cid.Undef, xerrors.Errorf("failed to parse reserve address: %w", err)
}

tree, err := sm.StateTree(root)
if err != nil {
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
Expand All @@ -295,7 +290,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
if !sysAcc {
transfers = append(transfers, transfer{
From: addr,
To: ReserveAddress,
To: builtin.ReserveAddress,
Amt: act.Balance,
})
}
Expand All @@ -319,7 +314,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal

transfers = append(transfers, transfer{
From: addr,
To: ReserveAddress,
To: builtin.ReserveAddress,
Amt: available,
})
}
Expand Down Expand Up @@ -370,7 +365,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
nbalance := big.Min(prevBalance, AccountCap)
if nbalance.Sign() != 0 {
transfersBack = append(transfersBack, transfer{
From: ReserveAddress,
From: builtin.ReserveAddress,
To: addr,
Amt: nbalance,
})
Expand All @@ -397,7 +392,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal

mfunds := minerFundsAlloc(power, totalPower)
transfersBack = append(transfersBack, transfer{
From: ReserveAddress,
From: builtin.ReserveAddress,
To: minfo.Worker,
Amt: mfunds,
})
Expand All @@ -417,7 +412,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal

if lbsectors.Length() > 0 {
transfersBack = append(transfersBack, transfer{
From: ReserveAddress,
From: builtin.ReserveAddress,
To: minfo.Worker,
Amt: BaseMinerBalance,
})
Expand All @@ -444,7 +439,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
if err != nil {
return cid.Undef, xerrors.Errorf("failed to load burnt funds actor: %w", err)
}
if err := doTransfer(cb, tree, builtin0.BurntFundsActorAddr, ReserveAddress, burntAct.Balance); err != nil {
if err := doTransfer(cb, tree, builtin0.BurntFundsActorAddr, builtin.ReserveAddress, burntAct.Balance); err != nil {
return cid.Undef, xerrors.Errorf("failed to unburn funds: %w", err)
}

Expand All @@ -460,7 +455,7 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
}

difference := types.BigSub(DesiredReimbursementBalance, reimb.Balance)
if err := doTransfer(cb, tree, ReserveAddress, reimbAddr, difference); err != nil {
if err := doTransfer(cb, tree, builtin.ReserveAddress, reimbAddr, difference); err != nil {
return cid.Undef, xerrors.Errorf("failed to top up reimbursement account: %w", err)
}

Expand Down Expand Up @@ -545,12 +540,7 @@ func UpgradeRefuel(ctx context.Context, sm *StateManager, cb ExecCallback, root
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
}

addr, err := address.NewFromString("t0122")
if err != nil {
return cid.Undef, xerrors.Errorf("getting address: %w", err)
}

err = resetMultisigVesting(ctx, store, tree, addr, 0, 0, big.Zero())
err = resetMultisigVesting(ctx, store, tree, builtin.SaftAddress, 0, 0, big.Zero())
if err != nil {
return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err)
}
Expand Down
103 changes: 98 additions & 5 deletions chain/stmgr/stmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import (
"sync"

"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/verifreg"

_init "github.com/filecoin-project/lotus/chain/actors/builtin/init"

"github.com/filecoin-project/lotus/chain/actors/builtin/miner"

builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
Expand Down Expand Up @@ -229,7 +234,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
Rand: r,
Bstore: sm.cs.Blockstore(),
Syscalls: sm.cs.VMSys(),
CircSupplyCalc: sm.GetCirculatingSupply,
CircSupplyCalc: sm.GetVMCirculatingSupply,
NtwkVersion: sm.GetNtwkVersion,
BaseFee: baseFee,
}
Expand Down Expand Up @@ -1294,7 +1299,16 @@ func GetFilBurnt(ctx context.Context, st *state.StateTree) (abi.TokenAmount, err
return burnt.Balance, nil
}

func (sm *StateManager) GetCirculatingSupplyDetailed(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (api.CirculatingSupply, error) {
func (sm *StateManager) GetVMCirculatingSupply(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) {
cs, err := sm.GetVMCirculatingSupplyDetailed(ctx, height, st)
if err != nil {
return types.EmptyInt, err
}

return cs.FilCirculating, err
}

func (sm *StateManager) GetVMCirculatingSupplyDetailed(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (api.CirculatingSupply, error) {
sm.genesisMsigLk.Lock()
defer sm.genesisMsigLk.Unlock()
if sm.preIgnitionGenInfos == nil {
Expand Down Expand Up @@ -1357,12 +1371,91 @@ func (sm *StateManager) GetCirculatingSupplyDetailed(ctx context.Context, height
}

func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) {
csi, err := sm.GetCirculatingSupplyDetailed(ctx, height, st)
circ := big.Zero()
unCirc := big.Zero()
err := st.ForEach(func(a address.Address, actor *types.Actor) error {
switch {
case actor.Balance.IsZero():
// Do nothing for zero-balance actors
break
case a == _init.Address ||
a == reward.Address ||
a == verifreg.Address ||
// The power actor itself should never receive funds
a == power.Address ||
a == builtin.SystemActorAddr ||
a == builtin.CronActorAddr ||
a == builtin.BurntFundsActorAddr ||
a == builtin.SaftAddress ||
a == builtin.ReserveAddress:

unCirc = big.Add(unCirc, actor.Balance)

case a == market.Address:
mst, err := market.Load(sm.cs.Store(ctx), actor)
if err != nil {
return err
}

lb, err := mst.TotalLocked()
if err != nil {
return err
}

circ = big.Add(circ, big.Sub(actor.Balance, lb))
unCirc = big.Add(unCirc, lb)

case builtin.IsAccountActor(actor.Code) || builtin.IsPaymentChannelActor(actor.Code):
circ = big.Add(circ, actor.Balance)

case builtin.IsStorageMinerActor(actor.Code):
mst, err := miner.Load(sm.cs.Store(ctx), actor)
if err != nil {
return err
}

ab, err := mst.AvailableBalance(actor.Balance)

if err == nil {
circ = big.Add(circ, ab)
unCirc = big.Add(unCirc, big.Sub(actor.Balance, ab))
} else {
// Assume any error is because the miner state is "broken" (lower actor balance than locked funds)
// In this case, the actor's entire balance is considered "uncirculating"
unCirc = big.Add(unCirc, actor.Balance)
}

case builtin.IsMultisigActor(actor.Code):
mst, err := multisig.Load(sm.cs.Store(ctx), actor)
if err != nil {
return err
}

lb, err := mst.LockedBalance(height)
if err != nil {
return err
}

ab := big.Sub(actor.Balance, lb)
circ = big.Add(circ, big.Max(ab, big.Zero()))
unCirc = big.Add(unCirc, big.Min(actor.Balance, lb))
default:
return xerrors.Errorf("unexpected actor: %s", a)
}

return nil
})

if err != nil {
return big.Zero(), err
return types.EmptyInt, err
}

total := big.Add(circ, unCirc)
if !total.Equals(types.TotalFilecoinInt) {
return types.EmptyInt, xerrors.Errorf("total filecoin didn't add to expected amount: %s != %s", total, types.TotalFilecoinInt)
}

return csi.FilCirculating, nil
return circ, nil
}

func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoch) network.Version {
Expand Down
2 changes: 1 addition & 1 deletion chain/stmgr/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
Rand: r,
Bstore: sm.cs.Blockstore(),
Syscalls: sm.cs.VMSys(),
CircSupplyCalc: sm.GetCirculatingSupply,
CircSupplyCalc: sm.GetVMCirculatingSupply,
NtwkVersion: sm.GetNtwkVersion,
BaseFee: ts.Blocks()[0].ParentBaseFee,
}
Expand Down

0 comments on commit 195d96c

Please sign in to comment.