forked from NebulousLabs/Sia
/
host.go
171 lines (144 loc) · 6.82 KB
/
host.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package modules
import (
"github.com/NebulousLabs/Sia/types"
)
const (
// AcceptResponse defines the response that is sent to a successful RPC.
AcceptResponse = "accept"
// HostDir names the directory that contains the host persistence.
HostDir = "host"
// MaxFileContractSetLen determines the maximum allowed size of a
// transaction set that can be sent when trying to negotiate a file
// contract. The transaction set will contain all of the unconfirmed
// dependencies of the file contract, meaning that it can be quite large.
// The transaction pool's size limit for transaction sets has been chosen
// as a reasonable guideline for determining what is too large.
MaxFileContractSetLen = TransactionSetSizeLimit - 1e3
)
var (
// RPCSettings is the specifier for requesting settings from the host.
RPCSettings = types.Specifier{'S', 'e', 't', 't', 'i', 'n', 'g', 's'}
// RPCUpload is the specifier for initiating an upload with the host.
RPCUpload = types.Specifier{'U', 'p', 'l', 'o', 'a', 'd'}
// RPCRenew is the specifier to renewing an existing contract.
RPCRenew = types.Specifier{'R', 'e', 'n', 'e', 'w'}
// RPCRevise is the specifier for revising an existing file contract.
RPCRevise = types.Specifier{'R', 'e', 'v', 'i', 's', 'e'}
// RPCDownload is the specifier for downloading a file from a host.
RPCDownload = types.Specifier{'D', 'o', 'w', 'n', 'l', 'o', 'a', 'd'}
// PrefixHostAnnouncement is used to indicate that a transaction's
// Arbitrary Data field contains a host announcement. The encoded
// announcement will follow this prefix.
PrefixHostAnnouncement = types.Specifier{'H', 'o', 's', 't', 'A', 'n', 'n', 'o', 'u', 'n', 'c', 'e', 'm', 'e', 'n', 't'}
)
type (
// A DownloadRequest is used to retrieve a particular segment of a file from a
// host.
DownloadRequest struct {
Offset uint64
Length uint64
}
// HostAnnouncement declares a nodes intent to be a host, providing a net
// address that can be used to contact the host.
HostAnnouncement struct {
IPAddress NetAddress
}
// HostSettings are the parameters advertised by the host. These are the
// values that the renter will request from the host in order to build its
// database.
HostSettings struct {
AcceptingContracts bool `json:"acceptingcontracts"`
NetAddress NetAddress `json:"netaddress"`
TotalStorage int64 `json:"totalstorage"`
MinDuration types.BlockHeight `json:"minduration"`
MaxDuration types.BlockHeight `json:"maxduration"`
WindowSize types.BlockHeight `json:"windowsize"`
Price types.Currency `json:"price"`
Collateral types.Currency `json:"collateral"`
UnlockHash types.UnlockHash `json:"unlockhash"`
}
// HostRPCMetrics reports the quantity of each type of RPC call that has
// been made to the host.
HostRPCMetrics struct {
ErrorCalls uint64 `json:"errorcalls"` // Calls that resulted in an error.
UnrecognizedCalls uint64 `json:"unrecognizedcalls"`
DownloadCalls uint64 `json:"downloadcalls"`
RenewCalls uint64 `json:"renewcalls"`
ReviseCalls uint64 `json:"revisecalls"`
SettingsCalls uint64 `json:"settingscalls"`
UploadCalls uint64 `json:"uploadcalls"`
}
// Host can take storage from disk and offer it to the network, managing things
// such as announcements, settings, and implementing all of the RPCs of the
// host protocol.
Host interface {
// Announce submits a host announcement to the blockchain, returning an
// error if its external IP address is unknown. After announcing, the
// host will begin accepting contracts.
Announce() error
// AnnounceAddress behaves like Announce, but allows the caller to
// specify the address announced. Like Announce, this will cause the
// host to start accepting contracts.
AnnounceAddress(NetAddress) error
// Capacity returns the amount of storage still available on the
// machine. The amount can be negative if the total capacity was
// reduced to below the active capacity.
Capacity() int64
// Contracts returns the number of unresolved file contracts that the
// host is responsible for.
Contracts() uint64
// DeleteContract deletes a file contract. The revenue and collateral
// on the file contract will be lost, and the data will be removed.
DeleteContract(types.FileContractID) error
// NetAddress returns the host's network address
NetAddress() NetAddress
// Revenue returns the amount of revenue that the host has lined up,
// the amount of revenue the host has successfully captured, and the
// amount of revenue the host has lost.
//
// TODO: This function will eventually include two more numbers, one
// representing current collateral at risk, and one representing total
// collateral lost.
Revenue() (unresolved, resolved, lost types.Currency)
// RPCMetrics returns information on the types of RPC calls that have
// been made to the host.
RPCMetrics() HostRPCMetrics
// SetConfig sets the hosting parameters of the host.
SetSettings(HostSettings) error
// Settings returns the host's settings.
Settings() HostSettings
// Close saves the state of the host and stops its listener process.
Close() error
}
)
// StoragePriceToConsensus converts a human storage price, having the unit
// 'Siacoins Per Month Per Terabyte', to a consensus storage price, having the
// unit 'Hastings Per Block Per Byte'.
func StoragePriceToConsensus(siacoinsMonthTB uint64) (hastingsBlockByte types.Currency) {
// Perform multiplication first to preserve precision.
hastingsMonthTB := types.NewCurrency64(siacoinsMonthTB).Mul(types.SiacoinPrecision)
hastingsBlockTB := hastingsMonthTB.Div(types.NewCurrency64(4320))
hastingsBlockByte = hastingsBlockTB.Div(types.NewCurrency64(1e12))
return hastingsBlockByte
}
// StoragePriceToHuman converts a consensus storage price, having the unit
// 'Hastings Per Block Per Byte', to a human storage price, having the unit
// 'Siacoins Per Month Per Terabyte'. An error is returned if the result would
// overflow a uint64. If the result is between 0 and 1, the value is rounded to
// the nearest value.
func StoragePriceToHuman(hastingsBlockByte types.Currency) (siacoinsMonthTB uint64, err error) {
// Perform multiplication first to preserve precision.
hastingsMonthByte := hastingsBlockByte.Mul(types.NewCurrency64(4320))
hastingsMonthTB := hastingsMonthByte.Mul(types.NewCurrency64(1e12))
if hastingsMonthTB.Cmp(types.SiacoinPrecision.Div(types.NewCurrency64(2))) < 0 {
// The result of the final division is going to be less than 0.5,
// therefore 0 should be returned.
return 0, nil
}
if hastingsMonthTB.Cmp(types.SiacoinPrecision) < 0 {
// The result of the final division is going to be greater than or
// equal to 0.5, but less than 1, therefore 1 should be returned.
return 1, nil
}
return hastingsMonthTB.Div(types.SiacoinPrecision).Uint64()
}