Downgrade actors, get tests to pass
This commit is contained in:
parent
a4fe866bff
commit
927ee2406a
@ -238,7 +238,7 @@ func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client
|
||||
Wallet: addr,
|
||||
Miner: maddr,
|
||||
EpochPrice: types.NewInt(1000000),
|
||||
MinBlocksDuration: 100,
|
||||
MinBlocksDuration: uint64(build.MinDealDuration),
|
||||
FastRetrieval: fastRet,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -90,3 +90,7 @@ const VerifSigCacheSize = 32000
|
||||
// TODO: If this is gonna stay, it should move to specs-actors
|
||||
const BlockMessageLimit = 512
|
||||
const BlockGasLimit = 7_500_000_000
|
||||
|
||||
// Actor consts
|
||||
// TODO: Pull from actors when its made not private
|
||||
var MinDealDuration = abi.ChainEpoch(180 * builtin.EpochsInDay)
|
||||
|
@ -102,91 +102,91 @@ Genesis: {
|
||||
|
||||
*/
|
||||
|
||||
func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template genesis.Template) (*state.StateTree, error) {
|
||||
func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template genesis.Template) (*state.StateTree, map[address.Address]address.Address, error) {
|
||||
// Create empty state tree
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
_, err := cst.Put(context.TODO(), []struct{}{})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("putting empty object: %w", err)
|
||||
return nil, nil, xerrors.Errorf("putting empty object: %w", err)
|
||||
}
|
||||
|
||||
state, err := state.NewStateTree(cst)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("making new state tree: %w", err)
|
||||
return nil, nil, xerrors.Errorf("making new state tree: %w", err)
|
||||
}
|
||||
|
||||
emptyobject, err := cst.Put(context.TODO(), []struct{}{})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed putting empty object: %w", err)
|
||||
return nil, nil, xerrors.Errorf("failed putting empty object: %w", err)
|
||||
}
|
||||
|
||||
// Create system actor
|
||||
|
||||
sysact, err := SetupSystemActor(bs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup init actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("setup init actor: %w", err)
|
||||
}
|
||||
if err := state.SetActor(builtin.SystemActorAddr, sysact); err != nil {
|
||||
return nil, xerrors.Errorf("set init actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("set init actor: %w", err)
|
||||
}
|
||||
|
||||
// Create init actor
|
||||
|
||||
initact, err := SetupInitActor(bs, template.NetworkName, template.Accounts, template.VerifregRootKey)
|
||||
initact, keyIDs, err := SetupInitActor(bs, template.NetworkName, template.Accounts, template.VerifregRootKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup init actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("setup init actor: %w", err)
|
||||
}
|
||||
if err := state.SetActor(builtin.InitActorAddr, initact); err != nil {
|
||||
return nil, xerrors.Errorf("set init actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("set init actor: %w", err)
|
||||
}
|
||||
|
||||
// Setup reward
|
||||
// RewardActor's state is overrwritten by SetupStorageMiners
|
||||
rewact, err := SetupRewardActor(bs, big.Zero())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup init actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("setup init actor: %w", err)
|
||||
}
|
||||
|
||||
err = state.SetActor(builtin.RewardActorAddr, rewact)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("set network account actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("set network account actor: %w", err)
|
||||
}
|
||||
|
||||
// Setup cron
|
||||
cronact, err := SetupCronActor(bs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup cron actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("setup cron actor: %w", err)
|
||||
}
|
||||
if err := state.SetActor(builtin.CronActorAddr, cronact); err != nil {
|
||||
return nil, xerrors.Errorf("set cron actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("set cron actor: %w", err)
|
||||
}
|
||||
|
||||
// Create empty power actor
|
||||
spact, err := SetupStoragePowerActor(bs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup storage market actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("setup storage market actor: %w", err)
|
||||
}
|
||||
if err := state.SetActor(builtin.StoragePowerActorAddr, spact); err != nil {
|
||||
return nil, xerrors.Errorf("set storage market actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("set storage market actor: %w", err)
|
||||
}
|
||||
|
||||
// Create empty market actor
|
||||
marketact, err := SetupStorageMarketActor(bs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup storage market actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("setup storage market actor: %w", err)
|
||||
}
|
||||
if err := state.SetActor(builtin.StorageMarketActorAddr, marketact); err != nil {
|
||||
return nil, xerrors.Errorf("set market actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("set market actor: %w", err)
|
||||
}
|
||||
|
||||
// Create verified registry
|
||||
verifact, err := SetupVerifiedRegistryActor(bs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup storage market actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("setup storage market actor: %w", err)
|
||||
}
|
||||
if err := state.SetActor(builtin.VerifiedRegistryActorAddr, verifact); err != nil {
|
||||
return nil, xerrors.Errorf("set market actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("set market actor: %w", err)
|
||||
}
|
||||
|
||||
// Setup burnt-funds
|
||||
@ -196,60 +196,60 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
|
||||
Head: emptyobject,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("set burnt funds account actor: %w", err)
|
||||
return nil, nil, xerrors.Errorf("set burnt funds account actor: %w", err)
|
||||
}
|
||||
|
||||
// Create accounts
|
||||
for id, info := range template.Accounts {
|
||||
if info.Type != genesis.TAccount && info.Type != genesis.TMultisig {
|
||||
return nil, xerrors.New("unsupported account type")
|
||||
return nil, nil, xerrors.New("unsupported account type")
|
||||
}
|
||||
|
||||
ida, err := address.NewIDAddress(uint64(AccountStart + id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err = createAccount(ctx, bs, cst, state, ida, info); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vregroot, err := address.NewIDAddress(80)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err = createAccount(ctx, bs, cst, state, vregroot, template.VerifregRootKey); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Setup the first verifier as ID-address 81
|
||||
// TODO: remove this
|
||||
skBytes, err := sigs.Generate(crypto.SigTypeBLS)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("creating random verifier secret key: %w", err)
|
||||
return nil, nil, xerrors.Errorf("creating random verifier secret key: %w", err)
|
||||
}
|
||||
|
||||
verifierPk, err := sigs.ToPublic(crypto.SigTypeBLS, skBytes)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("creating random verifier public key: %w", err)
|
||||
return nil, nil, xerrors.Errorf("creating random verifier public key: %w", err)
|
||||
}
|
||||
|
||||
verifierAd, err := address.NewBLSAddress(verifierPk)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("creating random verifier address: %w", err)
|
||||
return nil, nil, xerrors.Errorf("creating random verifier address: %w", err)
|
||||
}
|
||||
|
||||
verifierId, err := address.NewIDAddress(81)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
verifierState, err := cst.Put(ctx, &account.State{Address: verifierAd})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
err = state.SetActor(verifierId, &types.Actor{
|
||||
@ -259,10 +259,10 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setting account from actmap: %w", err)
|
||||
return nil, nil, xerrors.Errorf("setting account from actmap: %w", err)
|
||||
}
|
||||
|
||||
return state, nil
|
||||
return state, keyIDs, nil
|
||||
}
|
||||
|
||||
func createAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.IpldStore, state *state.StateTree, ida address.Address, info genesis.Actor) error {
|
||||
@ -317,7 +317,7 @@ func createAccount(ctx context.Context, bs bstore.Blockstore, cst cbor.IpldStore
|
||||
return nil
|
||||
}
|
||||
|
||||
func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot cid.Cid, template genesis.Template) (cid.Cid, error) {
|
||||
func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot cid.Cid, template genesis.Template, keyIDs map[address.Address]address.Address) (cid.Cid, error) {
|
||||
verifNeeds := make(map[address.Address]abi.PaddedPieceSize)
|
||||
var sum abi.PaddedPieceSize
|
||||
|
||||
@ -332,7 +332,7 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
|
||||
_, err = doExec(ctx, vm, builtin.StorageMarketActorAddr, m.Owner, builtin.MethodsMarket.AddBalance, mustEnc(adt.Empty))
|
||||
for _, s := range m.Sectors {
|
||||
amt := s.Deal.PieceSize
|
||||
verifNeeds[s.Deal.Client] += amt
|
||||
verifNeeds[keyIDs[s.Deal.Client]] += amt
|
||||
sum += amt
|
||||
}
|
||||
}
|
||||
@ -376,7 +376,7 @@ func VerifyPreSealedData(ctx context.Context, cs *store.ChainStore, stateroot ci
|
||||
}
|
||||
|
||||
func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallBuilder, template genesis.Template) (*GenesisBootstrap, error) {
|
||||
st, err := MakeInitialStateTree(ctx, bs, template)
|
||||
st, keyIDs, err := MakeInitialStateTree(ctx, bs, template)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("make initial state tree failed: %w", err)
|
||||
}
|
||||
@ -390,7 +390,7 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys vm.SyscallB
|
||||
cs := store.NewChainStore(bs, datastore.NewMapDatastore(), sys)
|
||||
|
||||
// Verify PreSealed Data
|
||||
stateroot, err = VerifyPreSealedData(ctx, cs, stateroot, template)
|
||||
stateroot, err = VerifyPreSealedData(ctx, cs, stateroot, template, keyIDs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to verify presealed data: %w", err)
|
||||
}
|
||||
|
@ -247,14 +247,17 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid
|
||||
return cid.Undef, xerrors.Errorf("getting current total power: %w", err)
|
||||
}
|
||||
|
||||
pledge := miner.InitialPledgeForPower(
|
||||
sectorWeight,
|
||||
epochReward.ThisEpochBaselinePower,
|
||||
tpow.PledgeCollateral,
|
||||
epochReward.ThisEpochRewardSmoothed,
|
||||
tpow.QualityAdjPowerSmoothed,
|
||||
circSupply(ctx, vm, minerInfos[i].maddr),
|
||||
)
|
||||
pledge := miner.InitialPledgeForPower(sectorWeight, tpow.QualityAdjPower, epochReward.ThisEpochBaselinePower, tpow.PledgeCollateral, epochReward.ThisEpochReward, circSupply(ctx, vm, minerInfos[i].maddr))
|
||||
/*
|
||||
Use with newer actors:
|
||||
pledge := miner.InitialPledgeForPower(
|
||||
sectorWeight,
|
||||
epochReward.ThisEpochBaselinePower,
|
||||
tpow.PledgeCollateral,
|
||||
epochReward.ThisEpochRewardSmoothed,
|
||||
tpow.QualityAdjPowerSmoothed,
|
||||
circSupply(ctx, vm, minerInfos[i].maddr),
|
||||
)*/
|
||||
|
||||
fmt.Println(types.FIL(pledge))
|
||||
_, err = doExecValue(ctx, vm, minerInfos[i].maddr, m.Worker, pledge, builtin.MethodsMiner.PreCommitSector, mustEnc(params))
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
@ -18,9 +19,9 @@ import (
|
||||
bstore "github.com/filecoin-project/lotus/lib/blockstore"
|
||||
)
|
||||
|
||||
func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesis.Actor, rootVerifier genesis.Actor) (*types.Actor, error) {
|
||||
func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesis.Actor, rootVerifier genesis.Actor) (*types.Actor, map[address.Address]address.Address, error) {
|
||||
if len(initialActors) > MaxAccounts {
|
||||
return nil, xerrors.New("too many initial actors")
|
||||
return nil, nil, xerrors.New("too many initial actors")
|
||||
}
|
||||
|
||||
var ias init_.State
|
||||
@ -30,48 +31,56 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
|
||||
store := adt.WrapStore(context.TODO(), cbor.NewCborStore(bs))
|
||||
amap := adt.MakeEmptyMap(store)
|
||||
|
||||
keyToId := map[address.Address]address.Address{}
|
||||
|
||||
for i, a := range initialActors {
|
||||
if a.Type == genesis.TMultisig {
|
||||
continue
|
||||
}
|
||||
|
||||
if a.Type != genesis.TAccount {
|
||||
return nil, xerrors.Errorf("unsupported account type: %s", a.Type) // TODO: Support msig (skip here)
|
||||
return nil, nil, xerrors.Errorf("unsupported account type: %s", a.Type) // TODO: Support msig (skip here)
|
||||
}
|
||||
|
||||
var ainfo genesis.AccountMeta
|
||||
if err := json.Unmarshal(a.Meta, &ainfo); err != nil {
|
||||
return nil, xerrors.Errorf("unmarshaling account meta: %w", err)
|
||||
return nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("init set %s t0%d\n", ainfo.Owner, AccountStart+int64(i))
|
||||
|
||||
value := cbg.CborInt(AccountStart + int64(i))
|
||||
if err := amap.Put(adt.AddrKey(ainfo.Owner), &value); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var err error
|
||||
keyToId[ainfo.Owner], err = address.NewIDAddress(uint64(value))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if rootVerifier.Type == genesis.TAccount {
|
||||
var ainfo genesis.AccountMeta
|
||||
if err := json.Unmarshal(rootVerifier.Meta, &ainfo); err != nil {
|
||||
return nil, xerrors.Errorf("unmarshaling account meta: %w", err)
|
||||
return nil, nil, xerrors.Errorf("unmarshaling account meta: %w", err)
|
||||
}
|
||||
value := cbg.CborInt(80)
|
||||
if err := amap.Put(adt.AddrKey(ainfo.Owner), &value); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
amapaddr, err := amap.Root()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
ias.AddressMap = amapaddr
|
||||
|
||||
statecid, err := store.Put(store.Context(), &ias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
act := &types.Actor{
|
||||
@ -79,5 +88,5 @@ func SetupInitActor(bs bstore.Blockstore, netname string, initialActors []genesi
|
||||
Head: statecid,
|
||||
}
|
||||
|
||||
return act, nil
|
||||
return act, keyToId, nil
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package cli
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
@ -344,6 +345,10 @@ var clientDealCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
if abi.ChainEpoch(dur) < build.MinDealDuration {
|
||||
return xerrors.Errorf("minimum deal duration is %d blocks", build.MinDealDuration)
|
||||
}
|
||||
|
||||
var a address.Address
|
||||
if from := cctx.String("from"); from != "" {
|
||||
faddr, err := address.NewFromString(from)
|
||||
|
2
go.mod
2
go.mod
@ -30,7 +30,7 @@ require (
|
||||
github.com/filecoin-project/go-statestore v0.1.0
|
||||
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b
|
||||
github.com/filecoin-project/sector-storage v0.0.0-20200727112136-9377cb376d25
|
||||
github.com/filecoin-project/specs-actors v0.8.1-0.20200728130932-33f4d6eb316b
|
||||
github.com/filecoin-project/specs-actors v0.8.1-0.20200728070314-197087a9685b
|
||||
github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea
|
||||
github.com/filecoin-project/storage-fsm v0.0.0-20200720190000-2cfe2fe3c334
|
||||
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
|
||||
|
2
go.sum
2
go.sum
@ -279,6 +279,8 @@ github.com/filecoin-project/specs-actors v0.7.3-0.20200716231407-60a2ae96d2e6/go
|
||||
github.com/filecoin-project/specs-actors v0.8.1-0.20200720115956-cd051eabf328/go.mod h1:0+CxQ5Jeii3522irTvhKRDpr4GG1bj5Erq3p/d38DzY=
|
||||
github.com/filecoin-project/specs-actors v0.8.1-0.20200723200253-a3c01bc62f99 h1:li6OZVhGNrQihzKhUy7x4vwKgUCExnpVSj746VMkq1I=
|
||||
github.com/filecoin-project/specs-actors v0.8.1-0.20200723200253-a3c01bc62f99/go.mod h1:TLvIheTVl0EIuyncuKSTVXPULaj7gzhLup5CLZ/S+uM=
|
||||
github.com/filecoin-project/specs-actors v0.8.1-0.20200728070314-197087a9685b h1:uigUd055IvGhjDXPVjB+D5IF8u4R5/BxnNby5aRU1Go=
|
||||
github.com/filecoin-project/specs-actors v0.8.1-0.20200728070314-197087a9685b/go.mod h1:U1qnlL3MjJnE6n3MTUUVhlmpJodx+fo26cC0aiL1jeo=
|
||||
github.com/filecoin-project/specs-actors v0.8.1-0.20200728130932-33f4d6eb316b h1:E3cJHaDN37gD60mFuIwg+/Mt6G5rrg0tTU5rBHQIG5o=
|
||||
github.com/filecoin-project/specs-actors v0.8.1-0.20200728130932-33f4d6eb316b/go.mod h1:U1qnlL3MjJnE6n3MTUUVhlmpJodx+fo26cC0aiL1jeo=
|
||||
github.com/filecoin-project/specs-storage v0.1.0/go.mod h1:Pr5ntAaxsh+sLG/LYiL4tKzvA83Vk5vLODYhfNwOg7k=
|
||||
|
@ -88,7 +88,7 @@ func (a *MpoolAPI) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (ci
|
||||
}
|
||||
|
||||
// GasMargin sets by how much should gas limit be increased over test execution
|
||||
var GasMargin = 1.2
|
||||
var GasMargin = 1.5
|
||||
|
||||
func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message) (*types.SignedMessage, error) {
|
||||
if msg.Nonce != 0 {
|
||||
|
@ -999,6 +999,8 @@ func (a *StateAPI) StateMinerInitialPledgeCollateral(ctx context.Context, maddr
|
||||
}
|
||||
|
||||
sectorWeight := miner.QAPowerForWeight(ssize, duration, dealWeights.DealWeight, dealWeights.VerifiedDealWeight)
|
||||
initialPledge := miner.InitialPledgeForPower(sectorWeight, powerState.TotalQualityAdjPower, reward.SlowConvenientBaselineForEpoch(ts.Height()), powerState.TotalPledgeCollateral, rewardState.ThisEpochReward, circSupply)
|
||||
/* Use with newer actors
|
||||
initialPledge := miner.InitialPledgeForPower(
|
||||
sectorWeight,
|
||||
rewardState.ThisEpochBaselinePower,
|
||||
@ -1006,7 +1008,7 @@ func (a *StateAPI) StateMinerInitialPledgeCollateral(ctx context.Context, maddr
|
||||
rewardState.ThisEpochRewardSmoothed,
|
||||
powerState.ThisEpochQAPowerSmoothed,
|
||||
circSupply,
|
||||
)
|
||||
)*/
|
||||
|
||||
return types.BigDiv(types.BigMul(initialPledge, initialPledgeNum), initialPledgeDen), nil
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ func PreSeal(ssize abi.SectorSize, maddr address.Address, sectors int) (*genesis
|
||||
preseal.Deal = market.DealProposal{
|
||||
PieceCID: preseal.CommD,
|
||||
PieceSize: abi.PaddedPieceSize(ssize),
|
||||
Client: maddr,
|
||||
Client: k.Address,
|
||||
Provider: maddr,
|
||||
Label: fmt.Sprintf("%d", i),
|
||||
StartEpoch: 1,
|
||||
|
Loading…
Reference in New Issue
Block a user