Skip to content

Commit 375fb76

Browse files
author
Nate Maninger
authored
Merge pull request #504 from SiaFoundation/nate/refactor-rhp-settings
Move settings and price table into config manager
2 parents bd91bb9 + cf191e2 commit 375fb76

16 files changed

+231
-204
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
default: patch
3+
---
4+
5+
# Move RHP2 and RHP3 settings into the config manager to be consistent with RHP4

cmd/hostd/run.go

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,15 @@ func runRootCmd(ctx context.Context, cfg config.Config, walletKey types.PrivateK
198198
}
199199
defer rhp3Listener.Close()
200200

201+
_, rhp3PortStr, err := net.SplitHostPort(rhp3Listener.Addr().String())
202+
if err != nil {
203+
return fmt.Errorf("failed to parse rhp3 port: %w", err)
204+
}
205+
rhp3Port, err := strconv.ParseUint(rhp3PortStr, 10, 16)
206+
if err != nil {
207+
return fmt.Errorf("failed to parse rhp3 port: %w", err)
208+
}
209+
201210
syncerAddr := syncerListener.Addr().String()
202211
if cfg.Syncer.EnableUPnP {
203212
_, portStr, _ := net.SplitHostPort(cfg.Syncer.Address)
@@ -253,42 +262,42 @@ func runRootCmd(ctx context.Context, cfg config.Config, walletKey types.PrivateK
253262

254263
am := alerts.NewManager(alerts.WithEventReporter(wr), alerts.WithLog(log.Named("alerts")))
255264

256-
cfm, err := settings.NewConfigManager(hostKey, store, cm, s, wm, settings.WithAlertManager(am), settings.WithLog(log.Named("settings")))
257-
if err != nil {
258-
return fmt.Errorf("failed to create settings manager: %w", err)
259-
}
260-
defer cfm.Close()
261-
262265
vm, err := storage.NewVolumeManager(store, storage.WithLogger(log.Named("volumes")), storage.WithAlerter(am))
263266
if err != nil {
264267
return fmt.Errorf("failed to create storage manager: %w", err)
265268
}
266269
defer vm.Close()
267270

271+
sm, err := settings.NewConfigManager(hostKey, store, cm, s, vm, wm, settings.WithAlertManager(am), settings.WithRHP3Port(uint16(rhp3Port)), settings.WithLog(log.Named("settings")))
272+
if err != nil {
273+
return fmt.Errorf("failed to create settings manager: %w", err)
274+
}
275+
defer sm.Close()
276+
268277
contractManager, err := contracts.NewManager(store, vm, cm, s, wm, contracts.WithLog(log.Named("contracts")), contracts.WithAlerter(am))
269278
if err != nil {
270279
return fmt.Errorf("failed to create contracts manager: %w", err)
271280
}
272281
defer contractManager.Close()
273282

274-
index, err := index.NewManager(store, cm, contractManager, wm, cfm, vm, index.WithLog(log.Named("index")), index.WithBatchSize(cfg.Consensus.IndexBatchSize))
283+
index, err := index.NewManager(store, cm, contractManager, wm, sm, vm, index.WithLog(log.Named("index")), index.WithBatchSize(cfg.Consensus.IndexBatchSize))
275284
if err != nil {
276285
return fmt.Errorf("failed to create index manager: %w", err)
277286
}
278287
defer index.Close()
279288

280289
dr := rhp.NewDataRecorder(store, log.Named("data"))
281290

282-
rhp2, err := rhp2.NewSessionHandler(rhp2Listener, hostKey, rhp3Listener.Addr().String(), cm, s, wm, contractManager, cfm, vm, rhp2.WithDataMonitor(dr), rhp2.WithLog(log.Named("rhp2")))
291+
rhp2, err := rhp2.NewSessionHandler(rhp2Listener, hostKey, cm, s, wm, contractManager, sm, vm, rhp2.WithDataMonitor(dr), rhp2.WithLog(log.Named("rhp2")))
283292
if err != nil {
284293
return fmt.Errorf("failed to create rhp2 session handler: %w", err)
285294
}
286295
go rhp2.Serve()
287296
defer rhp2.Close()
288297

289298
registry := registry.NewManager(hostKey, store, log.Named("registry"))
290-
accounts := accounts.NewManager(store, cfm)
291-
rhp3, err := rhp3.NewSessionHandler(rhp3Listener, hostKey, cm, s, wm, accounts, contractManager, registry, vm, cfm, rhp3.WithDataMonitor(dr), rhp3.WithSessionReporter(sr), rhp3.WithLog(log.Named("rhp3")))
299+
accounts := accounts.NewManager(store, sm)
300+
rhp3, err := rhp3.NewSessionHandler(rhp3Listener, hostKey, cm, s, wm, accounts, contractManager, registry, vm, sm, rhp3.WithDataMonitor(dr), rhp3.WithSessionReporter(sr), rhp3.WithLog(log.Named("rhp3")))
292301
if err != nil {
293302
return fmt.Errorf("failed to create rhp3 session handler: %w", err)
294303
}
@@ -304,7 +313,7 @@ func runRootCmd(ctx context.Context, cfg config.Config, walletKey types.PrivateK
304313
}
305314
if !cfg.Explorer.Disable {
306315
ex := explorer.New(cfg.Explorer.URL)
307-
pm, err := pin.NewManager(store, cfm, ex, pin.WithLogger(log.Named("pin")))
316+
pm, err := pin.NewManager(store, sm, ex, pin.WithLogger(log.Named("pin")))
308317
if err != nil {
309318
return fmt.Errorf("failed to create pin manager: %w", err)
310319
}
@@ -314,7 +323,7 @@ func runRootCmd(ctx context.Context, cfg config.Config, walletKey types.PrivateK
314323

315324
web := http.Server{
316325
Handler: webRouter{
317-
api: jape.BasicAuth(cfg.HTTP.Password)(api.NewServer(cfg.Name, hostKey.PublicKey(), cm, s, accounts, contractManager, vm, wm, store, cfm, index, apiOpts...)),
326+
api: jape.BasicAuth(cfg.HTTP.Password)(api.NewServer(cfg.Name, hostKey.PublicKey(), cm, s, accounts, contractManager, vm, wm, store, sm, index, apiOpts...)),
318327
ui: hostd.Handler(),
319328
},
320329
ReadTimeout: 30 * time.Second,

host/settings/announce_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func TestAutoAnnounce(t *testing.T) {
4848
}
4949
defer storage.Close()
5050

51-
sm, err := settings.NewConfigManager(hostKey, node.Store, node.Chain, node.Syncer, wm, settings.WithLog(log.Named("settings")), settings.WithAnnounceInterval(50))
51+
sm, err := settings.NewConfigManager(hostKey, node.Store, node.Chain, node.Syncer, vm, wm, settings.WithLog(log.Named("settings")), settings.WithAnnounceInterval(50))
5252
if err != nil {
5353
t.Fatal(err)
5454
}
@@ -186,7 +186,7 @@ func TestAutoAnnounceV2(t *testing.T) {
186186
}
187187
defer storage.Close()
188188

189-
sm, err := settings.NewConfigManager(hostKey, node.Store, node.Chain, node.Syncer, wm, settings.WithLog(log.Named("settings")), settings.WithAnnounceInterval(50))
189+
sm, err := settings.NewConfigManager(hostKey, node.Store, node.Chain, node.Syncer, vm, wm, settings.WithLog(log.Named("settings")), settings.WithAnnounceInterval(50))
190190
if err != nil {
191191
t.Fatal(err)
192192
}

host/settings/options.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,11 @@ func WithInitialSettings(settings Settings) Option {
4646
c.initialSettings = settings
4747
}
4848
}
49+
50+
// WithRHP3Port sets the port that the host is listening for
51+
// RHP3 connections on. This is part of the RHP2 settings.
52+
func WithRHP3Port(port uint16) Option {
53+
return func(c *ConfigManager) {
54+
c.rhp3Port = port
55+
}
56+
}

host/settings/pin/pin_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func TestPinnedFields(t *testing.T) {
119119
currency: "usd",
120120
}
121121

122-
sm, err := settings.NewConfigManager(types.GeneratePrivateKey(), node.Store, node.Chain, node.Syncer, nil)
122+
sm, err := settings.NewConfigManager(types.GeneratePrivateKey(), node.Store, node.Chain, node.Syncer, nil, nil)
123123
if err != nil {
124124
t.Fatal(err)
125125
}
@@ -218,7 +218,7 @@ func TestAutomaticUpdate(t *testing.T) {
218218
currency: "usd",
219219
}
220220

221-
sm, err := settings.NewConfigManager(types.GeneratePrivateKey(), node.Store, node.Chain, node.Syncer, nil)
221+
sm, err := settings.NewConfigManager(types.GeneratePrivateKey(), node.Store, node.Chain, node.Syncer, nil, nil)
222222
if err != nil {
223223
t.Fatal(err)
224224
}

host/settings/settings.go

Lines changed: 142 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,25 @@ package settings
22

33
import (
44
"crypto/ed25519"
5-
"crypto/tls"
65
"errors"
76
"fmt"
87
"net"
8+
"strconv"
99
"strings"
1010
"sync"
1111
"time"
1212

1313
"go.sia.tech/core/consensus"
14+
proto2 "go.sia.tech/core/rhp/v2"
15+
proto3 "go.sia.tech/core/rhp/v3"
1416
"go.sia.tech/core/types"
1517
"go.sia.tech/hostd/alerts"
18+
"go.sia.tech/hostd/build"
1619
"go.sia.tech/hostd/internal/threadgroup"
20+
rhp2 "go.sia.tech/hostd/rhp/v2"
1721
"go.uber.org/zap"
1822
"golang.org/x/time/rate"
23+
"lukechampine.com/frand"
1924
)
2025

2126
const (
@@ -67,6 +72,11 @@ type (
6772
BroadcastV2TransactionSet(types.ChainIndex, []types.V2Transaction)
6873
}
6974

75+
// Storage provides information about the host's storage capacity
76+
Storage interface {
77+
Usage() (used, total uint64, _ error)
78+
}
79+
7080
// A Wallet manages Siacoins and funds transactions
7181
Wallet interface {
7282
Address() types.Address
@@ -135,9 +145,10 @@ type (
135145
a Alerts
136146
log *zap.Logger
137147

138-
chain ChainManager
139-
syncer Syncer
140-
wallet Wallet
148+
chain ChainManager
149+
syncer Syncer
150+
storage Storage
151+
wallet Wallet
141152

142153
mu sync.Mutex // guards the following fields
143154
settings Settings // in-memory cache of the host's settings
@@ -150,7 +161,7 @@ type (
150161
lastIPv4 net.IP
151162
lastIPv6 net.IP
152163

153-
rhp3WSTLS *tls.Config
164+
rhp3Port uint16
154165

155166
tg *threadgroup.ThreadGroup
156167
}
@@ -258,18 +269,138 @@ func (m *ConfigManager) BandwidthLimiters() (ingress, egress *rate.Limiter) {
258269
return m.ingressLimit, m.egressLimit
259270
}
260271

272+
// AcceptingContracts returns true if the host is currently accepting contracts
273+
func (m *ConfigManager) AcceptingContracts() bool {
274+
s := m.Settings()
275+
return s.AcceptingContracts
276+
}
277+
278+
// RHP2Settings returns the host's current RHP2 settings
279+
func (m *ConfigManager) RHP2Settings() (proto2.HostSettings, error) {
280+
usedSectors, totalSectors, err := m.storage.Usage()
281+
if err != nil {
282+
return proto2.HostSettings{}, fmt.Errorf("failed to get storage usage: %w", err)
283+
}
284+
settings := m.Settings()
285+
286+
return proto2.HostSettings{
287+
// build info
288+
Release: "hostd " + build.Version(),
289+
// protocol version
290+
Version: rhp2.Version,
291+
292+
// host info
293+
Address: m.wallet.Address(),
294+
SiaMuxPort: strconv.FormatUint(uint64(m.rhp3Port), 10),
295+
NetAddress: settings.NetAddress,
296+
TotalStorage: totalSectors * proto2.SectorSize,
297+
RemainingStorage: (totalSectors - usedSectors) * proto2.SectorSize,
298+
299+
// network defaults
300+
MaxDownloadBatchSize: rhp2.DefaultBatchSize,
301+
MaxReviseBatchSize: rhp2.DefaultBatchSize,
302+
SectorSize: proto2.SectorSize,
303+
WindowSize: settings.WindowSize,
304+
305+
// contract formation
306+
AcceptingContracts: settings.AcceptingContracts,
307+
MaxDuration: settings.MaxContractDuration,
308+
ContractPrice: settings.ContractPrice,
309+
310+
// rpc prices
311+
BaseRPCPrice: settings.BaseRPCPrice,
312+
SectorAccessPrice: settings.SectorAccessPrice,
313+
Collateral: settings.StoragePrice.Mul64(uint64(settings.CollateralMultiplier * 1000)).Div64(1000),
314+
MaxCollateral: settings.MaxCollateral,
315+
StoragePrice: settings.StoragePrice,
316+
DownloadBandwidthPrice: settings.EgressPrice,
317+
UploadBandwidthPrice: settings.IngressPrice,
318+
319+
// ea settings
320+
MaxEphemeralAccountBalance: settings.MaxAccountBalance,
321+
EphemeralAccountExpiry: settings.AccountExpiry,
322+
323+
RevisionNumber: settings.Revision,
324+
}, nil
325+
}
326+
327+
// RHP3PriceTable returns the host's current RHP3 price table
328+
func (m *ConfigManager) RHP3PriceTable() (proto3.HostPriceTable, error) {
329+
settings := m.Settings()
330+
331+
fee := m.chain.RecommendedFee()
332+
currentHeight := m.chain.TipState().Index.Height
333+
oneHasting := types.NewCurrency64(1)
334+
335+
return proto3.HostPriceTable{
336+
UID: frand.Entropy128(),
337+
HostBlockHeight: currentHeight,
338+
Validity: settings.PriceTableValidity,
339+
340+
// ephemeral account costs
341+
AccountBalanceCost: oneHasting,
342+
FundAccountCost: oneHasting,
343+
UpdatePriceTableCost: oneHasting,
344+
345+
// MDM costs
346+
HasSectorBaseCost: oneHasting,
347+
MemoryTimeCost: oneHasting,
348+
DropSectorsBaseCost: oneHasting,
349+
DropSectorsUnitCost: oneHasting,
350+
SwapSectorBaseCost: oneHasting,
351+
352+
ReadBaseCost: settings.SectorAccessPrice,
353+
ReadLengthCost: oneHasting,
354+
WriteBaseCost: settings.SectorAccessPrice,
355+
WriteLengthCost: oneHasting,
356+
WriteStoreCost: settings.StoragePrice,
357+
InitBaseCost: settings.BaseRPCPrice,
358+
359+
// bandwidth costs
360+
DownloadBandwidthCost: settings.EgressPrice,
361+
UploadBandwidthCost: settings.IngressPrice,
362+
363+
// LatestRevisionCost is set to a reasonable base + the estimated
364+
// bandwidth cost of downloading a filecontract. This isn't perfect but
365+
// at least scales a bit as the host updates their download bandwidth
366+
// prices.
367+
LatestRevisionCost: settings.BaseRPCPrice.Add(settings.EgressPrice.Mul64(2048)),
368+
369+
// Contract Formation/Renewal related fields
370+
ContractPrice: settings.ContractPrice,
371+
CollateralCost: settings.StoragePrice.Mul64(uint64(settings.CollateralMultiplier * 1000)).Div64(1000),
372+
MaxCollateral: settings.MaxCollateral,
373+
MaxDuration: settings.MaxContractDuration,
374+
WindowSize: settings.WindowSize,
375+
RenewContractCost: types.Siacoins(100).Div64(1e9),
376+
377+
// Registry related fields.
378+
RegistryEntriesLeft: 0,
379+
RegistryEntriesTotal: 0,
380+
381+
// Subscription related fields.
382+
SubscriptionMemoryCost: oneHasting,
383+
SubscriptionNotificationCost: oneHasting,
384+
385+
// TxnFee related fields.
386+
TxnFeeMinRecommended: fee.Div64(3),
387+
TxnFeeMaxRecommended: fee,
388+
}, nil
389+
}
390+
261391
// NewConfigManager initializes a new config manager
262-
func NewConfigManager(hostKey types.PrivateKey, store Store, cm ChainManager, s Syncer, wm Wallet, opts ...Option) (*ConfigManager, error) {
392+
func NewConfigManager(hostKey types.PrivateKey, store Store, cm ChainManager, s Syncer, sm Storage, wm Wallet, opts ...Option) (*ConfigManager, error) {
263393
m := &ConfigManager{
264394
announceInterval: 144 * 90, // 90 days
265395
validateNetAddress: true,
266396
hostKey: hostKey,
267397
initialSettings: DefaultSettings,
268398

269-
store: store,
270-
chain: cm,
271-
syncer: s,
272-
wallet: wm,
399+
store: store,
400+
chain: cm,
401+
syncer: s,
402+
storage: sm,
403+
wallet: wm,
273404

274405
log: zap.NewNop(),
275406
a: alerts.NewNop(),
@@ -279,8 +410,7 @@ func NewConfigManager(hostKey types.PrivateKey, store Store, cm ChainManager, s
279410
ingressLimit: rate.NewLimiter(rate.Inf, defaultBurstSize),
280411
egressLimit: rate.NewLimiter(rate.Inf, defaultBurstSize),
281412

282-
// rhp3 WebSocket TLS
283-
rhp3WSTLS: &tls.Config{},
413+
rhp3Port: 9983,
284414
}
285415

286416
for _, opt := range opts {

host/settings/settings_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func TestSettings(t *testing.T) {
4141
}
4242
defer contracts.Close()
4343

44-
sm, err := settings.NewConfigManager(hostKey, node.Store, node.Chain, node.Syncer, wm, settings.WithLog(log.Named("settings")), settings.WithAnnounceInterval(50), settings.WithValidateNetAddress(false))
44+
sm, err := settings.NewConfigManager(hostKey, node.Store, node.Chain, node.Syncer, vm, wm, settings.WithLog(log.Named("settings")), settings.WithAnnounceInterval(50), settings.WithValidateNetAddress(false))
4545
if err != nil {
4646
t.Fatal(err)
4747
}

internal/testutil/testutil.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ func NewHostNode(t *testing.T, pk types.PrivateKey, network *consensus.Network,
188188
initialSettings.AcceptingContracts = true
189189
initialSettings.NetAddress = "127.0.0.1:9981"
190190
initialSettings.WindowSize = 10
191-
sm, err := settings.NewConfigManager(pk, cn.Store, cn.Chain, cn.Syncer, wm, settings.WithAnnounceInterval(10), settings.WithValidateNetAddress(false), settings.WithInitialSettings(initialSettings))
191+
sm, err := settings.NewConfigManager(pk, cn.Store, cn.Chain, cn.Syncer, vm, wm, settings.WithAnnounceInterval(10), settings.WithValidateNetAddress(false), settings.WithInitialSettings(initialSettings))
192192
if err != nil {
193193
t.Fatal(err)
194194
}

0 commit comments

Comments
 (0)