Commit 5923a2d3 authored by Luke Champine's avatar Luke Champine

implement Announce

parent ec41feb6
......@@ -4,6 +4,7 @@ import (
"net"
"github.com/NebulousLabs/Sia/consensus"
"github.com/NebulousLabs/Sia/network"
)
const (
......@@ -11,19 +12,21 @@ const (
)
type Host interface {
// Announce puts an annoucement out so that clients can find the host.
AnnounceHost(freezeVolume consensus.Currency, freezeUnlockHeight consensus.BlockHeight) (consensus.Transaction, error)
// Announce announces the host on the blockchain. A host announcement
// requires two things: the host's address, and a volume of "frozen"
// (time-locked) coins, used to mitigate Sybil attacks.
Announce(network.Address, consensus.Currency, consensus.BlockHeight) error
// NegotiateContract is a strict function that enables a client to
// communicate with the host to propose a contract.
//
// TODO: enhance this documentataion. For now, see the host package for a
// reference implementation.
NegotiateContract(conn net.Conn) error
NegotiateContract(net.Conn) error
// RetrieveFile is a strict function that enables a client to download a
// file from a host.
RetrieveFile(conn net.Conn) error
RetrieveFile(net.Conn) error
// Returns the number of contracts being managed by the host.
//
......
......@@ -2,46 +2,65 @@ package host
import (
"github.com/NebulousLabs/Sia/consensus"
// "github.com/NebulousLabs/Sia/encoding"
// "github.com/NebulousLabs/Sia/sia/components"
"github.com/NebulousLabs/Sia/encoding"
"github.com/NebulousLabs/Sia/modules"
"github.com/NebulousLabs/Sia/network"
)
// HostAnnounceSelf creates a host announcement transaction, adding
// information to the arbitrary data and then signing the transaction.
func (h *Host) AnnounceHost(freezeVolume consensus.Currency, freezeUnlockHeight consensus.BlockHeight) (t consensus.Transaction, err error) {
// Announce creates a host announcement transaction, adding information to the
// arbitrary data, signing the transaction, and submitting it to the
// transaction pool.
func (h *Host) Announce(addr network.Address, freezeVolume consensus.Currency, freezeDuration consensus.BlockHeight) (err error) {
h.mu.Lock()
defer h.mu.Unlock()
/*
// Get the encoded announcement based on the host settings.
info := h.announcement
// Fill out the transaction.
id, err := h.wallet.RegisterTransaction(t)
if err != nil {
return
}
err = h.wallet.FundTransaction(id, freezeVolume)
if err != nil {
return
}
info.SpendConditions, info.FreezeIndex, err = h.wallet.AddTimelockedRefund(id, freezeVolume, freezeUnlockHeight)
if err != nil {
return
}
announcement := string(encoding.MarshalAll(components.HostAnnouncementPrefix, info))
err = h.wallet.AddArbitraryData(id, announcement)
if err != nil {
return
}
// TODO: Have the wallet manually add a fee? How should this be managed?
t, err = h.wallet.SignTransaction(id, true)
if err != nil {
return
}
h.state.AcceptTransaction(t)
*/
// get current state height
h.state.RLock()
freezeUnlockHeight := h.state.Height() + freezeDuration
h.state.RUnlock()
// create the transaction that will hold the announcement
var t consensus.Transaction
id, err := h.wallet.RegisterTransaction(t)
if err != nil {
return
}
err = h.wallet.FundTransaction(id, freezeVolume)
if err != nil {
return
}
spendHash, spendConditions, err := h.wallet.TimelockedCoinAddress(freezeUnlockHeight)
if err != nil {
return
}
output := consensus.Output{
Value: freezeVolume,
SpendHash: spendHash,
}
freezeIndex, err := h.wallet.AddOutput(id, output)
if err != nil {
return
}
// create and encode the announcement
announcement := encoding.Marshal(modules.HostAnnouncement{
IPAddress: addr,
FreezeIndex: freezeIndex,
SpendConditions: spendConditions,
})
// add announcement to arbitrary data field
err = h.wallet.AddArbitraryData(id, modules.HostAnnouncementPrefix+string(announcement))
if err != nil {
return
}
// TODO: Have the wallet manually add a fee? How should this be managed?
t, err = h.wallet.SignTransaction(id, true)
if err != nil {
return
}
h.tpool.AcceptTransaction(t)
return
}
......@@ -19,16 +19,25 @@ var (
hostSetCmd = &cobra.Command{
Use: "set [setting] [value]",
Short: "Modify host settings",
Long: "Modify host settings.\nAvailable settings:\n\ttotalstorage\n\tmaxfilesize\n\tmintolerance\n\tmaxduration\n\tprice\n\tburn",
Run: wrap(hostsetcmd),
Long: `Modify host settings.
Available settings:
totalstorage
maxfilesize
mintolerance
maxduration
price
burn`,
Run: wrap(hostsetcmd),
}
hostAnnounceCmd = &cobra.Command{
Use: "announce",
Short: "Announce host",
Long: "Announce yourself as a host on the network. You may wish to set your hosting parameters first, via 'host setconfig'.",
Run: wrap(hostannouncecmd),
}
Use: "announce [freezeVolume] [freezeDuration]",
Short: "Announce yourself as a host",
Long: `Announce yourself as a host on the network.
An announcement requires 'freezing' a volume of coins for a number of blocks,
as a defense against Sybil attacks. Before announcing, you should set your
hosting parameters via 'host setconfig'.`,
Run: wrap(hostannouncecmd)}
hostStatusCmd = &cobra.Command{
Use: "status",
......@@ -47,9 +56,8 @@ func hostsetcmd(param, value string) {
fmt.Println("Host settings updated.")
}
// TODO: needs freeze values
func hostannouncecmd() {
err := callAPI("/host/announce")
func hostannouncecmd(freezeVolume, freezeDuration string) {
err := callAPI(fmt.Sprintf("/host/announce?freezeVolume=%s&freezeDuration=%s", freezeVolume, freezeDuration))
if err != nil {
fmt.Println("Could not announce host:", err)
return
......
......@@ -3,6 +3,8 @@ package main
import (
"fmt"
"net/http"
"github.com/NebulousLabs/Sia/consensus"
)
func (d *daemon) hostConfigHandler(w http.ResponseWriter, req *http.Request) {
......@@ -25,7 +27,7 @@ func (d *daemon) hostConfigHandler(w http.ResponseWriter, req *http.Request) {
if req.FormValue(qs) != "" {
_, err := fmt.Sscan(req.FormValue(qs), qsVars[qs])
if err != nil {
http.Error(w, "Malformed "+qs+" "+err.Error(), 400)
http.Error(w, "Malformed "+qs, 400)
return
}
}
......@@ -36,12 +38,25 @@ func (d *daemon) hostConfigHandler(w http.ResponseWriter, req *http.Request) {
}
func (d *daemon) hostAnnounceHandler(w http.ResponseWriter, req *http.Request) {
// err = d.AnnounceHost(1, d.state.Height()+20) // A freeze volume and unlock height.
// if err != nil {
// http.Error(w, "Could not update host:"+err.Error(), 400)
// return
// }
// writeSuccess(w)
var freezeVolume consensus.Currency
var freezeDuration consensus.BlockHeight
_, err := fmt.Sscan(req.FormValue("freezeVolume"), &freezeVolume)
if err != nil {
http.Error(w, "Malformed freezeVolume", 400)
return
}
_, err = fmt.Sscan(req.FormValue("freezeDuration"), &freezeDuration)
if err != nil {
http.Error(w, "Malformed freezeDuration", 400)
return
}
// TODO: return error if address unknown
err = d.host.Announce(d.network.Address(), freezeVolume, freezeDuration)
if err != nil {
http.Error(w, "Could not announce host:"+err.Error(), 400)
return
}
writeSuccess(w)
}
func (d *daemon) hostStatusHandler(w http.ResponseWriter, req *http.Request) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment