func CreateAnnouncement(addr NetAddress, pk types.SiaPublicKey, sk crypto.SecretKey) (signedAnnouncement []byte, err error) {
	if err := addr.IsValid(); err != nil {
		return nil, err
	}
	annBytes := encoding.Marshal(HostAnnouncement{
		Specifier:  PrefixHostAnnouncement,
		NetAddress: addr,
		PublicKey:  pk,
	})
	annHash := crypto.HashBytes(annBytes)
	sig := crypto.SignHash(annHash, sk)
	return append(annBytes, sig[:]...), nil
}
CreateAnnouncement will take a host announcement and encode it, returning
the exact []byte that should be added to the arbitrary data of a
transaction.
package modules
import (
	"bytes"
	"errors"
	"io"
	"time"
	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/encoding"
	"github.com/NebulousLabs/Sia/types"
)
const (
	AcceptResponse = "accept"
	StopResponse = "stop"
)
const (
	NegotiateDownloadTime = 600 * time.Second
	NegotiateFileContractRevisionTime = 600 * time.Second
	NegotiateFileContractTime = 360 * time.Second
	NegotiateMaxDownloadActionRequestSize = 50e3
	NegotiateMaxErrorSize = 256
	NegotiateMaxFileContractRevisionSize = 3e3
	NegotiateMaxFileContractSetLen = TransactionSetSizeLimit - 1e3
	NegotiateMaxHostExternalSettingsLen = 16000
	NegotiateMaxSiaPubkeySize = 1e3
	NegotiateMaxTransactionSignatureSize = 2e3
	NegotiateMaxTransactionSignaturesSize = 5e3
	NegotiateRecentRevisionTime = 120 * time.Second
	NegotiateRenewContractTime = 600 * time.Second
)
var (
	NegotiateSettingsTime = build.Select(build.Var{
		Dev:      120 * time.Second,
		Standard: 120 * time.Second,
		Testing:  3 * time.Second,
	}).(time.Duration)
)
var (
	ActionDelete = types.Specifier{'D', 'e', 'l', 'e', 't', 'e'}
	ActionInsert = types.Specifier{'I', 'n', 's', 'e', 'r', 't'}
	ActionModify = types.Specifier{'M', 'o', 'd', 'i', 'f', 'y'}
	ErrAnnNotAnnouncement = errors.New("provided data does not form a recognized host announcement")
	ErrAnnUnrecognizedSignature = errors.New("the signature provided in the host announcement is not recognized")
	ErrRevisionCoveredFields = errors.New("file contract revision transaction signature does not allow miner fees to be added")
	ErrRevisionSigCount = errors.New("file contract revision has the wrong number of transaction signatures")
	ErrStopResponse = errors.New("sender wishes to stop communicating")
	PrefixHostAnnouncement = types.Specifier{'H', 'o', 's', 't', 'A', 'n', 'n', 'o', 'u', 'n', 'c', 'e', 'm', 'e', 'n', 't'}
	RPCDownload = types.Specifier{'D', 'o', 'w', 'n', 'l', 'o', 'a', 'd', 2}
	RPCFormContract = types.Specifier{'F', 'o', 'r', 'm', 'C', 'o', 'n', 't', 'r', 'a', 'c', 't', 2}
	RPCRenewContract = types.Specifier{'R', 'e', 'n', 'e', 'w', 'C', 'o', 'n', 't', 'r', 'a', 'c', 't', 2}
	RPCReviseContract = types.Specifier{'R', 'e', 'v', 'i', 's', 'e', 'C', 'o', 'n', 't', 'r', 'a', 'c', 't', 2}
	RPCSettings = types.Specifier{'S', 'e', 't', 't', 'i', 'n', 'g', 's', 2}
	SectorSize = build.Select(build.Var{
		Dev:      uint64(1 << 18),  
		Standard: uint64(1 << 22),  
		Testing:  uint64(1 << 12),  
	}).(uint64)
)
type (
	DownloadAction struct {
		MerkleRoot crypto.Hash
		Offset     uint64
		Length     uint64
	}
	HostAnnouncement struct {
		Specifier  types.Specifier
		NetAddress NetAddress
		PublicKey  types.SiaPublicKey
	}
	HostExternalSettings struct {
		AcceptingContracts   bool              `json:"acceptingcontracts"`
		MaxDownloadBatchSize uint64            `json:"maxdownloadbatchsize"`
		MaxDuration          types.BlockHeight `json:"maxduration"`
		MaxReviseBatchSize   uint64            `json:"maxrevisebatchsize"`
		NetAddress           NetAddress        `json:"netaddress"`
		RemainingStorage     uint64            `json:"remainingstorage"`
		SectorSize           uint64            `json:"sectorsize"`
		TotalStorage         uint64            `json:"totalstorage"`
		UnlockHash           types.UnlockHash  `json:"unlockhash"`
		WindowSize           types.BlockHeight `json:"windowsize"`
		Collateral    types.Currency `json:"collateral"`
		MaxCollateral types.Currency `json:"maxcollateral"`
		ContractPrice          types.Currency `json:"contractprice"`
		DownloadBandwidthPrice types.Currency `json:"downloadbandwidthprice"`
		StoragePrice           types.Currency `json:"storageprice"`
		UploadBandwidthPrice   types.Currency `json:"uploadbandwidthprice"`
		RevisionNumber uint64 `json:"revisionnumber"`
		Version        string `json:"version"`
	}
	RevisionAction struct {
		Type        types.Specifier
		SectorIndex uint64
		Offset      uint64
		Data        []byte
	}
)
func ReadNegotiationAcceptance(r io.Reader) error {
	var resp string
	err := encoding.ReadObject(r, &resp, NegotiateMaxErrorSize)
	if err != nil {
		return err
	}
	switch resp {
	case AcceptResponse:
		return nil
	case StopResponse:
		return ErrStopResponse
	default:
		return errors.New(resp)
	}
}
func WriteNegotiationAcceptance(w io.Writer) error {
	return encoding.WriteObject(w, AcceptResponse)
}
func WriteNegotiationRejection(w io.Writer, err error) error {
	writeErr := encoding.WriteObject(w, err.Error())
	if writeErr != nil {
		return build.JoinErrors([]error{err, writeErr}, "; ")
	}
	return err
}
func WriteNegotiationStop(w io.Writer) error {
	return encoding.WriteObject(w, StopResponse)
}