Merge branch 'next' into feat/cid-builder
This commit is contained in:
commit
b51e2a868b
@ -68,7 +68,11 @@ type FullNode interface {
|
|||||||
|
|
||||||
// ChainHasObj checks if a given CID exists in the chain blockstore.
|
// ChainHasObj checks if a given CID exists in the chain blockstore.
|
||||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||||
ChainStatObj(context.Context, cid.Cid, cid.Cid) (ObjStat, error)
|
|
||||||
|
// ChainStatObj returns statistics about the graph referenced by 'obj'.
|
||||||
|
// If 'base' is also specified, then the returned stat will be a diff
|
||||||
|
// between the two objects.
|
||||||
|
ChainStatObj(ctx context.Context, obj cid.Cid, base cid.Cid) (ObjStat, error)
|
||||||
|
|
||||||
// ChainSetHead forcefully sets current chain head. Use with caution.
|
// ChainSetHead forcefully sets current chain head. Use with caution.
|
||||||
ChainSetHead(context.Context, types.TipSetKey) error
|
ChainSetHead(context.Context, types.TipSetKey) error
|
||||||
@ -639,6 +643,7 @@ type MiningBaseInfo struct {
|
|||||||
SectorSize abi.SectorSize
|
SectorSize abi.SectorSize
|
||||||
PrevBeaconEntry types.BeaconEntry
|
PrevBeaconEntry types.BeaconEntry
|
||||||
BeaconEntries []types.BeaconEntry
|
BeaconEntries []types.BeaconEntry
|
||||||
|
HasMinPower bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlockTemplate struct {
|
type BlockTemplate struct {
|
||||||
|
@ -59,8 +59,8 @@ const WinningPoStSectorSetLookback = abi.ChainEpoch(10)
|
|||||||
// /////
|
// /////
|
||||||
// Devnet settings
|
// Devnet settings
|
||||||
|
|
||||||
const TotalFilecoin = uint64(2_000_000_000)
|
const FilBase = uint64(2_000_000_000)
|
||||||
const MiningRewardTotal = uint64(1_900_000_000)
|
const FilAllocStorageMining = uint64(1_100_000_000)
|
||||||
|
|
||||||
const FilecoinPrecision = uint64(1_000_000_000_000_000_000)
|
const FilecoinPrecision = uint64(1_000_000_000_000_000_000)
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ var InitialRewardBalance *big.Int
|
|||||||
// TODO: Move other important consts here
|
// TODO: Move other important consts here
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
InitialRewardBalance = big.NewInt(int64(MiningRewardTotal))
|
InitialRewardBalance = big.NewInt(int64(FilAllocStorageMining))
|
||||||
InitialRewardBalance = InitialRewardBalance.Mul(InitialRewardBalance, big.NewInt(int64(FilecoinPrecision)))
|
InitialRewardBalance = InitialRewardBalance.Mul(InitialRewardBalance, big.NewInt(int64(FilecoinPrecision)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,13 +49,13 @@ var (
|
|||||||
TicketRandomnessLookback = abi.ChainEpoch(1)
|
TicketRandomnessLookback = abi.ChainEpoch(1)
|
||||||
WinningPoStSectorSetLookback = abi.ChainEpoch(10)
|
WinningPoStSectorSetLookback = abi.ChainEpoch(10)
|
||||||
|
|
||||||
TotalFilecoin uint64 = 2_000_000_000
|
FilBase uint64 = 2_000_000_000
|
||||||
MiningRewardTotal uint64 = 1_400_000_000
|
FilAllocStorageMining uint64 = 1_400_000_000
|
||||||
|
|
||||||
FilecoinPrecision uint64 = 1_000_000_000_000_000_000
|
FilecoinPrecision uint64 = 1_000_000_000_000_000_000
|
||||||
|
|
||||||
InitialRewardBalance = func() *big.Int {
|
InitialRewardBalance = func() *big.Int {
|
||||||
v := big.NewInt(int64(MiningRewardTotal))
|
v := big.NewInt(int64(FilAllocStorageMining))
|
||||||
v = v.Mul(v, big.NewInt(int64(FilecoinPrecision)))
|
v = v.Mul(v, big.NewInt(int64(FilecoinPrecision)))
|
||||||
return v
|
return v
|
||||||
}()
|
}()
|
||||||
|
@ -321,7 +321,7 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
|
|||||||
verifNeeds := make(map[address.Address]abi.PaddedPieceSize)
|
verifNeeds := make(map[address.Address]abi.PaddedPieceSize)
|
||||||
var sum abi.PaddedPieceSize
|
var sum abi.PaddedPieceSize
|
||||||
|
|
||||||
vm, err := vm.NewVM(stateroot, 0, &fakeRand{}, cs.Blockstore(), mkFakedSigSyscalls(cs.VMSys()))
|
vm, err := vm.NewVM(stateroot, 0, &fakeRand{}, cs.Blockstore(), mkFakedSigSyscalls(cs.VMSys()), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
|
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,11 @@ func mkFakedSigSyscalls(base vm.SyscallBuilder) vm.SyscallBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, miners []genesis.Miner) (cid.Cid, error) {
|
func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, miners []genesis.Miner) (cid.Cid, error) {
|
||||||
vm, err := vm.NewVM(sroot, 0, &fakeRand{}, cs.Blockstore(), mkFakedSigSyscalls(cs.VMSys()))
|
vc := func(context.Context, abi.ChainEpoch) (abi.TokenAmount, error) {
|
||||||
|
return big.Zero(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vm, err := vm.NewVM(sroot, 0, &fakeRand{}, cs.Blockstore(), mkFakedSigSyscalls(cs.VMSys()), vc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
|
return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,8 @@ const futureDebug = false
|
|||||||
|
|
||||||
const ReplaceByFeeRatio = 1.25
|
const ReplaceByFeeRatio = 1.25
|
||||||
|
|
||||||
|
const repubMsgLimit = 5
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rbfNum = types.NewInt(uint64((ReplaceByFeeRatio - 1) * 256))
|
rbfNum = types.NewInt(uint64((ReplaceByFeeRatio - 1) * 256))
|
||||||
rbfDenom = types.NewInt(256)
|
rbfDenom = types.NewInt(256)
|
||||||
@ -269,6 +271,10 @@ func (mp *MessagePool) repubLocal() {
|
|||||||
log.Infow("republishing local messages", "n", len(outputMsgs))
|
log.Infow("republishing local messages", "n", len(outputMsgs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(outputMsgs) > repubMsgLimit {
|
||||||
|
outputMsgs = outputMsgs[:repubMsgLimit]
|
||||||
|
}
|
||||||
|
|
||||||
for _, msg := range outputMsgs {
|
for _, msg := range outputMsgs {
|
||||||
msgb, err := msg.Serialize()
|
msgb, err := msg.Serialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -22,7 +22,7 @@ func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate
|
|||||||
ctx, span := trace.StartSpan(ctx, "statemanager.CallRaw")
|
ctx, span := trace.StartSpan(ctx, "statemanager.CallRaw")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
vmi, err := vm.NewVM(bstate, bheight, r, sm.cs.Blockstore(), sm.cs.VMSys())
|
vmi, err := vm.NewVM(bstate, bheight, r, sm.cs.Blockstore(), sm.cs.VMSys(), sm.GetVestedFunds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
||||||
}
|
}
|
||||||
@ -106,7 +106,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
vmi, err := vm.NewVM(state, ts.Height(), r, sm.cs.Blockstore(), sm.cs.VMSys())
|
vmi, err := vm.NewVM(state, ts.Height(), r, sm.cs.Blockstore(), sm.cs.VMSys(), sm.GetVestedFunds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -151,8 +151,8 @@ func TestForkHeightTriggers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inv.Register(builtin.PaymentChannelActorCodeID, &testActor{}, &testActorState{})
|
inv.Register(builtin.PaymentChannelActorCodeID, &testActor{}, &testActorState{})
|
||||||
sm.SetVMConstructor(func(c cid.Cid, h abi.ChainEpoch, r vm.Rand, b blockstore.Blockstore, s vm.SyscallBuilder) (*vm.VM, error) {
|
sm.SetVMConstructor(func(c cid.Cid, h abi.ChainEpoch, r vm.Rand, b blockstore.Blockstore, s vm.SyscallBuilder, vc vm.VestedCalculator) (*vm.VM, error) {
|
||||||
nvm, err := vm.NewVM(c, h, r, b, s)
|
nvm, err := vm.NewVM(c, h, r, b, s, sm.GetVestedFunds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package stmgr
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
@ -37,10 +38,12 @@ var log = logging.Logger("statemgr")
|
|||||||
type StateManager struct {
|
type StateManager struct {
|
||||||
cs *store.ChainStore
|
cs *store.ChainStore
|
||||||
|
|
||||||
stCache map[string][]cid.Cid
|
stCache map[string][]cid.Cid
|
||||||
compWait map[string]chan struct{}
|
compWait map[string]chan struct{}
|
||||||
stlk sync.Mutex
|
stlk sync.Mutex
|
||||||
newVM func(cid.Cid, abi.ChainEpoch, vm.Rand, blockstore.Blockstore, vm.SyscallBuilder) (*vm.VM, error)
|
genesisMsigLk sync.Mutex
|
||||||
|
newVM func(cid.Cid, abi.ChainEpoch, vm.Rand, blockstore.Blockstore, vm.SyscallBuilder, vm.VestedCalculator) (*vm.VM, error)
|
||||||
|
genesisMsigs []multisig.State
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStateManager(cs *store.ChainStore) *StateManager {
|
func NewStateManager(cs *store.ChainStore) *StateManager {
|
||||||
@ -149,7 +152,7 @@ type BlockMessages struct {
|
|||||||
type ExecCallback func(cid.Cid, *types.Message, *vm.ApplyRet) error
|
type ExecCallback func(cid.Cid, *types.Message, *vm.ApplyRet) error
|
||||||
|
|
||||||
func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEpoch, pstate cid.Cid, bms []BlockMessages, epoch abi.ChainEpoch, r vm.Rand, cb ExecCallback) (cid.Cid, cid.Cid, error) {
|
func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEpoch, pstate cid.Cid, bms []BlockMessages, epoch abi.ChainEpoch, r vm.Rand, cb ExecCallback) (cid.Cid, cid.Cid, error) {
|
||||||
vmi, err := sm.newVM(pstate, epoch, r, sm.cs.Blockstore(), sm.cs.VMSys())
|
vmi, err := sm.newVM(pstate, epoch, r, sm.cs.Blockstore(), sm.cs.VMSys(), sm.GetVestedFunds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
|
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -763,6 +766,91 @@ func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *StateManager) SetVMConstructor(nvm func(cid.Cid, abi.ChainEpoch, vm.Rand, blockstore.Blockstore, vm.SyscallBuilder) (*vm.VM, error)) {
|
func (sm *StateManager) SetVMConstructor(nvm func(cid.Cid, abi.ChainEpoch, vm.Rand, blockstore.Blockstore, vm.SyscallBuilder, vm.VestedCalculator) (*vm.VM, error)) {
|
||||||
sm.newVM = nvm
|
sm.newVM = nvm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GenesisMsigEntry struct {
|
||||||
|
totalFunds abi.TokenAmount
|
||||||
|
unitVest abi.TokenAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *StateManager) setupGenesisMsigs(ctx context.Context) error {
|
||||||
|
gb, err := sm.cs.GetGenesis()
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting genesis block: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gts, err := types.NewTipSet([]*types.BlockHeader{gb})
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting genesis tipset: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
st, _, err := sm.TipSetState(ctx, gts)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting genesis tipset state: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := adt.AsMap(sm.cs.Store(ctx), st)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting genesis actors: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalsByEpoch := make(map[abi.ChainEpoch]abi.TokenAmount)
|
||||||
|
var act types.Actor
|
||||||
|
err = r.ForEach(&act, func(k string) error {
|
||||||
|
if act.Code == builtin.MultisigActorCodeID {
|
||||||
|
var s multisig.State
|
||||||
|
err := sm.cs.Store(ctx).Get(ctx, act.Head, &s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.StartEpoch != 0 {
|
||||||
|
return xerrors.New("genesis multisig doesn't start vesting at epoch 0!")
|
||||||
|
}
|
||||||
|
|
||||||
|
ot, f := totalsByEpoch[s.UnlockDuration]
|
||||||
|
if f {
|
||||||
|
totalsByEpoch[s.UnlockDuration] = big.Add(ot, s.InitialBalance)
|
||||||
|
} else {
|
||||||
|
totalsByEpoch[s.UnlockDuration] = s.InitialBalance
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("error setting up composite genesis multisigs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sm.genesisMsigs = make([]multisig.State, 0, len(totalsByEpoch))
|
||||||
|
for k, v := range totalsByEpoch {
|
||||||
|
ns := multisig.State{
|
||||||
|
InitialBalance: v,
|
||||||
|
UnlockDuration: k,
|
||||||
|
PendingTxns: cid.Undef,
|
||||||
|
}
|
||||||
|
sm.genesisMsigs = append(sm.genesisMsigs, ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *StateManager) GetVestedFunds(ctx context.Context, height abi.ChainEpoch) (abi.TokenAmount, error) {
|
||||||
|
sm.genesisMsigLk.Lock()
|
||||||
|
defer sm.genesisMsigLk.Unlock()
|
||||||
|
if sm.genesisMsigs == nil {
|
||||||
|
err := sm.setupGenesisMsigs(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return big.Zero(), xerrors.Errorf("failed to setup genesis msig entries: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vf := big.Zero()
|
||||||
|
for _, v := range sm.genesisMsigs {
|
||||||
|
au := big.Sub(v.InitialBalance, v.AmountLocked(height))
|
||||||
|
vf = big.Add(vf, au)
|
||||||
|
}
|
||||||
|
return vf, nil
|
||||||
|
}
|
||||||
|
@ -440,7 +440,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
|
|||||||
}
|
}
|
||||||
|
|
||||||
r := store.NewChainRand(sm.cs, ts.Cids(), height)
|
r := store.NewChainRand(sm.cs, ts.Cids(), height)
|
||||||
vmi, err := vm.NewVM(base, height, r, sm.cs.Blockstore(), sm.cs.VMSys())
|
vmi, err := vm.NewVM(base, height, r, sm.cs.Blockstore(), sm.cs.VMSys(), sm.GetVestedFunds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, nil, err
|
return cid.Undef, nil, err
|
||||||
}
|
}
|
||||||
@ -567,6 +567,11 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcn beacon.RandomBe
|
|||||||
return nil, xerrors.Errorf("resolving worker address: %w", err)
|
return nil, xerrors.Errorf("resolving worker address: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hmp, err := MinerHasMinPower(ctx, sm, maddr, lbts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("determining if miner has min power failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return &api.MiningBaseInfo{
|
return &api.MiningBaseInfo{
|
||||||
MinerPower: mpow.QualityAdjPower,
|
MinerPower: mpow.QualityAdjPower,
|
||||||
NetworkPower: tpow.QualityAdjPower,
|
NetworkPower: tpow.QualityAdjPower,
|
||||||
@ -575,6 +580,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcn beacon.RandomBe
|
|||||||
SectorSize: info.SectorSize,
|
SectorSize: info.SectorSize,
|
||||||
PrevBeaconEntry: *prev,
|
PrevBeaconEntry: *prev,
|
||||||
BeaconEntries: entries,
|
BeaconEntries: entries,
|
||||||
|
HasMinPower: hmp,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,7 +595,7 @@ func (sm *StateManager) CirculatingSupply(ctx context.Context, ts *types.TipSet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height())
|
r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height())
|
||||||
vmi, err := vm.NewVM(st, ts.Height(), r, sm.cs.Blockstore(), sm.cs.VMSys())
|
vmi, err := vm.NewVM(st, ts.Height(), r, sm.cs.Blockstore(), sm.cs.VMSys(), sm.GetVestedFunds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return big.Zero(), err
|
return big.Zero(), err
|
||||||
}
|
}
|
||||||
@ -659,3 +665,13 @@ func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, me
|
|||||||
m := MethodsMap[act.Code][method]
|
m := MethodsMap[act.Code][method]
|
||||||
return reflect.New(m.Ret.Elem()).Interface().(cbg.CBORUnmarshaler), nil
|
return reflect.New(m.Ret.Elem()).Interface().(cbg.CBORUnmarshaler), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MinerHasMinPower(ctx context.Context, sm *StateManager, addr address.Address, ts *types.TipSet) (bool, error) {
|
||||||
|
var ps power.State
|
||||||
|
_, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &ps, ts)
|
||||||
|
if err != nil {
|
||||||
|
return false, xerrors.Errorf("loading power actor state: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ps.MinerNominalPowerMeetsConsensusMinimum(sm.ChainStore().Store(ctx), addr)
|
||||||
|
}
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/state"
|
"github.com/filecoin-project/lotus/chain/state"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/vm"
|
|
||||||
big2 "github.com/filecoin-project/specs-actors/actors/abi/big"
|
big2 "github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||||
@ -73,44 +72,3 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn
|
|||||||
|
|
||||||
return types.BigInt{Int: out}, nil
|
return types.BigInt{Int: out}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: dedupe with state manager
|
|
||||||
func (cs *ChainStore) call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
|
|
||||||
bstate := ts.ParentState()
|
|
||||||
|
|
||||||
r := NewChainRand(cs, ts.Cids(), ts.Height())
|
|
||||||
|
|
||||||
vmi, err := vm.NewVM(bstate, ts.Height(), r, cs.bs, cs.vmcalls)
|
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if msg.GasLimit == 0 {
|
|
||||||
msg.GasLimit = 10000000000
|
|
||||||
}
|
|
||||||
if msg.GasPrice == types.EmptyInt {
|
|
||||||
msg.GasPrice = types.NewInt(0)
|
|
||||||
}
|
|
||||||
if msg.Value == types.EmptyInt {
|
|
||||||
msg.Value = types.NewInt(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fromActor, err := vmi.StateTree().GetActor(msg.From)
|
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("call raw get actor: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.Nonce = fromActor.Nonce
|
|
||||||
|
|
||||||
// TODO: maybe just use the invoker directly?
|
|
||||||
// TODO: use signed message length for secp messages
|
|
||||||
ret, err := vmi.ApplyMessage(ctx, msg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("apply message failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ret.ActorErr != nil {
|
|
||||||
log.Warnf("chain call failed: %s", ret.ActorErr)
|
|
||||||
}
|
|
||||||
return &ret.MessageReceipt, nil
|
|
||||||
}
|
|
||||||
|
@ -190,14 +190,14 @@ func (bv *BlockValidator) Validate(ctx context.Context, pid peer.ID, msg *pubsub
|
|||||||
// if we can't find it, we check whether we are (near) synced in the chain.
|
// if we can't find it, we check whether we are (near) synced in the chain.
|
||||||
// if we are not synced we cannot validate the block and we must ignore it.
|
// if we are not synced we cannot validate the block and we must ignore it.
|
||||||
// if we are synced and the miner is unknown, then the block is rejcected.
|
// if we are synced and the miner is unknown, then the block is rejcected.
|
||||||
key, err := bv.getMinerWorkerKey(ctx, blk)
|
key, err := bv.checkPowerAndGetWorkerKey(ctx, blk.Header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if bv.isChainNearSynced() {
|
if bv.isChainNearSynced() {
|
||||||
log.Warnf("received block message from unknown miner over pubsub; rejecting message")
|
log.Warnf("received block from unknown miner or miner that doesn't meet min power over pubsub; rejecting message")
|
||||||
recordFailure("unknown_miner")
|
recordFailure("unknown_miner")
|
||||||
return pubsub.ValidationReject
|
return pubsub.ValidationReject
|
||||||
} else {
|
} else {
|
||||||
log.Warnf("cannot validate block message; unknown miner in unsynced chain")
|
log.Warnf("cannot validate block message; unknown miner or miner that doesn't meet min power in unsynced chain")
|
||||||
return pubsub.ValidationIgnore
|
return pubsub.ValidationIgnore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,60 +282,83 @@ func (bv *BlockValidator) validateMsgMeta(ctx context.Context, msg *types.BlockM
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bv *BlockValidator) getMinerWorkerKey(ctx context.Context, msg *types.BlockMsg) (address.Address, error) {
|
func (bv *BlockValidator) checkPowerAndGetWorkerKey(ctx context.Context, bh *types.BlockHeader) (address.Address, error) {
|
||||||
addr := msg.Header.Miner
|
addr := bh.Miner
|
||||||
|
|
||||||
bv.mx.Lock()
|
bv.mx.Lock()
|
||||||
key, ok := bv.keycache[addr.String()]
|
key, ok := bv.keycache[addr.String()]
|
||||||
bv.mx.Unlock()
|
bv.mx.Unlock()
|
||||||
if ok {
|
if !ok {
|
||||||
return key, nil
|
// TODO I have a feeling all this can be simplified by cleverer DI to use the API
|
||||||
|
ts := bv.chain.GetHeaviestTipSet()
|
||||||
|
st, _, err := bv.stmgr.TipSetState(ctx, ts)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, err
|
||||||
|
}
|
||||||
|
buf := bufbstore.NewBufferedBstore(bv.chain.Blockstore())
|
||||||
|
cst := cbor.NewCborStore(buf)
|
||||||
|
state, err := state.LoadStateTree(cst, st)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, err
|
||||||
|
}
|
||||||
|
act, err := state.GetActor(addr)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
blk, err := bv.chain.Blockstore().Get(act.Head)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, err
|
||||||
|
}
|
||||||
|
aso := blk.RawData()
|
||||||
|
|
||||||
|
var mst miner.State
|
||||||
|
err = mst.UnmarshalCBOR(bytes.NewReader(aso))
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := mst.GetInfo(adt.WrapStore(ctx, cst))
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
worker := info.Worker
|
||||||
|
key, err = bv.stmgr.ResolveToKeyAddress(ctx, worker, ts)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bv.mx.Lock()
|
||||||
|
bv.keycache[addr.String()] = key
|
||||||
|
bv.mx.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO I have a feeling all this can be simplified by cleverer DI to use the API
|
// we check that the miner met the minimum power at the lookback tipset
|
||||||
ts := bv.chain.GetHeaviestTipSet()
|
|
||||||
st, _, err := bv.stmgr.TipSetState(ctx, ts)
|
baseTs, err := bv.stmgr.ChainStore().LoadTipSet(types.NewTipSetKey(bh.Parents...))
|
||||||
if err != nil {
|
|
||||||
return address.Undef, err
|
|
||||||
}
|
|
||||||
buf := bufbstore.NewBufferedBstore(bv.chain.Blockstore())
|
|
||||||
cst := cbor.NewCborStore(buf)
|
|
||||||
state, err := state.LoadStateTree(cst, st)
|
|
||||||
if err != nil {
|
|
||||||
return address.Undef, err
|
|
||||||
}
|
|
||||||
act, err := state.GetActor(addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Warnf("failed to load parent tipset of incoming block")
|
||||||
return address.Undef, err
|
return address.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
blk, err := bv.chain.Blockstore().Get(act.Head)
|
lbts, err := stmgr.GetLookbackTipSetForRound(ctx, bv.stmgr, baseTs, bh.Height)
|
||||||
if err != nil {
|
|
||||||
return address.Undef, err
|
|
||||||
}
|
|
||||||
aso := blk.RawData()
|
|
||||||
|
|
||||||
var mst miner.State
|
|
||||||
err = mst.UnmarshalCBOR(bytes.NewReader(aso))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Warnf("failed to load lookback tipset for incoming block")
|
||||||
return address.Undef, err
|
return address.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := mst.GetInfo(adt.WrapStore(ctx, cst))
|
hmp, err := stmgr.MinerHasMinPower(ctx, bv.stmgr, bh.Miner, lbts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Warnf("failed to determine if incoming block's miner has minimum power")
|
||||||
return address.Undef, err
|
return address.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
worker := info.Worker
|
if !hmp {
|
||||||
key, err = bv.stmgr.ResolveToKeyAddress(ctx, worker, ts)
|
log.Warnf("incoming block's miner does not have minimum power")
|
||||||
if err != nil {
|
return address.Undef, xerrors.New("incoming block's miner does not have minimum power")
|
||||||
return address.Undef, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bv.mx.Lock()
|
|
||||||
bv.keycache[addr.String()] = key
|
|
||||||
bv.mx.Unlock()
|
|
||||||
|
|
||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,6 +738,15 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) (er
|
|||||||
return xerrors.Errorf("block is not claiming to be a winner")
|
return xerrors.Errorf("block is not claiming to be a winner")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hp, err := stmgr.MinerHasMinPower(ctx, syncer.sm, h.Miner, lbts)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("determining if miner has min power failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hp {
|
||||||
|
return xerrors.New("block's miner does not meet minimum power threshold")
|
||||||
|
}
|
||||||
|
|
||||||
rBeacon := *prevBeacon
|
rBeacon := *prevBeacon
|
||||||
if len(h.BeaconEntries) != 0 {
|
if len(h.BeaconEntries) != 0 {
|
||||||
rBeacon = h.BeaconEntries[len(h.BeaconEntries)-1]
|
rBeacon = h.BeaconEntries[len(h.BeaconEntries)-1]
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
const BigIntMaxSerializedLen = 128 // is this big enough? or too big?
|
const BigIntMaxSerializedLen = 128 // is this big enough? or too big?
|
||||||
|
|
||||||
var TotalFilecoinInt = FromFil(build.TotalFilecoin)
|
var TotalFilecoinInt = FromFil(build.FilBase)
|
||||||
|
|
||||||
var EmptyInt = BigInt{}
|
var EmptyInt = BigInt{}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ func (a *Applier) applyMessage(epoch abi.ChainEpoch, lm types.ChainMsg) (vtypes.
|
|||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
base := a.stateWrapper.Root()
|
base := a.stateWrapper.Root()
|
||||||
|
|
||||||
lotusVM, err := vm.NewVM(base, epoch, &vmRand{}, a.stateWrapper.bs, a.syscalls)
|
lotusVM, err := vm.NewVM(base, epoch, &vmRand{}, a.stateWrapper.bs, a.syscalls, nil)
|
||||||
// need to modify the VM invoker to add the puppet actor
|
// need to modify the VM invoker to add the puppet actor
|
||||||
chainValInvoker := vm.NewInvoker()
|
chainValInvoker := vm.NewInvoker()
|
||||||
chainValInvoker.Register(puppet.PuppetActorCodeID, puppet.Actor{}, puppet.State{})
|
chainValInvoker.Register(puppet.PuppetActorCodeID, puppet.Actor{}, puppet.State{})
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
samarket "github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||||
gruntime "runtime"
|
gruntime "runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -60,38 +61,62 @@ type Runtime struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rt *Runtime) TotalFilCircSupply() abi.TokenAmount {
|
func (rt *Runtime) TotalFilCircSupply() abi.TokenAmount {
|
||||||
total := types.FromFil(build.TotalFilecoin)
|
|
||||||
|
filVested, err := rt.vm.GetVestedFunds(rt.ctx)
|
||||||
|
if err != nil {
|
||||||
|
rt.Abortf(exitcode.ErrIllegalState, "failed to get vested funds for computing total supply: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
rew, err := rt.state.GetActor(builtin.RewardActorAddr)
|
rew, err := rt.state.GetActor(builtin.RewardActorAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get reward actor for computing total supply: %s", err)
|
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)
|
burnt, err := rt.state.GetActor(builtin.BurntFundsActorAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get reward actor for computing total supply: %s", err)
|
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)
|
market, err := rt.state.GetActor(builtin.StorageMarketActorAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get reward actor for computing total supply: %s", err)
|
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)
|
power, err := rt.state.GetActor(builtin.StoragePowerActorAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get reward actor for computing total supply: %s", err)
|
rt.Abortf(exitcode.ErrIllegalState, "failed to get reward actor for computing total supply: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
total = types.BigSub(total, rew.Balance)
|
var pst sapower.State
|
||||||
total = types.BigSub(total, burnt.Balance)
|
if err := rt.cst.Get(rt.ctx, power.Head, &pst); err != nil {
|
||||||
total = types.BigSub(total, market.Balance)
|
|
||||||
|
|
||||||
var st sapower.State
|
|
||||||
if err := rt.cst.Get(rt.ctx, power.Head, &st); err != nil {
|
|
||||||
rt.Abortf(exitcode.ErrIllegalState, "failed to get storage power state: %s", err)
|
rt.Abortf(exitcode.ErrIllegalState, "failed to get storage power state: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return types.BigSub(total, st.TotalPledgeCollateral)
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *Runtime) ResolveAddress(addr address.Address) (ret address.Address, ok bool) {
|
func (rt *Runtime) ResolveAddress(addr address.Address) (ret address.Address, ok bool) {
|
||||||
|
@ -138,6 +138,8 @@ func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message, origin
|
|||||||
return vm.VM.makeRuntime(ctx, msg, origin, originNonce, usedGas, nac)
|
return vm.VM.makeRuntime(ctx, msg, origin, originNonce, usedGas, nac)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VestedCalculator func(context.Context, abi.ChainEpoch) (abi.TokenAmount, error)
|
||||||
|
|
||||||
type VM struct {
|
type VM struct {
|
||||||
cstate *state.StateTree
|
cstate *state.StateTree
|
||||||
base cid.Cid
|
base cid.Cid
|
||||||
@ -146,11 +148,12 @@ type VM struct {
|
|||||||
blockHeight abi.ChainEpoch
|
blockHeight abi.ChainEpoch
|
||||||
inv *Invoker
|
inv *Invoker
|
||||||
rand Rand
|
rand Rand
|
||||||
|
vc VestedCalculator
|
||||||
|
|
||||||
Syscalls SyscallBuilder
|
Syscalls SyscallBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVM(base cid.Cid, height abi.ChainEpoch, r Rand, cbs blockstore.Blockstore, syscalls SyscallBuilder) (*VM, error) {
|
func NewVM(base cid.Cid, height abi.ChainEpoch, r Rand, cbs blockstore.Blockstore, syscalls SyscallBuilder, vestedCalc VestedCalculator) (*VM, error) {
|
||||||
buf := bufbstore.NewBufferedBstore(cbs)
|
buf := bufbstore.NewBufferedBstore(cbs)
|
||||||
cst := cbor.NewCborStore(buf)
|
cst := cbor.NewCborStore(buf)
|
||||||
state, err := state.LoadStateTree(cst, base)
|
state, err := state.LoadStateTree(cst, base)
|
||||||
@ -166,6 +169,7 @@ func NewVM(base cid.Cid, height abi.ChainEpoch, r Rand, cbs blockstore.Blockstor
|
|||||||
blockHeight: height,
|
blockHeight: height,
|
||||||
inv: NewInvoker(),
|
inv: NewInvoker(),
|
||||||
rand: r, // TODO: Probably should be a syscall
|
rand: r, // TODO: Probably should be a syscall
|
||||||
|
vc: vestedCalc,
|
||||||
Syscalls: syscalls,
|
Syscalls: syscalls,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -675,6 +679,10 @@ func (vm *VM) SetInvoker(i *Invoker) {
|
|||||||
vm.inv = i
|
vm.inv = i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vm *VM) GetVestedFunds(ctx context.Context) (abi.TokenAmount, error) {
|
||||||
|
return vm.vc(ctx, vm.blockHeight)
|
||||||
|
}
|
||||||
|
|
||||||
func (vm *VM) incrementNonce(addr address.Address) error {
|
func (vm *VM) incrementNonce(addr address.Address) error {
|
||||||
return vm.cstate.MutateActor(addr, func(a *types.Actor) error {
|
return vm.cstate.MutateActor(addr, func(a *types.Actor) error {
|
||||||
a.Nonce++
|
a.Nonce++
|
||||||
|
@ -131,7 +131,15 @@ func LoadTipSet(ctx context.Context, cctx *cli.Context, api api.FullNode) (*type
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ParseTipSetRef(ctx, api, tss)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseTipSetRef(ctx context.Context, api api.FullNode, tss string) (*types.TipSet, error) {
|
||||||
if tss[0] == '@' {
|
if tss[0] == '@' {
|
||||||
|
if tss == "@head" {
|
||||||
|
return api.ChainHead(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
var h uint64
|
var h uint64
|
||||||
if _, err := fmt.Sscanf(tss, "@%d", &h); err != nil {
|
if _, err := fmt.Sscanf(tss, "@%d", &h); err != nil {
|
||||||
return nil, xerrors.Errorf("parsing height tipset ref: %w", err)
|
return nil, xerrors.Errorf("parsing height tipset ref: %w", err)
|
||||||
|
@ -21,7 +21,7 @@ func main() {
|
|||||||
keyinfoCmd,
|
keyinfoCmd,
|
||||||
noncefix,
|
noncefix,
|
||||||
bigIntParseCmd,
|
bigIntParseCmd,
|
||||||
staterootStatsCmd,
|
staterootCmd,
|
||||||
importCarCmd,
|
importCarCmd,
|
||||||
commpToCidCmd,
|
commpToCidCmd,
|
||||||
fetchParamCmd,
|
fetchParamCmd,
|
||||||
|
@ -2,17 +2,29 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/multiformats/go-multihash"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
lcli "github.com/filecoin-project/lotus/cli"
|
lcli "github.com/filecoin-project/lotus/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
var staterootStatsCmd = &cli.Command{
|
var staterootCmd = &cli.Command{
|
||||||
Name: "stateroot-stats",
|
Name: "stateroot",
|
||||||
|
Subcommands: []*cli.Command{
|
||||||
|
staterootDiffsCmd,
|
||||||
|
staterootStatCmd,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var staterootDiffsCmd = &cli.Command{
|
||||||
|
Name: "diffs",
|
||||||
Description: "Walk down the chain and collect stats-obj changes between tipsets",
|
Description: "Walk down the chain and collect stats-obj changes between tipsets",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
@ -92,3 +104,101 @@ var staterootStatsCmd = &cli.Command{
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type statItem struct {
|
||||||
|
Addr address.Address
|
||||||
|
Actor *types.Actor
|
||||||
|
Stat api.ObjStat
|
||||||
|
}
|
||||||
|
|
||||||
|
var staterootStatCmd = &cli.Command{
|
||||||
|
Name: "stat",
|
||||||
|
Usage: "print statistics for the stateroot of a given block",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "tipset",
|
||||||
|
Usage: "specify tipset to start from",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
api, closer, err := lcli.GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer closer()
|
||||||
|
ctx := lcli.ReqContext(cctx)
|
||||||
|
|
||||||
|
ts, err := lcli.LoadTipSet(ctx, cctx, api)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ts == nil {
|
||||||
|
ts, err = api.ChainHead(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var addrs []address.Address
|
||||||
|
|
||||||
|
for _, inp := range cctx.Args().Slice() {
|
||||||
|
a, err := address.NewFromString(inp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
addrs = append(addrs, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(addrs) == 0 {
|
||||||
|
allActors, err := api.StateListActors(ctx, ts.Key())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
addrs = allActors
|
||||||
|
}
|
||||||
|
|
||||||
|
var infos []statItem
|
||||||
|
for _, a := range addrs {
|
||||||
|
act, err := api.StateGetActor(ctx, a, ts.Key())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
stat, err := api.ChainStatObj(ctx, act.Head, cid.Undef)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
infos = append(infos, statItem{
|
||||||
|
Addr: a,
|
||||||
|
Actor: act,
|
||||||
|
Stat: stat,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(infos, func(i, j int) bool {
|
||||||
|
return infos[i].Stat.Size > infos[j].Stat.Size
|
||||||
|
})
|
||||||
|
|
||||||
|
outcap := 10
|
||||||
|
if cctx.Args().Len() > outcap {
|
||||||
|
outcap = cctx.Args().Len()
|
||||||
|
}
|
||||||
|
if len(infos) < outcap {
|
||||||
|
outcap = len(infos)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("Addr\tType\tSize\n")
|
||||||
|
for _, inf := range infos[:outcap] {
|
||||||
|
cmh, err := multihash.Decode(inf.Actor.Code.Hash())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%s\t%s\t%d\n", inf.Addr, string(cmh.Digest), inf.Stat.Size)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
2
go.mod
2
go.mod
@ -23,7 +23,7 @@ require (
|
|||||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
|
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
|
||||||
github.com/filecoin-project/go-data-transfer v0.5.1
|
github.com/filecoin-project/go-data-transfer v0.5.1
|
||||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f
|
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f
|
||||||
github.com/filecoin-project/go-fil-markets v0.5.2-0.20200728110539-caae3fda6623
|
github.com/filecoin-project/go-fil-markets v0.5.2
|
||||||
github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24
|
github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24
|
||||||
github.com/filecoin-project/go-multistore v0.0.2
|
github.com/filecoin-project/go-multistore v0.0.2
|
||||||
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
|
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
|
||||||
|
4
go.sum
4
go.sum
@ -244,8 +244,8 @@ github.com/filecoin-project/go-data-transfer v0.5.1/go.mod h1:PRs78hp9u8T4G2Jce5
|
|||||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5/go.mod h1:JbkIgFF/Z9BDlvrJO1FuKkaWsH673/UdFaiVS6uIHlA=
|
github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5/go.mod h1:JbkIgFF/Z9BDlvrJO1FuKkaWsH673/UdFaiVS6uIHlA=
|
||||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s=
|
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s=
|
||||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
|
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
|
||||||
github.com/filecoin-project/go-fil-markets v0.5.2-0.20200728110539-caae3fda6623 h1:LuX25+rzM56XX+M4413ngRA+RAhm88vlFbsvbVtpcDc=
|
github.com/filecoin-project/go-fil-markets v0.5.2 h1:4xW3JoPnPDKP+f4s/tWLmuYaReGdjetHZT7qgXivdiw=
|
||||||
github.com/filecoin-project/go-fil-markets v0.5.2-0.20200728110539-caae3fda6623/go.mod h1:zDhwmUy/AS/xCJOayW7Cedff9SDuSdGIWRnGXBDjcOk=
|
github.com/filecoin-project/go-fil-markets v0.5.2/go.mod h1:zDhwmUy/AS/xCJOayW7Cedff9SDuSdGIWRnGXBDjcOk=
|
||||||
github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24 h1:Jc7vkplmZYVuaEcSXGHDwefvZIdoyyaoGDLqSr8Svms=
|
github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24 h1:Jc7vkplmZYVuaEcSXGHDwefvZIdoyyaoGDLqSr8Svms=
|
||||||
github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24/go.mod h1:j6zV//WXIIY5kky873Q3iIKt/ViOE8rcijovmpxrXzM=
|
github.com/filecoin-project/go-jsonrpc v0.1.1-0.20200602181149-522144ab4e24/go.mod h1:j6zV//WXIIY5kky873Q3iIKt/ViOE8rcijovmpxrXzM=
|
||||||
github.com/filecoin-project/go-multistore v0.0.2 h1:JZEddnXXt3mMzHi7bi9IH7Yi1NpGLy19J5Lk/xbxBMs=
|
github.com/filecoin-project/go-multistore v0.0.2 h1:JZEddnXXt3mMzHi7bi9IH7Yi1NpGLy19J5Lk/xbxBMs=
|
||||||
|
@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||||
lru "github.com/hashicorp/golang-lru"
|
lru "github.com/hashicorp/golang-lru"
|
||||||
|
|
||||||
@ -271,15 +270,6 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error)
|
|||||||
return m.lastWork, nil
|
return m.lastWork, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Miner) hasPower(ctx context.Context, addr address.Address, ts *types.TipSet) (bool, error) {
|
|
||||||
mpower, err := m.api.StateMinerPower(ctx, addr, ts.Key())
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return mpower.MinerPower.QualityAdjPower.GreaterThanEqual(power.ConsensusMinerMinPower), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// mineOne attempts to mine a single block, and does so synchronously, if and
|
// mineOne attempts to mine a single block, and does so synchronously, if and
|
||||||
// only if we are eligible to mine.
|
// only if we are eligible to mine.
|
||||||
//
|
//
|
||||||
@ -303,6 +293,10 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*types.BlockMsg,
|
|||||||
if mbi == nil {
|
if mbi == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
if !mbi.HasMinPower {
|
||||||
|
// slashed or just have no power yet
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
tMBI := build.Clock.Now()
|
tMBI := build.Clock.Now()
|
||||||
|
|
||||||
@ -311,15 +305,6 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*types.BlockMsg,
|
|||||||
tDrand := build.Clock.Now()
|
tDrand := build.Clock.Now()
|
||||||
bvals := mbi.BeaconEntries
|
bvals := mbi.BeaconEntries
|
||||||
|
|
||||||
hasPower, err := m.hasPower(ctx, m.address, base.TipSet)
|
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("checking if miner is slashed: %w", err)
|
|
||||||
}
|
|
||||||
if !hasPower {
|
|
||||||
// slashed or just have no power yet
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
tPowercheck := build.Clock.Now()
|
tPowercheck := build.Clock.Now()
|
||||||
|
|
||||||
log.Infof("Time delta between now and our mining base: %ds (nulls: %d)", uint64(build.Clock.Now().Unix())-base.TipSet.MinTimestamp(), base.NullRounds)
|
log.Infof("Time delta between now and our mining base: %ds (nulls: %d)", uint64(build.Clock.Now().Unix())-base.TipSet.MinTimestamp(), base.NullRounds)
|
||||||
|
Loading…
Reference in New Issue
Block a user