github.com/nebulouslabs/sia@v1.3.7/modules/host/announce.go (about) 1 package host 2 3 import ( 4 "errors" 5 6 "github.com/NebulousLabs/Sia/build" 7 "github.com/NebulousLabs/Sia/modules" 8 ) 9 10 var ( 11 // errAnnWalletLocked is returned during a host announcement if the wallet 12 // is locked. 13 errAnnWalletLocked = errors.New("cannot announce the host while the wallet is locked") 14 15 // errUnknownAddress is returned if the host is unable to determine a 16 // public address for itself to use in the announcement. 17 errUnknownAddress = errors.New("host cannot announce, does not seem to have a valid address") 18 ) 19 20 // managedAnnounce creates an announcement transaction and submits it to the network. 21 func (h *Host) managedAnnounce(addr modules.NetAddress) (err error) { 22 // The wallet needs to be unlocked to add fees to the transaction, and the 23 // host needs to have an active unlock hash that renters can make payment 24 // to. 25 unlocked, err := h.wallet.Unlocked() 26 if err != nil { 27 return err 28 } 29 if !unlocked { 30 return errAnnWalletLocked 31 } 32 33 h.mu.Lock() 34 pubKey := h.publicKey 35 secKey := h.secretKey 36 err = h.checkUnlockHash() 37 h.mu.Unlock() 38 if err != nil { 39 return err 40 } 41 42 // Create the announcement that's going to be added to the arbitrary data 43 // field of the transaction. 44 signedAnnouncement, err := modules.CreateAnnouncement(addr, pubKey, secKey) 45 if err != nil { 46 return err 47 } 48 49 // Create a transaction, with a fee, that contains the full announcement. 50 txnBuilder, err := h.wallet.StartTransaction() 51 if err != nil { 52 return err 53 } 54 defer func() { 55 if err != nil { 56 txnBuilder.Drop() 57 } 58 }() 59 _, fee := h.tpool.FeeEstimation() 60 fee = fee.Mul64(600) // Estimated txn size (in bytes) of a host announcement. 61 err = txnBuilder.FundSiacoins(fee) 62 if err != nil { 63 return err 64 } 65 _ = txnBuilder.AddMinerFee(fee) 66 _ = txnBuilder.AddArbitraryData(signedAnnouncement) 67 txnSet, err := txnBuilder.Sign(true) 68 if err != nil { 69 return err 70 } 71 72 // Add the transactions to the transaction pool. 73 err = h.tpool.AcceptTransactionSet(txnSet) 74 if err != nil { 75 return err 76 } 77 78 h.mu.Lock() 79 h.announced = true 80 h.mu.Unlock() 81 h.log.Printf("INFO: Successfully announced as %v", addr) 82 return nil 83 } 84 85 // Announce creates a host announcement transaction. 86 func (h *Host) Announce() error { 87 err := h.tg.Add() 88 if err != nil { 89 return err 90 } 91 defer h.tg.Done() 92 93 // Grab the internal net address and internal auto address, and compare 94 // them. 95 h.mu.RLock() 96 userSet := h.settings.NetAddress 97 autoSet := h.autoAddress 98 h.mu.RUnlock() 99 100 // Check that we have at least one address to work with. 101 if userSet == "" && autoSet == "" { 102 return build.ExtendErr("cannot announce because address could not be determined", err) 103 } 104 105 // Prefer using the userSet address, otherwise use the automatic address. 106 var annAddr modules.NetAddress 107 if userSet != "" { 108 annAddr = userSet 109 } else { 110 annAddr = autoSet 111 } 112 113 // Check that the address is sane, and that the address is also not local. 114 err = annAddr.IsStdValid() 115 if err != nil { 116 return build.ExtendErr("announcement requested with bad net address", err) 117 } 118 if annAddr.IsLocal() && build.Release != "testing" { 119 return errors.New("announcement requested with local net address") 120 } 121 122 // Address has cleared inspection, perform the announcement. 123 return h.managedAnnounce(annAddr) 124 } 125 126 // AnnounceAddress submits a host announcement to the blockchain to announce a 127 // specific address. If there is no error, the host's address will be updated 128 // to the supplied address. 129 func (h *Host) AnnounceAddress(addr modules.NetAddress) error { 130 err := h.tg.Add() 131 if err != nil { 132 return err 133 } 134 defer h.tg.Done() 135 136 // Check that the address is sane, and that the address is also not local. 137 err = addr.IsStdValid() 138 if err != nil { 139 return build.ExtendErr("announcement requested with bad net address", err) 140 } 141 if addr.IsLocal() { 142 return errors.New("announcement requested with local net address") 143 } 144 145 // Attempt the actual announcement. 146 err = h.managedAnnounce(addr) 147 if err != nil { 148 return build.ExtendErr("unable to perform manual host announcement", err) 149 } 150 151 // Address is valid, update the host's internal net address to match the 152 // specified addr. 153 h.mu.Lock() 154 h.settings.NetAddress = addr 155 h.mu.Unlock() 156 return nil 157 }