forked from NebulousLabs/Sia
/
announce.go
157 lines (137 loc) · 4.1 KB
/
announce.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
package host
import (
"errors"
"github.com/NebulousLabs/Sia/build"
"github.com/NebulousLabs/Sia/modules"
)
var (
// errAnnWalletLocked is returned during a host announcement if the wallet
// is locked.
errAnnWalletLocked = errors.New("cannot announce the host while the wallet is locked")
// errUnknownAddress is returned if the host is unable to determine a
// public address for itself to use in the announcement.
errUnknownAddress = errors.New("host cannot announce, does not seem to have a valid address")
)
// managedAnnounce creates an announcement transaction and submits it to the network.
func (h *Host) managedAnnounce(addr modules.NetAddress) (err error) {
// The wallet needs to be unlocked to add fees to the transaction, and the
// host needs to have an active unlock hash that renters can make payment
// to.
unlocked, err := h.wallet.Unlocked()
if err != nil {
return err
}
if !unlocked {
return errAnnWalletLocked
}
h.mu.Lock()
pubKey := h.publicKey
secKey := h.secretKey
err = h.checkUnlockHash()
h.mu.Unlock()
if err != nil {
return err
}
// Create the announcement that's going to be added to the arbitrary data
// field of the transaction.
signedAnnouncement, err := modules.CreateAnnouncement(addr, pubKey, secKey)
if err != nil {
return err
}
// Create a transaction, with a fee, that contains the full announcement.
txnBuilder, err := h.wallet.StartTransaction()
if err != nil {
return err
}
defer func() {
if err != nil {
txnBuilder.Drop()
}
}()
_, fee := h.tpool.FeeEstimation()
fee = fee.Mul64(600) // Estimated txn size (in bytes) of a host announcement.
err = txnBuilder.FundSiacoins(fee)
if err != nil {
return err
}
_ = txnBuilder.AddMinerFee(fee)
_ = txnBuilder.AddArbitraryData(signedAnnouncement)
txnSet, err := txnBuilder.Sign(true)
if err != nil {
return err
}
// Add the transactions to the transaction pool.
err = h.tpool.AcceptTransactionSet(txnSet)
if err != nil {
return err
}
h.mu.Lock()
h.announced = true
h.mu.Unlock()
h.log.Printf("INFO: Successfully announced as %v", addr)
return nil
}
// Announce creates a host announcement transaction.
func (h *Host) Announce() error {
err := h.tg.Add()
if err != nil {
return err
}
defer h.tg.Done()
// Grab the internal net address and internal auto address, and compare
// them.
h.mu.RLock()
userSet := h.settings.NetAddress
autoSet := h.autoAddress
h.mu.RUnlock()
// Check that we have at least one address to work with.
if userSet == "" && autoSet == "" {
return build.ExtendErr("cannot announce because address could not be determined", err)
}
// Prefer using the userSet address, otherwise use the automatic address.
var annAddr modules.NetAddress
if userSet != "" {
annAddr = userSet
} else {
annAddr = autoSet
}
// Check that the address is sane, and that the address is also not local.
err = annAddr.IsStdValid()
if err != nil {
return build.ExtendErr("announcement requested with bad net address", err)
}
if annAddr.IsLocal() && build.Release != "testing" {
return errors.New("announcement requested with local net address")
}
// Address has cleared inspection, perform the announcement.
return h.managedAnnounce(annAddr)
}
// AnnounceAddress submits a host announcement to the blockchain to announce a
// specific address. If there is no error, the host's address will be updated
// to the supplied address.
func (h *Host) AnnounceAddress(addr modules.NetAddress) error {
err := h.tg.Add()
if err != nil {
return err
}
defer h.tg.Done()
// Check that the address is sane, and that the address is also not local.
err = addr.IsStdValid()
if err != nil {
return build.ExtendErr("announcement requested with bad net address", err)
}
if addr.IsLocal() {
return errors.New("announcement requested with local net address")
}
// Attempt the actual announcement.
err = h.managedAnnounce(addr)
if err != nil {
return build.ExtendErr("unable to perform manual host announcement", err)
}
// Address is valid, update the host's internal net address to match the
// specified addr.
h.mu.Lock()
h.settings.NetAddress = addr
h.mu.Unlock()
return nil
}