Skip to content

Commit

Permalink
contractor: State -> MaintenanceState; contractor: remove 2 interface…
Browse files Browse the repository at this point in the history
… functions from Bus interface
  • Loading branch information
ChrisSchinnerl committed Mar 19, 2024
1 parent 252ca57 commit bac605d
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 50 deletions.
15 changes: 11 additions & 4 deletions autopilot/autopilot.go
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ func (ap *Autopilot) hostsHandlerPOST(jc jape.Context) {
jc.Encode(hosts)
}

func (ap *Autopilot) buildState(ctx context.Context) (*contractor.State, error) {
func (ap *Autopilot) buildState(ctx context.Context) (*contractor.MaintenanceState, error) {
// fetch the autopilot from the bus
autopilot, err := ap.Config(ctx)
if err != nil {
Expand Down Expand Up @@ -807,6 +807,12 @@ func (ap *Autopilot) buildState(ctx context.Context) (*contractor.State, error)
}
address := wi.Address

// no need to try and form contracts if wallet is completely empty
skipContractFormations := wi.Confirmed.IsZero() && wi.Unconfirmed.IsZero()
if skipContractFormations {
ap.logger.Warn("contract formations skipped, wallet is empty")
}

// update current period if necessary
if cs.Synced {
if autopilot.CurrentPeriod == 0 {
Expand All @@ -827,12 +833,13 @@ func (ap *Autopilot) buildState(ctx context.Context) (*contractor.State, error)
}
}

return &contractor.State{
return &contractor.MaintenanceState{
GS: gs,
RS: rs,
AP: autopilot,

Address: address,
Fee: fee,
Address: address,
Fee: fee,
SkipContractFormations: skipContractFormations,
}, nil
}
2 changes: 1 addition & 1 deletion autopilot/contractor/contract_spending.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (c *Contractor) currentPeriodSpending(contracts []api.Contract, currentPeri
return totalAllocated
}

func (c *Contractor) remainingFunds(contracts []api.Contract, state *State) types.Currency {
func (c *Contractor) remainingFunds(contracts []api.Contract, state *MaintenanceState) types.Currency {
// find out how much we spent in the current period
spent := c.currentPeriodSpending(contracts, state.Period())

Expand Down
45 changes: 17 additions & 28 deletions autopilot/contractor/contractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,13 @@ type Bus interface {
AncestorContracts(ctx context.Context, id types.FileContractID, minStartHeight uint64) ([]api.ArchivedContract, error)
ArchiveContracts(ctx context.Context, toArchive map[types.FileContractID]string) error
ConsensusState(ctx context.Context) (api.ConsensusState, error)
Contract(ctx context.Context, id types.FileContractID) (api.ContractMetadata, error)
Contracts(ctx context.Context, opts api.ContractsOpts) (contracts []api.ContractMetadata, err error)
FileContractTax(ctx context.Context, payout types.Currency) (types.Currency, error)
Host(ctx context.Context, hostKey types.PublicKey) (hostdb.HostInfo, error)
Hosts(ctx context.Context, opts api.GetHostsOptions) ([]hostdb.Host, error)
RecordContractSetChurnMetric(ctx context.Context, metrics ...api.ContractSetChurnMetric) error
SearchHosts(ctx context.Context, opts api.SearchHostOptions) ([]hostdb.Host, error)
SetContractSet(ctx context.Context, set string, contracts []types.FileContractID) error
Wallet(ctx context.Context) (api.WalletResponse, error)
}

type Worker interface {
Expand Down Expand Up @@ -226,7 +224,7 @@ func canSkipContractMaintenance(ctx context.Context, cfg api.ContractsConfig) (s
return "", false
}

func (c *Contractor) PerformContractMaintenance(ctx context.Context, w Worker, state *State) (bool, error) {
func (c *Contractor) PerformContractMaintenance(ctx context.Context, w Worker, state *MaintenanceState) (bool, error) {
// check if we can skip maintenance
if reason, skip := canSkipContractMaintenance(ctx, state.ContractsConfig()); skip {
if reason != "" {
Expand Down Expand Up @@ -418,23 +416,14 @@ func (c *Contractor) PerformContractMaintenance(ctx context.Context, w Worker, s

// check if we need to form contracts and add them to the contract set
var formed []api.ContractMetadata
if uint64(len(updatedSet)) < threshold {
// no need to try and form contracts if wallet is completely empty
wallet, err := c.bus.Wallet(ctx)
if uint64(len(updatedSet)) < threshold && !state.SkipContractFormations {
formed, err = c.runContractFormations(ctx, w, state, candidates, usedHosts, unusableHosts, state.WantedContracts()-uint64(len(updatedSet)), &remaining)
if err != nil {
c.logger.Errorf("failed to fetch wallet, err: %v", err)
return false, err
} else if wallet.Confirmed.IsZero() && wallet.Unconfirmed.IsZero() {
c.logger.Warn("contract formations skipped, wallet is empty")
c.logger.Errorf("failed to form contracts, err: %v", err) // continue
} else {
formed, err = c.runContractFormations(ctx, w, state, candidates, usedHosts, unusableHosts, state.WantedContracts()-uint64(len(updatedSet)), &remaining)
if err != nil {
c.logger.Errorf("failed to form contracts, err: %v", err) // continue
} else {
for _, fc := range formed {
updatedSet = append(updatedSet, fc)
contractData[fc.ID] = 0
}
for _, fc := range formed {
updatedSet = append(updatedSet, fc)
contractData[fc.ID] = 0
}
}
}
Expand Down Expand Up @@ -472,7 +461,7 @@ func (c *Contractor) PerformContractMaintenance(ctx context.Context, w Worker, s
return c.computeContractSetChanged(ctx, state, currentSet, updatedSet, formed, refreshed, renewed, toStopUsing, contractData), nil
}

func (c *Contractor) computeContractSetChanged(ctx context.Context, state *State, oldSet, newSet []api.ContractMetadata, formed []api.ContractMetadata, refreshed, renewed []renewal, toStopUsing map[types.FileContractID]string, contractData map[types.FileContractID]uint64) bool {
func (c *Contractor) computeContractSetChanged(ctx context.Context, state *MaintenanceState, oldSet, newSet []api.ContractMetadata, formed []api.ContractMetadata, refreshed, renewed []renewal, toStopUsing map[types.FileContractID]string, contractData map[types.FileContractID]uint64) bool {
name := state.ContractSet()

// build set lookups
Expand Down Expand Up @@ -600,7 +589,7 @@ func (c *Contractor) computeContractSetChanged(ctx context.Context, state *State
return hasChanged
}

func (c *Contractor) runContractChecks(ctx context.Context, w Worker, state *State, contracts []api.Contract, inCurrentSet map[types.FileContractID]struct{}, minScore float64) (toKeep []api.ContractMetadata, toArchive, toStopUsing map[types.FileContractID]string, toRefresh, toRenew []contractInfo, _ error) {
func (c *Contractor) runContractChecks(ctx context.Context, w Worker, state *MaintenanceState, contracts []api.Contract, inCurrentSet map[types.FileContractID]struct{}, minScore float64) (toKeep []api.ContractMetadata, toArchive, toStopUsing map[types.FileContractID]string, toRefresh, toRenew []contractInfo, _ error) {
select {
case <-ctx.Done():
return
Expand Down Expand Up @@ -787,7 +776,7 @@ LOOP:
return toKeep, toArchive, toStopUsing, toRefresh, toRenew, nil
}

func (c *Contractor) runContractFormations(ctx context.Context, w Worker, state *State, candidates scoredHosts, usedHosts map[types.PublicKey]struct{}, unusableHosts unusableHostResult, missing uint64, budget *types.Currency) (formed []api.ContractMetadata, _ error) {
func (c *Contractor) runContractFormations(ctx context.Context, w Worker, state *MaintenanceState, candidates scoredHosts, usedHosts map[types.PublicKey]struct{}, unusableHosts unusableHostResult, missing uint64, budget *types.Currency) (formed []api.ContractMetadata, _ error) {
select {
case <-ctx.Done():
return nil, nil
Expand Down Expand Up @@ -976,7 +965,7 @@ func (c *Contractor) runRevisionBroadcast(ctx context.Context, w Worker, allCont
}
}

func (c *Contractor) runContractRenewals(ctx context.Context, w Worker, state *State, toRenew []contractInfo, budget *types.Currency, limit int) (renewals []renewal, toKeep []api.ContractMetadata) {
func (c *Contractor) runContractRenewals(ctx context.Context, w Worker, state *MaintenanceState, toRenew []contractInfo, budget *types.Currency, limit int) (renewals []renewal, toKeep []api.ContractMetadata) {
c.logger.Debugw(
"run contracts renewals",
"torenew", len(toRenew),
Expand Down Expand Up @@ -1036,7 +1025,7 @@ func (c *Contractor) runContractRenewals(ctx context.Context, w Worker, state *S
return renewals, toKeep
}

func (c *Contractor) runContractRefreshes(ctx context.Context, w Worker, state *State, toRefresh []contractInfo, budget *types.Currency) (refreshed []renewal, _ error) {
func (c *Contractor) runContractRefreshes(ctx context.Context, w Worker, state *MaintenanceState, toRefresh []contractInfo, budget *types.Currency) (refreshed []renewal, _ error) {
c.logger.Debugw(
"run contracts refreshes",
"torefresh", len(toRefresh),
Expand Down Expand Up @@ -1110,7 +1099,7 @@ func (c *Contractor) refreshFundingEstimate(cfg api.AutopilotConfig, ci contract
return refreshAmountCapped
}

func (c *Contractor) renewFundingEstimate(ctx context.Context, state *State, ci contractInfo, fee types.Currency, renewing bool) (types.Currency, error) {
func (c *Contractor) renewFundingEstimate(ctx context.Context, state *MaintenanceState, ci contractInfo, fee types.Currency, renewing bool) (types.Currency, error) {
// estimate the cost of the current data stored
dataStored := ci.contract.FileSize()
storageCost := sectorStorageCost(ci.priceTable, state.Period()).Mul64(bytesToSectors(dataStored))
Expand Down Expand Up @@ -1246,7 +1235,7 @@ func (c *Contractor) calculateMinScore(candidates []scoredHost, numContracts uin
return minScore
}

func (c *Contractor) candidateHosts(ctx context.Context, state *State, hosts []hostdb.Host, usedHosts map[types.PublicKey]struct{}, storedData map[types.PublicKey]uint64, minScore float64) ([]scoredHost, unusableHostResult, error) {
func (c *Contractor) candidateHosts(ctx context.Context, state *MaintenanceState, hosts []hostdb.Host, usedHosts map[types.PublicKey]struct{}, storedData map[types.PublicKey]uint64, minScore float64) ([]scoredHost, unusableHostResult, error) {
start := time.Now()

// fetch consensus state
Expand Down Expand Up @@ -1316,7 +1305,7 @@ func (c *Contractor) candidateHosts(ctx context.Context, state *State, hosts []h
return candidates, unusableHostResult, nil
}

func (c *Contractor) renewContract(ctx context.Context, w Worker, state *State, ci contractInfo, budget *types.Currency) (cm api.ContractMetadata, proceed bool, err error) {
func (c *Contractor) renewContract(ctx context.Context, w Worker, state *MaintenanceState, ci contractInfo, budget *types.Currency) (cm api.ContractMetadata, proceed bool, err error) {
if ci.contract.Revision == nil {
return api.ContractMetadata{}, true, errors.New("can't renew contract without a revision")
}
Expand Down Expand Up @@ -1396,7 +1385,7 @@ func (c *Contractor) renewContract(ctx context.Context, w Worker, state *State,
return renewedContract, true, nil
}

func (c *Contractor) refreshContract(ctx context.Context, w Worker, state *State, ci contractInfo, budget *types.Currency) (cm api.ContractMetadata, proceed bool, err error) {
func (c *Contractor) refreshContract(ctx context.Context, w Worker, state *MaintenanceState, ci contractInfo, budget *types.Currency) (cm api.ContractMetadata, proceed bool, err error) {
if ci.contract.Revision == nil {
return api.ContractMetadata{}, true, errors.New("can't refresh contract without a revision")
}
Expand Down Expand Up @@ -1475,7 +1464,7 @@ func (c *Contractor) refreshContract(ctx context.Context, w Worker, state *State
return refreshedContract, true, nil
}

func (c *Contractor) formContract(ctx context.Context, w Worker, state *State, host hostdb.Host, minInitialContractFunds, maxInitialContractFunds types.Currency, budget *types.Currency) (cm api.ContractMetadata, proceed bool, err error) {
func (c *Contractor) formContract(ctx context.Context, w Worker, state *MaintenanceState, host hostdb.Host, minInitialContractFunds, maxInitialContractFunds types.Currency, budget *types.Currency) (cm api.ContractMetadata, proceed bool, err error) {
// convenience variables
hk := host.PublicKey

Expand Down
6 changes: 3 additions & 3 deletions autopilot/contractor/hostinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"go.sia.tech/renterd/worker"
)

func (c *Contractor) HostInfo(ctx context.Context, hostKey types.PublicKey, state *State) (api.HostHandlerResponse, error) {
func (c *Contractor) HostInfo(ctx context.Context, hostKey types.PublicKey, state *MaintenanceState) (api.HostHandlerResponse, error) {
if state.ContractsConfig().Allowance.IsZero() {
return api.HostHandlerResponse{}, fmt.Errorf("can not score hosts because contracts allowance is zero")
}
Expand Down Expand Up @@ -53,7 +53,7 @@ func (c *Contractor) HostInfo(ctx context.Context, hostKey types.PublicKey, stat
}, nil
}

func (c *Contractor) hostInfoFromCache(ctx context.Context, state *State, host hostdb.Host) (hi hostInfo, found bool) {
func (c *Contractor) hostInfoFromCache(ctx context.Context, state *MaintenanceState, host hostdb.Host) (hi hostInfo, found bool) {
// grab host details from cache
c.mu.Lock()
hi, found = c.cachedHostInfo[host.PublicKey]
Expand Down Expand Up @@ -91,7 +91,7 @@ func (c *Contractor) hostInfoFromCache(ctx context.Context, state *State, host h
return
}

func (c *Contractor) HostInfos(ctx context.Context, state *State, filterMode, usabilityMode, addressContains string, keyIn []types.PublicKey, offset, limit int) ([]api.HostHandlerResponse, error) {
func (c *Contractor) HostInfos(ctx context.Context, state *MaintenanceState, filterMode, usabilityMode, addressContains string, keyIn []types.PublicKey, offset, limit int) ([]api.HostHandlerResponse, error) {
// declare helper to decide whether to keep a host.
if !isValidUsabilityFilterMode(usabilityMode) {
return nil, fmt.Errorf("invalid usability mode: '%v', options are 'usable', 'unusable' or an empty string for no filter", usabilityMode)
Expand Down
29 changes: 15 additions & 14 deletions autopilot/contractor/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,52 @@ import (
)

type (
// State serves as input for the contractor's maintenance. It contains all
// MaintenanceState serves as input for the contractor's maintenance. It contains all
// state that should remain constant across a single round of contract
// performance.
State struct {
MaintenanceState struct {
GS api.GougingSettings
RS api.RedundancySettings
AP api.Autopilot

Address types.Address
Fee types.Currency
Address types.Address
Fee types.Currency
SkipContractFormations bool
}
)

func (state *State) AllowRedundantIPs() bool {
func (state *MaintenanceState) AllowRedundantIPs() bool {
return state.AP.Config.Hosts.AllowRedundantIPs
}

func (state *State) Allowance() types.Currency {
func (state *MaintenanceState) Allowance() types.Currency {
return state.AP.Config.Contracts.Allowance
}

func (state *State) AutopilotConfig() api.AutopilotConfig {
func (state *MaintenanceState) AutopilotConfig() api.AutopilotConfig {
return state.AP.Config
}

func (state *State) ContractsConfig() api.ContractsConfig {
func (state *MaintenanceState) ContractsConfig() api.ContractsConfig {
return state.AP.Config.Contracts
}

func (state *State) ContractSet() string {
func (state *MaintenanceState) ContractSet() string {
return state.AP.Config.Contracts.Set
}

func (s *State) EndHeight() uint64 {
return s.AP.EndHeight()
func (state *MaintenanceState) EndHeight() uint64 {
return state.AP.EndHeight()
}

func (state *State) WantedContracts() uint64 {
func (state *MaintenanceState) WantedContracts() uint64 {
return state.AP.Config.Contracts.Amount
}

func (state *State) Period() uint64 {
func (state *MaintenanceState) Period() uint64 {
return state.AP.Config.Contracts.Period
}

func (state *State) RenewWindow() uint64 {
func (state *MaintenanceState) RenewWindow() uint64 {
return state.AP.Config.Contracts.RenewWindow
}

0 comments on commit bac605d

Please sign in to comment.