Move GetCircSupply out of the vm, and into stmgr
This commit is contained in:
parent
5933e64de1
commit
fe2da35a45
@ -323,13 +323,13 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
|
||||
var sum abi.PaddedPieceSize
|
||||
|
||||
vmopt := vm.VMOpts{
|
||||
StateBase: stateroot,
|
||||
Epoch: 0,
|
||||
Rand: &fakeRand{},
|
||||
Bstore: cs.Blockstore(),
|
||||
Syscalls: mkFakedSigSyscalls(cs.VMSys()),
|
||||
VestedCalc: nil,
|
||||
BaseFee: types.NewInt(0),
|
||||
StateBase: stateroot,
|
||||
Epoch: 0,
|
||||
Rand: &fakeRand{},
|
||||
Bstore: cs.Blockstore(),
|
||||
Syscalls: mkFakedSigSyscalls(cs.VMSys()),
|
||||
CircSupplyCalc: nil,
|
||||
BaseFee: types.NewInt(0),
|
||||
}
|
||||
vm, err := vm.NewVM(&vmopt)
|
||||
if err != nil {
|
||||
|
@ -57,18 +57,18 @@ func mkFakedSigSyscalls(base vm.SyscallBuilder) vm.SyscallBuilder {
|
||||
}
|
||||
|
||||
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, miners []genesis.Miner) (cid.Cid, error) {
|
||||
vc := func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error) {
|
||||
csc := func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error) {
|
||||
return big.Zero(), nil
|
||||
}
|
||||
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: sroot,
|
||||
Epoch: 0,
|
||||
Rand: &fakeRand{},
|
||||
Bstore: cs.Blockstore(),
|
||||
Syscalls: mkFakedSigSyscalls(cs.VMSys()),
|
||||
VestedCalc: vc,
|
||||
BaseFee: types.NewInt(0),
|
||||
StateBase: sroot,
|
||||
Epoch: 0,
|
||||
Rand: &fakeRand{},
|
||||
Bstore: cs.Blockstore(),
|
||||
Syscalls: mkFakedSigSyscalls(cs.VMSys()),
|
||||
CircSupplyCalc: csc,
|
||||
BaseFee: types.NewInt(0),
|
||||
}
|
||||
|
||||
vm, err := vm.NewVM(vmopt)
|
||||
|
@ -23,13 +23,13 @@ func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate
|
||||
defer span.End()
|
||||
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: bstate,
|
||||
Epoch: bheight,
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
VestedCalc: sm.GetVestedFunds,
|
||||
BaseFee: types.NewInt(0),
|
||||
StateBase: bstate,
|
||||
Epoch: bheight,
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
||||
BaseFee: types.NewInt(0),
|
||||
}
|
||||
|
||||
vmi, err := vm.NewVM(vmopt)
|
||||
@ -124,13 +124,13 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
|
||||
}
|
||||
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: state,
|
||||
Epoch: ts.Height() + 1,
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
VestedCalc: sm.GetVestedFunds,
|
||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||
StateBase: state,
|
||||
Epoch: ts.Height() + 1,
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||
}
|
||||
vmi, err := vm.NewVM(vmopt)
|
||||
if err != nil {
|
||||
|
@ -3,6 +3,7 @@ package stmgr
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||
@ -148,13 +149,13 @@ type ExecCallback func(cid.Cid, *types.Message, *vm.ApplyRet) error
|
||||
func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEpoch, pstate cid.Cid, bms []store.BlockMessages, epoch abi.ChainEpoch, r vm.Rand, cb ExecCallback, baseFee abi.TokenAmount) (cid.Cid, cid.Cid, error) {
|
||||
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: pstate,
|
||||
Epoch: epoch,
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
VestedCalc: sm.GetVestedFunds,
|
||||
BaseFee: baseFee,
|
||||
StateBase: pstate,
|
||||
Epoch: epoch,
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
||||
BaseFee: baseFee,
|
||||
}
|
||||
|
||||
vmi, err := sm.newVM(vmopt)
|
||||
@ -873,7 +874,7 @@ func (sm *StateManager) setupGenesisActors(ctx context.Context) error {
|
||||
// GetVestedFunds returns all funds that have "left" actors that are in the genesis state:
|
||||
// - For Multisigs, it counts the actual amounts that have vested at the given epoch
|
||||
// - For Accounts, it counts max(currentBalance - genesisBalance, 0).
|
||||
func (sm *StateManager) GetVestedFunds(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) {
|
||||
func (sm *StateManager) GetFilVested(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) {
|
||||
sm.genesisMsigLk.Lock()
|
||||
defer sm.genesisMsigLk.Unlock()
|
||||
if sm.genesisMsigs == nil || sm.genesisActors == nil {
|
||||
@ -903,3 +904,84 @@ func (sm *StateManager) GetVestedFunds(ctx context.Context, height abi.ChainEpoc
|
||||
|
||||
return vf, nil
|
||||
}
|
||||
|
||||
func GetFilMined(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
|
||||
rew, err := st.GetActor(builtin.RewardActorAddr)
|
||||
if err != nil {
|
||||
return big.Zero(), xerrors.Errorf("failed to load reward actor state: %w", err)
|
||||
}
|
||||
|
||||
fm := types.BigSub(types.FromFil(build.FilAllocStorageMining), rew.Balance)
|
||||
if fm.LessThan(big.Zero()) {
|
||||
fm = big.Zero()
|
||||
}
|
||||
return fm, nil
|
||||
}
|
||||
|
||||
func GetFilLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
|
||||
mactor, err := st.GetActor(builtin.StorageMarketActorAddr)
|
||||
if err != nil {
|
||||
return big.Zero(), xerrors.Errorf("failed to load market actor: %w", err)
|
||||
}
|
||||
|
||||
var mst market.State
|
||||
if err := st.Store.Get(ctx, mactor.Head, &mst); err != nil {
|
||||
return big.Zero(), xerrors.Errorf("failed to load market state: %w", err)
|
||||
}
|
||||
|
||||
filMarketLocked := types.BigAdd(mst.TotalClientLockedCollateral, mst.TotalProviderLockedCollateral)
|
||||
filMarketLocked = types.BigAdd(filMarketLocked, mst.TotalClientStorageFee)
|
||||
|
||||
pactor, err := st.GetActor(builtin.StoragePowerActorAddr)
|
||||
if err != nil {
|
||||
return big.Zero(), xerrors.Errorf("failed to load power actor: %w", err)
|
||||
}
|
||||
|
||||
var pst power.State
|
||||
if err := st.Store.Get(ctx, pactor.Head, &pst); err != nil {
|
||||
return big.Zero(), xerrors.Errorf("failed to load power state: %w", err)
|
||||
}
|
||||
|
||||
return types.BigAdd(filMarketLocked, pst.TotalPledgeCollateral), nil
|
||||
}
|
||||
|
||||
func GetFilBurnt(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
|
||||
burnt, err := st.GetActor(builtin.BurntFundsActorAddr)
|
||||
if err != nil {
|
||||
return big.Zero(), xerrors.Errorf("failed to load burnt actor: %w", err)
|
||||
}
|
||||
|
||||
return burnt.Balance, nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.ChainEpoch, st *state.StateTree) (abi.TokenAmount, error) {
|
||||
filVested, err := sm.GetFilVested(ctx, height, st)
|
||||
if err != nil {
|
||||
return big.Zero(), xerrors.Errorf("failed to calculate filVested: %w", err)
|
||||
}
|
||||
|
||||
filMined, err := GetFilMined(ctx, st)
|
||||
if err != nil {
|
||||
return big.Zero(), xerrors.Errorf("failed to calculate filMined: %w", err)
|
||||
}
|
||||
|
||||
filBurnt, err := GetFilBurnt(ctx, st)
|
||||
if err != nil {
|
||||
return big.Zero(), xerrors.Errorf("failed to calculate filBurnt: %w", err)
|
||||
}
|
||||
|
||||
filLocked, err := GetFilLocked(ctx, st)
|
||||
if err != nil {
|
||||
return big.Zero(), xerrors.Errorf("failed to calculate filLocked: %w", err)
|
||||
}
|
||||
|
||||
ret := types.BigAdd(filVested, filMined)
|
||||
ret = types.BigSub(ret, filBurnt)
|
||||
ret = types.BigSub(ret, filLocked)
|
||||
|
||||
if ret.LessThan(big.Zero()) {
|
||||
ret = big.Zero()
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
@ -441,13 +441,13 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
|
||||
|
||||
r := store.NewChainRand(sm.cs, ts.Cids(), height)
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: base,
|
||||
Epoch: height,
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
VestedCalc: sm.GetVestedFunds,
|
||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||
StateBase: base,
|
||||
Epoch: height,
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||
}
|
||||
vmi, err := vm.NewVM(vmopt)
|
||||
if err != nil {
|
||||
@ -605,13 +605,13 @@ func (sm *StateManager) CirculatingSupply(ctx context.Context, ts *types.TipSet)
|
||||
|
||||
r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height())
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: st,
|
||||
Epoch: ts.Height(),
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
VestedCalc: sm.GetVestedFunds,
|
||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||
StateBase: st,
|
||||
Epoch: ts.Height(),
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
CircSupplyCalc: sm.GetCirculatingSupply,
|
||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||
}
|
||||
vmi, err := vm.NewVM(vmopt)
|
||||
if err != nil {
|
||||
@ -693,30 +693,3 @@ func MinerHasMinPower(ctx context.Context, sm *StateManager, addr address.Addres
|
||||
|
||||
return ps.MinerNominalPowerMeetsConsensusMinimum(sm.ChainStore().Store(ctx), addr)
|
||||
}
|
||||
|
||||
func GetCirculatingSupply(ctx context.Context, sm *StateManager, ts *types.TipSet) (abi.TokenAmount, error) {
|
||||
if ts == nil {
|
||||
ts = sm.cs.GetHeaviestTipSet()
|
||||
}
|
||||
|
||||
r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height())
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: ts.ParentState(),
|
||||
Epoch: ts.Height(),
|
||||
Rand: r,
|
||||
Bstore: sm.cs.Blockstore(),
|
||||
Syscalls: sm.cs.VMSys(),
|
||||
VestedCalc: sm.GetVestedFunds,
|
||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||
}
|
||||
vmi, err := vm.NewVM(vmopt)
|
||||
if err != nil {
|
||||
return abi.NewTokenAmount(0), err
|
||||
}
|
||||
|
||||
uvm := &vm.UnsafeVM{vmi}
|
||||
|
||||
rt := uvm.MakeRuntime(ctx, &types.Message{From: builtin.InitActorAddr, GasLimit: 10000000}, builtin.InitActorAddr, 0, 0, 0)
|
||||
|
||||
return rt.TotalFilCircSupply(), nil
|
||||
}
|
||||
|
@ -148,13 +148,13 @@ func (a *Applier) applyMessage(epoch abi.ChainEpoch, lm types.ChainMsg) (vtypes.
|
||||
base := a.stateWrapper.Root()
|
||||
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: base,
|
||||
Epoch: epoch,
|
||||
Rand: &vmRand{},
|
||||
Bstore: a.stateWrapper.bs,
|
||||
Syscalls: a.syscalls,
|
||||
VestedCalc: nil,
|
||||
BaseFee: abi.NewTokenAmount(100),
|
||||
StateBase: base,
|
||||
Epoch: epoch,
|
||||
Rand: &vmRand{},
|
||||
Bstore: a.stateWrapper.bs,
|
||||
Syscalls: a.syscalls,
|
||||
CircSupplyCalc: nil,
|
||||
BaseFee: abi.NewTokenAmount(100),
|
||||
}
|
||||
|
||||
lotusVM, err := vm.NewVM(vmopt)
|
||||
|
@ -8,13 +8,10 @@ import (
|
||||
gruntime "runtime"
|
||||
"time"
|
||||
|
||||
samarket "github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
sapower "github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
vmr "github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
@ -61,62 +58,12 @@ type Runtime struct {
|
||||
}
|
||||
|
||||
func (rt *Runtime) TotalFilCircSupply() abi.TokenAmount {
|
||||
|
||||
filVested, err := rt.vm.GetVestedFunds(rt.ctx)
|
||||
cs, err := rt.vm.GetCircSupply(rt.ctx)
|
||||
if err != nil {
|
||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get vested funds for computing total supply: %s", err)
|
||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get total circ supply: %s", err)
|
||||
}
|
||||
|
||||
rew, err := rt.state.GetActor(builtin.RewardActorAddr)
|
||||
if err != nil {
|
||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get reward actor for computing total supply: %s", err)
|
||||
}
|
||||
|
||||
filMined := types.BigSub(types.FromFil(build.FilAllocStorageMining), rew.Balance)
|
||||
if filMined.LessThan(big.Zero()) {
|
||||
filMined = big.Zero()
|
||||
}
|
||||
|
||||
burnt, err := rt.state.GetActor(builtin.BurntFundsActorAddr)
|
||||
if err != nil {
|
||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get reward actor for computing total supply: %s", err)
|
||||
}
|
||||
|
||||
filBurned := burnt.Balance
|
||||
|
||||
market, err := rt.state.GetActor(builtin.StorageMarketActorAddr)
|
||||
if err != nil {
|
||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get reward actor for computing total supply: %s", err)
|
||||
}
|
||||
|
||||
var mst samarket.State
|
||||
if err := rt.cst.Get(rt.ctx, market.Head, &mst); err != nil {
|
||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get market state: %s", err)
|
||||
}
|
||||
|
||||
filMarketLocked := types.BigAdd(mst.TotalClientLockedCollateral, mst.TotalProviderLockedCollateral)
|
||||
filMarketLocked = types.BigAdd(filMarketLocked, mst.TotalClientStorageFee)
|
||||
|
||||
power, err := rt.state.GetActor(builtin.StoragePowerActorAddr)
|
||||
if err != nil {
|
||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get reward actor for computing total supply: %s", err)
|
||||
}
|
||||
|
||||
var pst sapower.State
|
||||
if err := rt.cst.Get(rt.ctx, power.Head, &pst); err != nil {
|
||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get storage power state: %s", err)
|
||||
}
|
||||
|
||||
filLocked := types.BigAdd(filMarketLocked, pst.TotalPledgeCollateral)
|
||||
|
||||
ret := types.BigAdd(filVested, filMined)
|
||||
ret = types.BigSub(ret, filBurned)
|
||||
ret = types.BigSub(ret, filLocked)
|
||||
|
||||
if ret.LessThan(big.Zero()) {
|
||||
ret = big.Zero()
|
||||
}
|
||||
return ret
|
||||
return cs
|
||||
}
|
||||
|
||||
func (rt *Runtime) ResolveAddress(addr address.Address) (ret address.Address, ok bool) {
|
||||
|
@ -140,30 +140,30 @@ func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message, origin
|
||||
return vm.VM.makeRuntime(ctx, msg, origin, originNonce, usedGas, nac)
|
||||
}
|
||||
|
||||
type VestedCalculator func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error)
|
||||
type CircSupplyCalculator func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error)
|
||||
|
||||
type VM struct {
|
||||
cstate *state.StateTree
|
||||
base cid.Cid
|
||||
cst *cbor.BasicIpldStore
|
||||
buf *bufbstore.BufferedBS
|
||||
blockHeight abi.ChainEpoch
|
||||
inv *Invoker
|
||||
rand Rand
|
||||
vc VestedCalculator
|
||||
baseFee abi.TokenAmount
|
||||
cstate *state.StateTree
|
||||
base cid.Cid
|
||||
cst *cbor.BasicIpldStore
|
||||
buf *bufbstore.BufferedBS
|
||||
blockHeight abi.ChainEpoch
|
||||
inv *Invoker
|
||||
rand Rand
|
||||
circSupplyCalc CircSupplyCalculator
|
||||
baseFee abi.TokenAmount
|
||||
|
||||
Syscalls SyscallBuilder
|
||||
}
|
||||
|
||||
type VMOpts struct {
|
||||
StateBase cid.Cid
|
||||
Epoch abi.ChainEpoch
|
||||
Rand Rand
|
||||
Bstore bstore.Blockstore
|
||||
Syscalls SyscallBuilder
|
||||
VestedCalc VestedCalculator
|
||||
BaseFee abi.TokenAmount
|
||||
StateBase cid.Cid
|
||||
Epoch abi.ChainEpoch
|
||||
Rand Rand
|
||||
Bstore bstore.Blockstore
|
||||
Syscalls SyscallBuilder
|
||||
CircSupplyCalc CircSupplyCalculator
|
||||
BaseFee abi.TokenAmount
|
||||
}
|
||||
|
||||
func NewVM(opts *VMOpts) (*VM, error) {
|
||||
@ -175,16 +175,16 @@ func NewVM(opts *VMOpts) (*VM, error) {
|
||||
}
|
||||
|
||||
return &VM{
|
||||
cstate: state,
|
||||
base: opts.StateBase,
|
||||
cst: cst,
|
||||
buf: buf,
|
||||
blockHeight: opts.Epoch,
|
||||
inv: NewInvoker(),
|
||||
rand: opts.Rand, // TODO: Probably should be a syscall
|
||||
vc: opts.VestedCalc,
|
||||
Syscalls: opts.Syscalls,
|
||||
baseFee: opts.BaseFee,
|
||||
cstate: state,
|
||||
base: opts.StateBase,
|
||||
cst: cst,
|
||||
buf: buf,
|
||||
blockHeight: opts.Epoch,
|
||||
inv: NewInvoker(),
|
||||
rand: opts.Rand, // TODO: Probably should be a syscall
|
||||
circSupplyCalc: opts.CircSupplyCalc,
|
||||
Syscalls: opts.Syscalls,
|
||||
baseFee: opts.BaseFee,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -714,8 +714,8 @@ func (vm *VM) SetInvoker(i *Invoker) {
|
||||
vm.inv = i
|
||||
}
|
||||
|
||||
func (vm *VM) GetVestedFunds(ctx context.Context) (abi.TokenAmount, error) {
|
||||
return vm.vc(ctx, vm.blockHeight, vm.cstate)
|
||||
func (vm *VM) GetCircSupply(ctx context.Context) (abi.TokenAmount, error) {
|
||||
return vm.circSupplyCalc(ctx, vm.blockHeight, vm.cstate)
|
||||
}
|
||||
|
||||
func (vm *VM) incrementNonce(addr address.Address) error {
|
||||
|
@ -1193,5 +1193,13 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK
|
||||
return abi.TokenAmount{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
}
|
||||
|
||||
return stmgr.GetCirculatingSupply(ctx, a.StateManager, ts)
|
||||
st, _, err := a.StateManager.TipSetState(ctx, ts)
|
||||
if err != nil {
|
||||
return big.Zero(), err
|
||||
}
|
||||
|
||||
cst := cbor.NewCborStore(a.Chain.Blockstore())
|
||||
sTree, err := state.LoadStateTree(cst, st)
|
||||
|
||||
return a.StateManager.GetCirculatingSupply(ctx, ts.Height(), sTree)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user