Skip to content

Commit

Permalink
Add an endpoint for precise circularting supply
Browse files Browse the repository at this point in the history
  • Loading branch information
arajasek committed Oct 3, 2020
1 parent efc1b24 commit bc72681
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 14 deletions.
3 changes: 3 additions & 0 deletions api/api_full.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,9 @@ type FullNode interface {

// StateCirculatingSupply returns the circulating supply of Filecoin at the given tipset
StateCirculatingSupply(context.Context, types.TipSetKey) (CirculatingSupply, error)
// TODO: Remove StateCirculatingSupply maybe?
// StateExactCirculatingSupply returns the exact circulating supply of Filecoin at the given tipset
StateExactCirculatingSupply(context.Context, types.TipSetKey) (abi.TokenAmount, error)
// StateNetworkVersion returns the network version at the given tipset
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)

Expand Down
5 changes: 5 additions & 0 deletions api/apistruct/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ type FullNodeStruct struct {
StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, 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"`
StateExactCirculatingSupply func(context.Context, types.TipSetKey) (abi.TokenAmount, 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 @@ -905,6 +906,10 @@ func (c *FullNodeStruct) StateCirculatingSupply(ctx context.Context, tsk types.T
return c.Internal.StateCirculatingSupply(ctx, tsk)
}

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

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

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

"github.com/filecoin-project/go-address"

"github.com/filecoin-project/go-state-types/abi"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
proof0 "github.com/filecoin-project/specs-actors/actors/runtime/proof"
Expand All @@ -12,6 +16,12 @@ import (
"github.com/filecoin-project/go-state-types/network"
)

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

type Version int

const (
Expand Down Expand Up @@ -41,3 +51,12 @@ func FromV0FilterEstimate(v0 smoothing0.FilterEstimate) FilterEstimate {
func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower {
return miner0.QAPowerForWeight(size, duration, dealWeight, verifiedWeight)
}

func makeAddress(addr string) address.Address {
ret, err := address.NewFromString(addr)
if err != nil {
panic(err)
}

return ret
}
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 @@ -171,3 +172,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 @@ -35,8 +35,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
21 changes: 9 additions & 12 deletions chain/stmgr/forks.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"encoding/binary"
"math"

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

multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"

"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
Expand Down Expand Up @@ -150,11 +152,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 @@ -180,7 +177,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 @@ -204,7 +201,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 @@ -255,7 +252,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 @@ -282,7 +279,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 @@ -302,7 +299,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 @@ -329,7 +326,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 @@ -345,7 +342,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
91 changes: 91 additions & 0 deletions chain/stmgr/stmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import (
"fmt"
"sync"

"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 @@ -1257,6 +1263,91 @@ func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.Cha
return csi.FilCirculating, nil
}

func (sm *StateManager) GetExactCirculatingSupply(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) {
circ := big.Zero()
unCirc := big.Zero()
err := st.ForEach(func(a address.Address, actor *types.Actor) error {
switch {
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 actor.IsAccountActor() || actor.IsPaymentChannelActor():
circ = big.Add(circ, actor.Balance)

case actor.IsStorageMinerActor():
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 actor.IsMultisigActor():
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 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 circ, nil
}

func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoch) network.Version {
// TODO: move hard fork epoch checks to a schedule defined in build/

Expand Down
29 changes: 29 additions & 0 deletions cli/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var stateCmd = &cli.Command{
stateListActorsCmd,
stateListMinersCmd,
stateCircSupplyCmd,
stateExactCircSupplyCmd,
stateSectorCmd,
stateGetActorCmd,
stateLookupIDCmd,
Expand Down Expand Up @@ -1638,6 +1639,34 @@ var stateCircSupplyCmd = &cli.Command{
},
}

// TODO: Remove stateCircSupplyCmd
var stateExactCircSupplyCmd = &cli.Command{
Name: "exact-circulating-supply",
Usage: "Get the exact current circulating supply of filecoin",
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()

ctx := ReqContext(cctx)

ts, err := LoadTipSet(ctx, cctx, api)
if err != nil {
return err
}

circ, err := api.StateExactCirculatingSupply(ctx, ts.Key())
if err != nil {
return err
}

fmt.Println("Circulating supply: ", types.FIL(circ))
return nil
},
}

var stateSectorCmd = &cli.Command{
Name: "sector",
Usage: "Get miner sector info",
Expand Down
24 changes: 24 additions & 0 deletions documentation/en/api-methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
* [StateCirculatingSupply](#StateCirculatingSupply)
* [StateCompute](#StateCompute)
* [StateDealProviderCollateralBounds](#StateDealProviderCollateralBounds)
* [StateExactCirculatingSupply](#StateExactCirculatingSupply)
* [StateGetActor](#StateGetActor)
* [StateGetReceipt](#StateGetReceipt)
* [StateListActors](#StateListActors)
Expand Down Expand Up @@ -3035,6 +3036,29 @@ Response:
}
```

### StateExactCirculatingSupply
TODO: Remove StateCirculatingSupply maybe?
StateExactCirculatingSupply returns the exact circulating supply of Filecoin at the given tipset


Perms: read

Inputs:
```json
[
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
{
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
}
]
]
```

Response: `"0"`

### StateGetActor
StateGetActor returns the indicated actor's nonce and balance.

Expand Down
13 changes: 13 additions & 0 deletions node/impl/full/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,19 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK
return a.StateManager.GetCirculatingSupplyDetailed(ctx, ts.Height(), sTree)
}

func (a *StateAPI) StateExactCirculatingSupply(ctx context.Context, tsk types.TipSetKey) (abi.TokenAmount, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
return types.EmptyInt, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}

sTree, err := a.stateForTs(ctx, ts)
if err != nil {
return types.EmptyInt, err
}
return a.StateManager.GetExactCirculatingSupply(ctx, ts.Height(), sTree)
}

func (a *StateAPI) StateNetworkVersion(ctx context.Context, tsk types.TipSetKey) (network.Version, error) {
ts, err := a.Chain.GetTipSetFromKey(tsk)
if err != nil {
Expand Down

0 comments on commit bc72681

Please sign in to comment.