<commit_before>package selfplay

import (
	"bufio"
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"
	"runtime/pprof"
	"strings"
	"text/tabwriter"
	"time"

	"github.com/google/subcommands"
	"github.com/nelhage/taktician/ptn"
	"github.com/nelhage/taktician/tak"
)

type Command struct {
	size int
	zero bool
	p1   string
	p2   string
	seed int64

	games  int
	cutoff int
	swap   bool

	prefix   string
	openings string

	debug int
	limit time.Duration

	threads int

	out     string
	summary string
	verbose bool

	memProfile string
}

func (*Command) Name() string     { return "selfplay" }
func (*Command) Synopsis() string { return "Play two AIs against each other and report results" }
func (*Command) Usage() string {
	return `selfplay [flags]
`
}

func (c *Command) SetFlags(flags *flag.FlagSet) {
	flags.IntVar(&c.size, "size", 5, "board size")
	flags.StringVar(&c.p1, "p1", "taktician tei", "player1 TIE driver")
	flags.StringVar(&c.p2, "p2", "taktician tei", "player2 TIE driver")

	flags.Int64Var(&c.seed, "seed", 0, "starting random seed")
	flags.IntVar(&c.games, "games", 10, "number of games to play per opening/color")
	flags.IntVar(&c.cutoff, "cutoff", 80, "cut games off after how many plies")
	flags.BoolVar(&c.swap, "swap", true, "swap colors each game")
	flags.StringVar(&c.prefix, "prefix", "", "ptn file to start games at the end of")
	flags.StringVar(&c.openings, "openings", "", "File of openings, 1/line in TPS")
	flags.IntVar(&c.debug, "debug", 0, "debug level")
	flags.DurationVar(&c.limit, "limit", 0, "amount of time to search each move")
	flags.IntVar(&c.threads, "threads", 4, "number of parallel threads")
	flags.StringVar(&c.out, "out", "", "directory to write ptns to")
	flags.StringVar(&c.summary, "summary", "", "write summary JSON file")
	flags.BoolVar(&c.verbose, "v", false, "verbose output")
	flags.StringVar(&c.memProfile, "mem-profile", "", "write memory profile")
}

func readOpenings(path string) ([]*tak.Position, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	var out []*tak.Position
	r := bufio.NewScanner(f)
	for r.Scan() {
		line := r.Text()
		pos, err := ptn.ParseTPS(line)
		if err != nil {
			return nil, fmt.Errorf("parse TPS: %q: %w", line, err)
		}
		out = append(out, pos)
	}
	return out, nil
}

func (c *Command) Execute(ctx context.Context, flag *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	if c.memProfile != "" {
		defer func() {
			f, e := os.OpenFile(c.memProfile,
				os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
			if e != nil {
				log.Printf("open memory profile: %v", e)
				return
			}
			pprof.Lookup("heap").WriteTo(f, 0)
		}()
	}

	if c.seed == 0 {
		c.seed = time.Now().Unix()
	}

	var openings []*tak.Position
	if c.prefix != "" {
		pt, e := ptn.ParseFile(c.prefix)
		if e != nil {
			log.Fatalf("Parse PTN: %v", e)
		}
		p, e := pt.PositionAtMove(0, tak.NoColor)
		if e != nil {
			log.Fatalf("PTN: %v", e)
		}
		openings = []*tak.Position{p}
	}
	if c.openings != "" {
		var e error
		openings, e = readOpenings(c.openings)
		if e != nil {
			log.Fatalf("-openings: %v", e)
		}
	}
	if len(openings) == 0 {
		openings = []*tak.Position{tak.New(tak.Config{Size: c.size})}
	}

	cfg := &Config{
		Zero:    c.zero,
		Size:    c.size,
		Debug:   c.debug,
		Swap:    c.swap,
		Games:   c.games,
		Threads: c.threads,
		Seed:    c.seed,
		Cutoff:  c.cutoff,
		Limit:   c.limit,
		Initial: openings,
		Verbose: c.verbose,
		P1:      strings.Split(c.p1, " "),
		P2:      strings.Split(c.p2, " "),
	}

	st := Simulate(cfg)

	if c.out != "" {
		if c.summary == "" {
			c.summary = path.Join(c.out, "summary.json")
		}
		for _, r := range st.Games {
			writeGame(c.out, &r)
		}
	}
	if c.summary != "" {
		if err := c.writeSummary(c.summary, &st); err != nil {
			log.Println("writing summary: ", err.Error())
		}
	}

	log.Printf("done games=%d seed=%d ties=%d cutoff=%d white=%d black=%d limit=%s",
		len(st.Games), c.seed, st.Ties, st.Cutoff, st.White, st.Black, c.limit)
	log.Printf("p1.wins=%d (%d road/%d flat) p2.wins=%d (%d road/%d flat)",
		st.Players[0].Wins, st.Players[0].RoadWins, st.Players[0].FlatWins,
		st.Players[1].Wins, st.Players[1].RoadWins, st.Players[1].FlatWins)
	tw := tabwriter.NewWriter(os.Stderr, 2, 4, 2, ' ', 0)

	fmt.Fprintf(tw, "\twhite\tblack\tsum\n")
	fmt.Fprintf(tw, "p1\t%d\t%d\t%d\n", st.Players[0].WhiteWins, st.Players[0].BlackWins, st.Players[0].Wins)
	fmt.Fprintf(tw, "p2\t%d\t%d\t%d\n", st.Players[1].WhiteWins, st.Players[1].BlackWins, st.Players[1].Wins)
	fmt.Fprintf(tw, "sum\t%d\t%d\t%d\n",
		st.Players[0].WhiteWins+st.Players[1].WhiteWins,
		st.Players[0].BlackWins+st.Players[1].BlackWins,
		st.Players[0].Wins+st.Players[1].Wins,
	)
	tw.Flush()

	a, b := int64(st.Players[0].Wins), int64(st.Players[1].Wins)
	if a < b {
		a, b = b, a
	}
	log.Printf("p[one-sided]=%f", binomTest(a, b, 0.5))

	return subcommands.ExitSuccess
}

func writeGame(d string, r *Result) {
	os.MkdirAll(d, 0755)
	p := &ptn.PTN{}
	p.Tags = []ptn.Tag{
		{Name: "Size", Value: fmt.Sprintf("%d", r.Position.Size())},
		{Name: "Player1", Value: r.spec.p1color.String()},
	}
	if r.Initial.MoveNumber() != 0 {
		p.Tags = append(p.Tags, ptn.Tag{
			Name: "TPS", Value: ptn.FormatTPS(r.Initial)})
	}
	for i, m := range r.Moves {
		if i%2 == 0 {
			p.Ops = append(p.Ops, &ptn.MoveNumber{Number: i/2 + 1})
		}
		p.Ops = append(p.Ops, &ptn.Move{Move: m})
	}
	ptnPath := path.Join(d, fmt.Sprintf("%d-%d.ptn", r.spec.oi, r.spec.i))
	ioutil.WriteFile(ptnPath, []byte(p.Render()), 0644)
}

type Summary struct {
	Cmdline []string
	Player1 string
	Player2 string
	Limit   time.Duration
	Stats   *Stats
}

func (c *Command) writeSummary(path string, stats *Stats) error {
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()
	summary := Summary{
		Cmdline: os.Args,
		Player1: c.p1,
		Player2: c.p2,
		Limit:   c.limit,
		Stats:   stats,
	}

	bs, err := json.MarshalIndent(&summary, "", "  ")
	if err != nil {
		return err
	}
	f.Write(bs)
	return nil
}
<commit_msg>newline<commit_after>package selfplay

import (
	"bufio"
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"
	"runtime/pprof"
	"strings"
	"text/tabwriter"
	"time"

	"github.com/google/subcommands"
	"github.com/nelhage/taktician/ptn"
	"github.com/nelhage/taktician/tak"
)

type Command struct {
	size int
	zero bool
	p1   string
	p2   string
	seed int64

	games  int
	cutoff int
	swap   bool

	prefix   string
	openings string

	debug int
	limit time.Duration

	threads int

	out     string
	summary string
	verbose bool

	memProfile string
}

func (*Command) Name() string     { return "selfplay" }
func (*Command) Synopsis() string { return "Play two AIs against each other and report results" }
func (*Command) Usage() string {
	return `selfplay [flags]
`
}

func (c *Command) SetFlags(flags *flag.FlagSet) {
	flags.IntVar(&c.size, "size", 5, "board size")
	flags.StringVar(&c.p1, "p1", "taktician tei", "player1 TIE driver")
	flags.StringVar(&c.p2, "p2", "taktician tei", "player2 TIE driver")

	flags.Int64Var(&c.seed, "seed", 0, "starting random seed")
	flags.IntVar(&c.games, "games", 10, "number of games to play per opening/color")
	flags.IntVar(&c.cutoff, "cutoff", 80, "cut games off after how many plies")
	flags.BoolVar(&c.swap, "swap", true, "swap colors each game")
	flags.StringVar(&c.prefix, "prefix", "", "ptn file to start games at the end of")
	flags.StringVar(&c.openings, "openings", "", "File of openings, 1/line in TPS")
	flags.IntVar(&c.debug, "debug", 0, "debug level")
	flags.DurationVar(&c.limit, "limit", 0, "amount of time to search each move")
	flags.IntVar(&c.threads, "threads", 4, "number of parallel threads")
	flags.StringVar(&c.out, "out", "", "directory to write ptns to")
	flags.StringVar(&c.summary, "summary", "", "write summary JSON file")
	flags.BoolVar(&c.verbose, "v", false, "verbose output")
	flags.StringVar(&c.memProfile, "mem-profile", "", "write memory profile")
}

func readOpenings(path string) ([]*tak.Position, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	var out []*tak.Position
	r := bufio.NewScanner(f)
	for r.Scan() {
		line := r.Text()
		pos, err := ptn.ParseTPS(line)
		if err != nil {
			return nil, fmt.Errorf("parse TPS: %q: %w", line, err)
		}
		out = append(out, pos)
	}
	return out, nil
}

func (c *Command) Execute(ctx context.Context, flag *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	if c.memProfile != "" {
		defer func() {
			f, e := os.OpenFile(c.memProfile,
				os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
			if e != nil {
				log.Printf("open memory profile: %v", e)
				return
			}
			pprof.Lookup("heap").WriteTo(f, 0)
		}()
	}

	if c.seed == 0 {
		c.seed = time.Now().Unix()
	}

	var openings []*tak.Position
	if c.prefix != "" {
		pt, e := ptn.ParseFile(c.prefix)
		if e != nil {
			log.Fatalf("Parse PTN: %v", e)
		}
		p, e := pt.PositionAtMove(0, tak.NoColor)
		if e != nil {
			log.Fatalf("PTN: %v", e)
		}
		openings = []*tak.Position{p}
	}
	if c.openings != "" {
		var e error
		openings, e = readOpenings(c.openings)
		if e != nil {
			log.Fatalf("-openings: %v", e)
		}
	}
	if len(openings) == 0 {
		openings = []*tak.Position{tak.New(tak.Config{Size: c.size})}
	}

	cfg := &Config{
		Zero:    c.zero,
		Size:    c.size,
		Debug:   c.debug,
		Swap:    c.swap,
		Games:   c.games,
		Threads: c.threads,
		Seed:    c.seed,
		Cutoff:  c.cutoff,
		Limit:   c.limit,
		Initial: openings,
		Verbose: c.verbose,
		P1:      strings.Split(c.p1, " "),
		P2:      strings.Split(c.p2, " "),
	}

	st := Simulate(cfg)

	if c.out != "" {
		if c.summary == "" {
			c.summary = path.Join(c.out, "summary.json")
		}
		for _, r := range st.Games {
			writeGame(c.out, &r)
		}
	}
	if c.summary != "" {
		if err := c.writeSummary(c.summary, &st); err != nil {
			log.Println("writing summary: ", err.Error())
		}
	}

	log.Printf("done games=%d seed=%d ties=%d cutoff=%d white=%d black=%d limit=%s",
		len(st.Games), c.seed, st.Ties, st.Cutoff, st.White, st.Black, c.limit)
	log.Printf("p1.wins=%d (%d road/%d flat) p2.wins=%d (%d road/%d flat)",
		st.Players[0].Wins, st.Players[0].RoadWins, st.Players[0].FlatWins,
		st.Players[1].Wins, st.Players[1].RoadWins, st.Players[1].FlatWins)
	tw := tabwriter.NewWriter(os.Stderr, 2, 4, 2, ' ', 0)

	fmt.Fprintf(tw, "\twhite\tblack\tsum\n")
	fmt.Fprintf(tw, "p1\t%d\t%d\t%d\n", st.Players[0].WhiteWins, st.Players[0].BlackWins, st.Players[0].Wins)
	fmt.Fprintf(tw, "p2\t%d\t%d\t%d\n", st.Players[1].WhiteWins, st.Players[1].BlackWins, st.Players[1].Wins)
	fmt.Fprintf(tw, "sum\t%d\t%d\t%d\n",
		st.Players[0].WhiteWins+st.Players[1].WhiteWins,
		st.Players[0].BlackWins+st.Players[1].BlackWins,
		st.Players[0].Wins+st.Players[1].Wins,
	)
	tw.Flush()

	a, b := int64(st.Players[0].Wins), int64(st.Players[1].Wins)
	if a < b {
		a, b = b, a
	}
	log.Printf("p[one-sided]=%f", binomTest(a, b, 0.5))

	return subcommands.ExitSuccess
}

func writeGame(d string, r *Result) {
	os.MkdirAll(d, 0755)
	p := &ptn.PTN{}
	p.Tags = []ptn.Tag{
		{Name: "Size", Value: fmt.Sprintf("%d", r.Position.Size())},
		{Name: "Player1", Value: r.spec.p1color.String()},
	}
	if r.Initial.MoveNumber() != 0 {
		p.Tags = append(p.Tags, ptn.Tag{
			Name: "TPS", Value: ptn.FormatTPS(r.Initial)})
	}
	for i, m := range r.Moves {
		if i%2 == 0 {
			p.Ops = append(p.Ops, &ptn.MoveNumber{Number: i/2 + 1})
		}
		p.Ops = append(p.Ops, &ptn.Move{Move: m})
	}
	ptnPath := path.Join(d, fmt.Sprintf("%d-%d.ptn", r.spec.oi, r.spec.i))
	ioutil.WriteFile(ptnPath, []byte(p.Render()), 0644)
}

type Summary struct {
	Cmdline []string
	Player1 string
	Player2 string
	Limit   time.Duration
	Stats   *Stats
}

func (c *Command) writeSummary(path string, stats *Stats) error {
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()
	summary := Summary{
		Cmdline: os.Args,
		Player1: c.p1,
		Player2: c.p2,
		Limit:   c.limit,
		Stats:   stats,
	}

	bs, err := json.MarshalIndent(&summary, "", "  ")
	if err != nil {
		return err
	}
	f.Write(bs)
	fmt.Fprintln(f)
	return nil
}
<|endoftext|>


<commit_before>package server_test

import (
	"bytes"
	"fmt"
	"io"
	. "launchpad.net/gocheck"
	"launchpad.net/gozk/zookeeper"
	"launchpad.net/juju/go/charm"
	"launchpad.net/juju/go/cmd"
	"launchpad.net/juju/go/cmd/jujuc/server"
	"launchpad.net/juju/go/state"
	"launchpad.net/juju/go/testing"
	"net/url"
	stdtesting "testing"
)

var zkAddr string

func TestPackage(t *stdtesting.T) {
	srv := testing.StartZkServer()
	defer srv.Destroy()
	var err error
	zkAddr, err = srv.Addr()
	if err != nil {
		t.Fatalf("could not get ZooKeeper server address")
	}
	TestingT(t)
}

func addDummyCharm(c *C, st *state.State) *state.Charm {
	ch := testing.Charms.Dir("dummy")
	u := fmt.Sprintf("local:series/%s-%d", ch.Meta().Name, ch.Revision())
	curl := charm.MustParseURL(u)
	burl, err := url.Parse("http://bundle.url")
	c.Assert(err, IsNil)
	dummy, err := st.AddCharm(ch, curl, burl)
	c.Assert(err, IsNil)
	return dummy
}

func dummyContext(c *C) *cmd.Context {
	return &cmd.Context{c.MkDir(), &bytes.Buffer{}, &bytes.Buffer{}}
}

func bufferString(w io.Writer) string {
	return w.(*bytes.Buffer).String()
}

type UnitFixture struct {
	ctx     *server.ClientContext
	service *state.Service
	unit    *state.Unit
}

func (f *UnitFixture) SetUpTest(c *C) {
	st, err := state.Initialize(&state.Info{
		Addrs: []string{zkAddr},
	})
	c.Assert(err, IsNil)
	f.ctx = &server.ClientContext{
		Id:            "TestCtx",
		State:         st,
		LocalUnitName: "minecraft/0",
	}
	dummy := addDummyCharm(c, st)
	f.service, err = st.AddService("minecraft", dummy)
	c.Assert(err, IsNil)
	f.unit, err = f.service.AddUnit()
	c.Assert(err, IsNil)
}

func (f *UnitFixture) TearDownTest(c *C) {
	zk, session, err := zookeeper.Dial(zkAddr, 15e9)
	c.Assert(err, IsNil)
	event := <-session
	c.Assert(event.Ok(), Equals, true)
	c.Assert(event.Type, Equals, zookeeper.EVENT_SESSION)
	c.Assert(event.State, Equals, zookeeper.STATE_CONNECTED)
	testing.ZkRemoveTree(zk, "/")
}

func (f *UnitFixture) AssertUnitCommand(c *C, name string) {
	ctx := &server.ClientContext{Id: "TestCtx", State: f.ctx.State}
	com, err := ctx.NewCommand(name)
	c.Assert(com, IsNil)
	c.Assert(err, ErrorMatches, "context TestCtx is not attached to a unit")

	ctx = &server.ClientContext{Id: "TestCtx", LocalUnitName: f.ctx.LocalUnitName}
	com, err = ctx.NewCommand(name)
	c.Assert(com, IsNil)
	c.Assert(err, ErrorMatches, "context TestCtx cannot access state")
}

type TruthErrorSuite struct{}

var _ = Suite(&TruthErrorSuite{})

var truthErrorTests = []struct {
	value interface{}
	err   error
}{
	{0, cmd.ErrSilent},
	{int8(0), cmd.ErrSilent},
	{int16(0), cmd.ErrSilent},
	{int32(0), cmd.ErrSilent},
	{int64(0), cmd.ErrSilent},
	{uint(0), cmd.ErrSilent},
	{uint8(0), cmd.ErrSilent},
	{uint16(0), cmd.ErrSilent},
	{uint32(0), cmd.ErrSilent},
	{uint64(0), cmd.ErrSilent},
	{uintptr(0), cmd.ErrSilent},
	{123, nil},
	{int8(123), nil},
	{int16(123), nil},
	{int32(123), nil},
	{int64(123), nil},
	{uint(123), nil},
	{uint8(123), nil},
	{uint16(123), nil},
	{uint32(123), nil},
	{uint64(123), nil},
	{uintptr(123), nil},
	{0.0, cmd.ErrSilent},
	{float32(0.0), cmd.ErrSilent},
	{123.45, nil},
	{float32(123.45), nil},
	{nil, cmd.ErrSilent},
	{"", cmd.ErrSilent},
	{"blah", nil},
	{true, nil},
	{false, cmd.ErrSilent},
	{[]string{}, cmd.ErrSilent},
	{[]string{""}, nil},
	{[]bool{}, cmd.ErrSilent},
	{[]bool{false}, nil},
	{map[string]string{}, cmd.ErrSilent},
	{map[string]string{"": ""}, nil},
	{map[bool]bool{}, cmd.ErrSilent},
	{map[bool]bool{false: false}, nil},
	{struct{ x bool }{false}, nil},
}

func (s *TruthErrorSuite) TestTruthError(c *C) {
	for _, t := range truthErrorTests {
		c.Assert(server.TruthError(t.value), Equals, t.err)
	}
}
<commit_msg>missed broken test<commit_after>package server_test

import (
	"bytes"
	"fmt"
	"io"
	. "launchpad.net/gocheck"
	"launchpad.net/gozk/zookeeper"
	"launchpad.net/juju/go/charm"
	"launchpad.net/juju/go/cmd"
	"launchpad.net/juju/go/cmd/jujuc/server"
	"launchpad.net/juju/go/state"
	"launchpad.net/juju/go/testing"
	"net/url"
	stdtesting "testing"
)

var zkAddr string

func TestPackage(t *stdtesting.T) {
	srv := testing.StartZkServer()
	defer srv.Destroy()
	var err error
	zkAddr, err = srv.Addr()
	if err != nil {
		t.Fatalf("could not get ZooKeeper server address")
	}
	TestingT(t)
}

func addDummyCharm(c *C, st *state.State) *state.Charm {
	ch := testing.Charms.Dir("dummy")
	u := fmt.Sprintf("local:series/%s-%d", ch.Meta().Name, ch.Revision())
	curl := charm.MustParseURL(u)
	burl, err := url.Parse("http://bundle.url")
	c.Assert(err, IsNil)
	dummy, err := st.AddCharm(ch, curl, burl, "dummy-sha256")
	c.Assert(err, IsNil)
	return dummy
}

func dummyContext(c *C) *cmd.Context {
	return &cmd.Context{c.MkDir(), &bytes.Buffer{}, &bytes.Buffer{}}
}

func bufferString(w io.Writer) string {
	return w.(*bytes.Buffer).String()
}

type UnitFixture struct {
	ctx     *server.ClientContext
	service *state.Service
	unit    *state.Unit
}

func (f *UnitFixture) SetUpTest(c *C) {
	st, err := state.Initialize(&state.Info{
		Addrs: []string{zkAddr},
	})
	c.Assert(err, IsNil)
	f.ctx = &server.ClientContext{
		Id:            "TestCtx",
		State:         st,
		LocalUnitName: "minecraft/0",
	}
	dummy := addDummyCharm(c, st)
	f.service, err = st.AddService("minecraft", dummy)
	c.Assert(err, IsNil)
	f.unit, err = f.service.AddUnit()
	c.Assert(err, IsNil)
}

func (f *UnitFixture) TearDownTest(c *C) {
	zk, session, err := zookeeper.Dial(zkAddr, 15e9)
	c.Assert(err, IsNil)
	event := <-session
	c.Assert(event.Ok(), Equals, true)
	c.Assert(event.Type, Equals, zookeeper.EVENT_SESSION)
	c.Assert(event.State, Equals, zookeeper.STATE_CONNECTED)
	testing.ZkRemoveTree(zk, "/")
}

func (f *UnitFixture) AssertUnitCommand(c *C, name string) {
	ctx := &server.ClientContext{Id: "TestCtx", State: f.ctx.State}
	com, err := ctx.NewCommand(name)
	c.Assert(com, IsNil)
	c.Assert(err, ErrorMatches, "context TestCtx is not attached to a unit")

	ctx = &server.ClientContext{Id: "TestCtx", LocalUnitName: f.ctx.LocalUnitName}
	com, err = ctx.NewCommand(name)
	c.Assert(com, IsNil)
	c.Assert(err, ErrorMatches, "context TestCtx cannot access state")
}

type TruthErrorSuite struct{}

var _ = Suite(&TruthErrorSuite{})

var truthErrorTests = []struct {
	value interface{}
	err   error
}{
	{0, cmd.ErrSilent},
	{int8(0), cmd.ErrSilent},
	{int16(0), cmd.ErrSilent},
	{int32(0), cmd.ErrSilent},
	{int64(0), cmd.ErrSilent},
	{uint(0), cmd.ErrSilent},
	{uint8(0), cmd.ErrSilent},
	{uint16(0), cmd.ErrSilent},
	{uint32(0), cmd.ErrSilent},
	{uint64(0), cmd.ErrSilent},
	{uintptr(0), cmd.ErrSilent},
	{123, nil},
	{int8(123), nil},
	{int16(123), nil},
	{int32(123), nil},
	{int64(123), nil},
	{uint(123), nil},
	{uint8(123), nil},
	{uint16(123), nil},
	{uint32(123), nil},
	{uint64(123), nil},
	{uintptr(123), nil},
	{0.0, cmd.ErrSilent},
	{float32(0.0), cmd.ErrSilent},
	{123.45, nil},
	{float32(123.45), nil},
	{nil, cmd.ErrSilent},
	{"", cmd.ErrSilent},
	{"blah", nil},
	{true, nil},
	{false, cmd.ErrSilent},
	{[]string{}, cmd.ErrSilent},
	{[]string{""}, nil},
	{[]bool{}, cmd.ErrSilent},
	{[]bool{false}, nil},
	{map[string]string{}, cmd.ErrSilent},
	{map[string]string{"": ""}, nil},
	{map[bool]bool{}, cmd.ErrSilent},
	{map[bool]bool{false: false}, nil},
	{struct{ x bool }{false}, nil},
}

func (s *TruthErrorSuite) TestTruthError(c *C) {
	for _, t := range truthErrorTests {
		c.Assert(server.TruthError(t.value), Equals, t.err)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cmd

import (
	"github.com/spf13/cobra"
	"k8s.io/minikube/pkg/minikube/driver"
	"k8s.io/minikube/pkg/minikube/exit"
	"k8s.io/minikube/pkg/minikube/machine"
	"k8s.io/minikube/pkg/minikube/mustload"
	"k8s.io/minikube/pkg/minikube/node"
	"k8s.io/minikube/pkg/minikube/out"
)

var nodeStopCmd = &cobra.Command{
	Use:   "stop",
	Short: "Stops a node in a cluster.",
	Long:  "Stops a node in a cluster.",
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 {
			exit.UsageT("Usage: minikube node stop [name]")
		}

		name := args[0]
		api, cc := mustload.Partial(ClusterFlagValue())

		n, _, err := node.Retrieve(cc, name)
		if err != nil {
			exit.WithError("retrieving node", err)
		}

		machineName := driver.MachineName(*cc, *n)

		err = machine.StopHost(api, machineName)
		if err != nil {
			out.FatalT("Failed to stop node {{.name}}", out.V{"name": name})
		}
	},
}

func init() {
	nodeCmd.AddCommand(nodeStopCmd)
}
<commit_msg>improve node stop output<commit_after>/*
Copyright 2020 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cmd

import (
	"github.com/spf13/cobra"
	"k8s.io/minikube/pkg/minikube/driver"
	"k8s.io/minikube/pkg/minikube/exit"
	"k8s.io/minikube/pkg/minikube/machine"
	"k8s.io/minikube/pkg/minikube/mustload"
	"k8s.io/minikube/pkg/minikube/node"
	"k8s.io/minikube/pkg/minikube/out"
)

var nodeStopCmd = &cobra.Command{
	Use:   "stop",
	Short: "Stops a node in a cluster.",
	Long:  "Stops a node in a cluster.",
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 {
			exit.UsageT("Usage: minikube node stop [name]")
		}

		name := args[0]
		api, cc := mustload.Partial(ClusterFlagValue())

		n, _, err := node.Retrieve(cc, name)
		if err != nil {
			exit.WithError("retrieving node", err)
		}

		machineName := driver.MachineName(*cc, *n)

		err = machine.StopHost(api, machineName)
		if err != nil {
			out.FatalT("Failed to stop node {{.name}}", out.V{"name": name})
		}

		out.T(out.Stopped, "Successfully stopped node {{.name}}", out.V{"name": name})
	},
}

func init() {
	nodeCmd.AddCommand(nodeStopCmd)
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"os"

	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"nimona.io/internal/api"
	"nimona.io/internal/telemetry"
	"nimona.io/pkg/discovery/hyperspace"
	"nimona.io/pkg/net"
	"nimona.io/pkg/object/exchange"
	"nimona.io/pkg/storage"
)

var (
	daemonPeerKey     string
	daemonIdentityKey string

	daemonPort             int
	daemonAPIPort          int
	daemonAnnounceHostname string
	daemonEnableMetrics    bool
	daemonToken            string

	daemonRelayAddresses []string

	daemonBootstrapAddresses = []string{
		// "tcps:andromeda.nimona.io:21013",
		// "tcps:borealis.nimona.io:21013",
		"tcps:cassiopeia.nimona.io:21013",
		// "tcps:draco.nimona.io:21013",
		// "tcps:eridanus.nimona.io:21013",
		// "tcps:fornax.nimona.io:21013",
		// "tcps:gemini.nimona.io:21013",
		// "tcps:hydra.nimona.io:21013",
		// "tcps:indus.nimona.io:21013",
		// "tcps:lacerta.nimona.io:21013",
		// "tcps:mensa.nimona.io:21013",
		// "tcps:norma.nimona.io:21013",
		// "tcps:orion.nimona.io:21013",
		// "tcps:pyxis.nimona.io:21013",
		// "tcps:stats.nimona.io:21013",
	}
)

// daemonStartCmd represents the daemon command
var daemonStartCmd = &cobra.Command{
	Use:   "start",
	Short: "Start a peer as a daemon",
	Long:  "",
	RunE: func(cmd *cobra.Command, args []string) error {
		bootstrapAddresses := viper.GetStringSlice("daemon.bootstraps")
		relayAddresses := viper.GetStringSlice("daemon.relays")

		if config.Daemon.PeerKey == nil {
			return errors.New("daemon not configured, please run 'daemon init'")
		}

		if err := os.MkdirAll(config.Daemon.ObjectPath, 0777); err != nil {
			return errors.Wrap(err, "could not create objects dir")
		}

		if len(bootstrapAddresses) > 0 {
			cmd.Println("Adding bootstrap nodes")
			for _, v := range bootstrapAddresses {
				cmd.Println("  *", v)
			}
		} else {
			cmd.Println("No bootstrap nodes provided")
		}

		k := config.Daemon.PeerKey

		n, err := net.New(
			k,
			viper.GetString("daemon.announce_hostname"),
			relayAddresses,
		)
		if err != nil {
			return err
		}

		dpr := storage.NewDiskStorage(config.Daemon.ObjectPath)

		bind := fmt.Sprintf("0.0.0.0:%d", viper.GetInt("daemon.port"))
		x, err := exchange.New(k, n, dpr, bind)
		if err != nil {
			return err
		}

		hsr, err := hyperspace.NewDiscoverer(k, n, x, bootstrapAddresses)
		if err != nil {
			return err
		}

		_ = telemetry.NewTelemetry(x, k, "tcps:stats.nimona.io:21013")

		if err := n.Discoverer().AddProvider(hsr); err != nil {
			return err
		}

		cmd.Println("Started daemon")
		cmd.Println("* Peer private key hash:\n  *", k.HashBase58())
		cmd.Println("* Peer public key hash:\n  *", k.GetPublicKey().HashBase58())
		if config.Daemon.IdentityKey != nil {
			if config.Daemon.Mandate == nil {
				return errors.New("missing mandate for identity")
			}
			ik := config.Daemon.IdentityKey
			if err := n.AttachMandate(config.Daemon.Mandate); err != nil {
				return errors.Wrap(err, "could not attach mandate to network")
			}
			cmd.Println("* Identity private key hash:\n  *", ik.HashBase58())
			cmd.Println("* Identity public key hash:\n  *", ik.GetPublicKey().HashBase58())
		}
		peerAddresses := n.GetPeerInfo().Addresses
		cmd.Println("* Peer addresses:")
		if len(peerAddresses) > 0 {
			for _, addr := range peerAddresses {
				cmd.Println("  *", addr)
			}
		} else {
			cmd.Println("  * No addresses available")
		}

		apiServer := api.New(
			k, n, x, dpr,
			Version, Commit, Date,
			viper.GetString("daemon.token"),
		)

		apiPort := viper.GetInt("daemon.api_port")
		cmd.Printf("* HTTP API address:\n  * http://localhost:%d\n", apiPort)
		return apiServer.Serve(fmt.Sprintf("0.0.0.0:%d", apiPort))
	},
}

func init() {
	daemonCmd.AddCommand(daemonStartCmd)

	daemonStartCmd.PersistentFlags().IntVarP(
		&daemonPort,
		"port",
		"p",
		0,
		"peer port",
	)
	_ = viper.BindPFlag(
		"daemon.port",
		daemonStartCmd.PersistentFlags().Lookup("port"),
	)

	daemonStartCmd.PersistentFlags().StringVarP(
		&daemonToken,
		"token",
		"t",
		daemonToken,
		"daemon token",
	)
	_ = viper.BindPFlag(
		"daemon.token",
		daemonStartCmd.PersistentFlags().Lookup("token"),
	)

	daemonStartCmd.PersistentFlags().StringVar(
		&daemonAnnounceHostname,
		"announce-hostname",
		"",
		"set and announce local dns address",
	)
	_ = viper.BindPFlag(
		"daemon.announce_hostname",
		daemonStartCmd.PersistentFlags().Lookup("announce-hostname"),
	)

	daemonStartCmd.PersistentFlags().IntVar(
		&daemonAPIPort,
		"api-port",
		8030,
		"api port",
	)
	_ = viper.BindPFlag(
		"daemon.api_port",
		daemonStartCmd.PersistentFlags().Lookup("api-port"),
	)

	daemonStartCmd.PersistentFlags().BoolVarP(
		&daemonEnableMetrics,
		"metrics",
		"m",
		false,
		"enable sending anonymous metrics",
	)
	_ = viper.BindPFlag(
		"daemon.metrics",
		daemonStartCmd.PersistentFlags().Lookup("metrics"),
	)

	daemonStartCmd.PersistentFlags().StringSliceVar(
		&daemonBootstrapAddresses,
		"bootstraps",
		daemonBootstrapAddresses,
		"bootstrap addresses",
	)
	_ = viper.BindPFlag(
		"daemon.bootstraps",
		daemonStartCmd.PersistentFlags().Lookup("bootstraps"),
	)

	daemonStartCmd.PersistentFlags().StringSliceVar(
		&daemonRelayAddresses,
		"relays",
		daemonRelayAddresses,
		"relay addresses",
	)
	_ = viper.BindPFlag(
		"daemon.relays",
		daemonStartCmd.PersistentFlags().Lookup("relays"),
	)
}
<commit_msg>Fix attaching mandate to net<commit_after>package cmd

import (
	"fmt"
	"os"

	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"nimona.io/internal/api"
	"nimona.io/internal/telemetry"
	"nimona.io/pkg/discovery/hyperspace"
	"nimona.io/pkg/net"
	"nimona.io/pkg/object/exchange"
	"nimona.io/pkg/storage"
)

var (
	daemonPeerKey     string
	daemonIdentityKey string

	daemonPort             int
	daemonAPIPort          int
	daemonAnnounceHostname string
	daemonEnableMetrics    bool
	daemonToken            string

	daemonRelayAddresses []string

	daemonBootstrapAddresses = []string{
		// "tcps:andromeda.nimona.io:21013",
		// "tcps:borealis.nimona.io:21013",
		"tcps:cassiopeia.nimona.io:21013",
		// "tcps:draco.nimona.io:21013",
		// "tcps:eridanus.nimona.io:21013",
		// "tcps:fornax.nimona.io:21013",
		// "tcps:gemini.nimona.io:21013",
		// "tcps:hydra.nimona.io:21013",
		// "tcps:indus.nimona.io:21013",
		// "tcps:lacerta.nimona.io:21013",
		// "tcps:mensa.nimona.io:21013",
		// "tcps:norma.nimona.io:21013",
		// "tcps:orion.nimona.io:21013",
		// "tcps:pyxis.nimona.io:21013",
		// "tcps:stats.nimona.io:21013",
	}
)

// daemonStartCmd represents the daemon command
var daemonStartCmd = &cobra.Command{
	Use:   "start",
	Short: "Start a peer as a daemon",
	Long:  "",
	RunE: func(cmd *cobra.Command, args []string) error {
		bootstrapAddresses := viper.GetStringSlice("daemon.bootstraps")
		relayAddresses := viper.GetStringSlice("daemon.relays")

		if config.Daemon.PeerKey == nil {
			return errors.New("daemon not configured, please run 'daemon init'")
		}

		if err := os.MkdirAll(config.Daemon.ObjectPath, 0777); err != nil {
			return errors.Wrap(err, "could not create objects dir")
		}

		if len(bootstrapAddresses) > 0 {
			cmd.Println("Adding bootstrap nodes")
			for _, v := range bootstrapAddresses {
				cmd.Println("  *", v)
			}
		} else {
			cmd.Println("No bootstrap nodes provided")
		}

		k := config.Daemon.PeerKey

		n, err := net.New(
			k,
			viper.GetString("daemon.announce_hostname"),
			relayAddresses,
		)
		if err != nil {
			return err
		}

		ik := config.Daemon.IdentityKey
		if ik != nil {
			if config.Daemon.Mandate == nil {
				return errors.New("missing mandate for identity")
			}
			if err := n.AttachMandate(config.Daemon.Mandate); err != nil {
				return errors.Wrap(err, "could not attach mandate to network")
			}
		}

		dpr := storage.NewDiskStorage(config.Daemon.ObjectPath)

		bind := fmt.Sprintf("0.0.0.0:%d", viper.GetInt("daemon.port"))
		x, err := exchange.New(k, n, dpr, bind)
		if err != nil {
			return err
		}

		hsr, err := hyperspace.NewDiscoverer(k, n, x, bootstrapAddresses)
		if err != nil {
			return err
		}

		_ = telemetry.NewTelemetry(x, k, "tcps:stats.nimona.io:21013")

		if err := n.Discoverer().AddProvider(hsr); err != nil {
			return err
		}

		cmd.Println("Started daemon")
		cmd.Println("* Peer private key hash:\n  *", k.HashBase58())
		cmd.Println("* Peer public key hash:\n  *", k.GetPublicKey().HashBase58())
		if ik != nil {
			cmd.Println("* Identity private key hash:\n  *", ik.HashBase58())
			cmd.Println("* Identity public key hash:\n  *", ik.GetPublicKey().HashBase58())
		}
		peerAddresses := n.GetPeerInfo().Addresses
		cmd.Println("* Peer addresses:")
		if len(peerAddresses) > 0 {
			for _, addr := range peerAddresses {
				cmd.Println("  *", addr)
			}
		} else {
			cmd.Println("  * No addresses available")
		}

		apiServer := api.New(
			k, n, x, dpr,
			Version, Commit, Date,
			viper.GetString("daemon.token"),
		)

		apiPort := viper.GetInt("daemon.api_port")
		cmd.Printf("* HTTP API address:\n  * http://localhost:%d\n", apiPort)
		return apiServer.Serve(fmt.Sprintf("0.0.0.0:%d", apiPort))
	},
}

func init() {
	daemonCmd.AddCommand(daemonStartCmd)

	daemonStartCmd.PersistentFlags().IntVarP(
		&daemonPort,
		"port",
		"p",
		0,
		"peer port",
	)
	_ = viper.BindPFlag(
		"daemon.port",
		daemonStartCmd.PersistentFlags().Lookup("port"),
	)

	daemonStartCmd.PersistentFlags().StringVarP(
		&daemonToken,
		"token",
		"t",
		daemonToken,
		"daemon token",
	)
	_ = viper.BindPFlag(
		"daemon.token",
		daemonStartCmd.PersistentFlags().Lookup("token"),
	)

	daemonStartCmd.PersistentFlags().StringVar(
		&daemonAnnounceHostname,
		"announce-hostname",
		"",
		"set and announce local dns address",
	)
	_ = viper.BindPFlag(
		"daemon.announce_hostname",
		daemonStartCmd.PersistentFlags().Lookup("announce-hostname"),
	)

	daemonStartCmd.PersistentFlags().IntVar(
		&daemonAPIPort,
		"api-port",
		8030,
		"api port",
	)
	_ = viper.BindPFlag(
		"daemon.api_port",
		daemonStartCmd.PersistentFlags().Lookup("api-port"),
	)

	daemonStartCmd.PersistentFlags().BoolVarP(
		&daemonEnableMetrics,
		"metrics",
		"m",
		false,
		"enable sending anonymous metrics",
	)
	_ = viper.BindPFlag(
		"daemon.metrics",
		daemonStartCmd.PersistentFlags().Lookup("metrics"),
	)

	daemonStartCmd.PersistentFlags().StringSliceVar(
		&daemonBootstrapAddresses,
		"bootstraps",
		daemonBootstrapAddresses,
		"bootstrap addresses",
	)
	_ = viper.BindPFlag(
		"daemon.bootstraps",
		daemonStartCmd.PersistentFlags().Lookup("bootstraps"),
	)

	daemonStartCmd.PersistentFlags().StringSliceVar(
		&daemonRelayAddresses,
		"relays",
		daemonRelayAddresses,
		"relay addresses",
	)
	_ = viper.BindPFlag(
		"daemon.relays",
		daemonStartCmd.PersistentFlags().Lookup("relays"),
	)
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha1"
	"crypto/sha256"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"syscall"

	"github.com/zaolin/go-tpm/tpm"
	"golang.org/x/crypto/ed25519"
	"golang.org/x/sys/unix"
)

const (
	tpmDevice  string = "/dev/tpm0"
	mountPath  string = "/mnt/vboot"
	filesystem string = "ext3"
)

func dieHard() {
	if e1, e2, err := syscall.Syscall6(syscall.SYS_REBOOT, syscall.LINUX_REBOOT_MAGIC1, syscall.LINUX_REBOOT_MAGIC2, syscall.LINUX_REBOOT_CMD_POWER_OFF, 0, 0, 0); err != 0 {
		log.Fatalf("a %v b %v err %v", e1, e2, err)
	}
}

func main() {
	var publicKey = flag.String("pubkey", "/etc/sig.pub", "A public key which should verify the signature.")
	var pcr = flag.Uint("pcr", 12, "The pcr index used for measuring the kernel before kexec.")
	var bootDev = flag.String("boot-device", "/dev/sda1", "The boot device which is used to kexec into a signed kernel.")
	var linuxKernel = flag.String("kernel", "/mnt/vboot/kernel", "Kernel image file path.")
	var linuxKernelSignature = flag.String("kernel-sig", "/mnt/vboot/kernel.sig", "Kernel image signature file path.")
	var initrd = flag.String("initrd", "/mnt/vboot/initrd", "Initrd file path.")
	var initrdSignature = flag.String("initrd-sig", "/mnt/vboot/initrd.sig", "Initrd signature file path.")
	var debug = flag.Bool("debug", false, "Enables debug mode.")

	flag.Parse()

	if err := os.MkdirAll(mountPath, os.ModePerm); err != nil {
		if *debug {
			dieHard()
		} else {
			panic(err)
		}
	}

	unix.Mount(*bootDev, mountPath, filesystem, unix.MS_RDONLY, "")

	paths := [...]string{*publicKey, *linuxKernel, *linuxKernelSignature, *initrd, *initrdSignature}
	files := make(map[string][]byte)

	for _, element := range paths {
		data, err := ioutil.ReadFile(element)
		if err != nil {
			if *debug {
				dieHard()
			} else {
				panic(err)
			}
		} else {
			files[element] = data
		}
	}

	kernelDigest := sha256.Sum256(files[*linuxKernel])
	initrdDigest := sha256.Sum256(files[*initrd])

	pcrDigestKernel := sha1.Sum(files[*linuxKernel])
	pcrDigestInitrd := sha1.Sum(files[*initrd])

	kernelSuccess := ed25519.Verify(files[*publicKey], kernelDigest[:], files[*linuxKernelSignature])
	initrdSuccess := ed25519.Verify(files[*publicKey], initrdDigest[:], files[*linuxKernelSignature])

	if kernelSuccess && initrdSuccess {
		rwc, err := tpm.OpenTPM(tpmDevice)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Couldn't open the TPM file %s: %s\n", tpmDevice, err)
			return
		}

		tpm.PcrExtend(rwc, uint32(*pcr), pcrDigestKernel)
		tpm.PcrExtend(rwc, uint32(*pcr), pcrDigestInitrd)

		binary, lookErr := exec.LookPath("kexec")
		if lookErr != nil {
			if *debug {
				dieHard()
			} else {
				panic(lookErr)
			}
		}

		args := []string{"kexec", "-initrd", *initrd, *linuxKernel}
		env := os.Environ()

		execErr := syscall.Exec(binary, args, env)
		if execErr != nil {
			if *debug {
				dieHard()
			} else {
				panic(execErr)
			}
		}
	} else {
		dieHard()
	}
}
<commit_msg>Fix error handling, add no-tpm option<commit_after>package main

import (
	"crypto/sha1"
	"crypto/sha256"
	"flag"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"syscall"

	"github.com/zaolin/go-tpm/tpm"
	"golang.org/x/crypto/ed25519"
	"golang.org/x/sys/unix"
)

const (
	tpmDevice  string = "/dev/tpm0"
	mountPath  string = "/mnt/vboot"
	filesystem string = "ext3"
)

func dieHard() {
	if e1, e2, err := syscall.Syscall6(syscall.SYS_REBOOT, syscall.LINUX_REBOOT_MAGIC1, syscall.LINUX_REBOOT_MAGIC2, syscall.LINUX_REBOOT_CMD_POWER_OFF, 0, 0, 0); err != 0 {
		log.Fatalf("a %v b %v err %v", e1, e2, err)
	}
}

func main() {
	var publicKey = flag.String("pubkey", "/etc/sig.pub", "A public key which should verify the signature.")
	var pcr = flag.Uint("pcr", 12, "The pcr index used for measuring the kernel before kexec.")
	var bootDev = flag.String("boot-device", "/dev/sda1", "The boot device which is used to kexec into a signed kernel.")
	var linuxKernel = flag.String("kernel", "/mnt/vboot/kernel", "Kernel image file path.")
	var linuxKernelSignature = flag.String("kernel-sig", "/mnt/vboot/kernel.sig", "Kernel image signature file path.")
	var initrd = flag.String("initrd", "/mnt/vboot/initrd", "Initrd file path.")
	var initrdSignature = flag.String("initrd-sig", "/mnt/vboot/initrd.sig", "Initrd signature file path.")
	var debug = flag.Bool("debug", false, "Enables debug mode.")
	var noTPM = flag.Bool("no-tpm", false, "Disables tpm measuring process.")

	flag.Parse()

	if err := os.MkdirAll(mountPath, os.ModePerm); err != nil {
		if *debug {
			panic(err)
		} else {
			dieHard()
		}
	}

	if err := unix.Mount(*bootDev, mountPath, filesystem, unix.MS_RDONLY, ""); err != nil {
		if *debug {
			panic(err)
		} else {
			dieHard()
		}
	}

	paths := [...]string{*publicKey, *linuxKernel, *linuxKernelSignature, *initrd, *initrdSignature}
	files := make(map[string][]byte)

	for _, element := range paths {
		data, err := ioutil.ReadFile(element)
		if err != nil {
			if *debug {
				panic(err)
			} else {
				dieHard()
			}
		} else {
			files[element] = data
		}
	}

	kernelDigest := sha256.Sum256(files[*linuxKernel])
	initrdDigest := sha256.Sum256(files[*initrd])

	pcrDigestKernel := sha1.Sum(files[*linuxKernel])
	pcrDigestInitrd := sha1.Sum(files[*initrd])

	kernelSuccess := ed25519.Verify(files[*publicKey], kernelDigest[:], files[*linuxKernelSignature])
	initrdSuccess := ed25519.Verify(files[*publicKey], initrdDigest[:], files[*linuxKernelSignature])

	if kernelSuccess && initrdSuccess {
		if !*noTPM {
			rwc, err := tpm.OpenTPM(tpmDevice)
			if err != nil {
				if *debug {
					panic(err)
				} else {
					dieHard()
				}
			}

			tpm.PcrExtend(rwc, uint32(*pcr), pcrDigestKernel)
			tpm.PcrExtend(rwc, uint32(*pcr), pcrDigestInitrd)
		}

		binary, lookErr := exec.LookPath("kexec")
		if lookErr != nil {
			if *debug {
				panic(lookErr)
			} else {
				dieHard()
			}
		}

		args := []string{"kexec", "-initrd", *initrd, *linuxKernel}
		env := os.Environ()

		execErr := syscall.Exec(binary, args, env)
		if execErr != nil {
			if *debug {
				panic(execErr)
			} else {
				dieHard()
			}
		}
	} else {
		dieHard()
	}
}
<|endoftext|>


<commit_before>package cliedit

// Elvish code for default bindings, assuming the editor ns as the global ns.
const defaultBindingsElv = `
insert:binding = (binding-table [
  &Left=  $move-dot-left~
  &Right= $move-dot-right~

  &Ctrl-Left=  $move-dot-left-word~
  &Ctrl-Right= $move-dot-right-word~
  &Alt-Left=   $move-dot-left-word~
  &Alt-Right=  $move-dot-right-word~
  &Alt-b=      $move-dot-left-word~
  &Alt-f=      $move-dot-right-word~

  &Home= $move-dot-sol~
  &End=  $move-dot-eol~

  &Backspace= $kill-rune-left~
  &Delete=    $kill-rune-right~
  &Ctrl-W=    $kill-word-left~
  &Ctrl-U=    $kill-line-left~
  &Ctrl-K=    $kill-line-right~

  &Ctrl-V= $insert-raw~

  &Alt-,=  $lastcmd:start~
  &Ctrl-R= $histlist:start~
  &Ctrl-L= $location:start~
  &Ctrl-N= $navigation:start~
  &Tab=    $completion:smart-start~
  &Up=     $history:start~

  &Enter=   $smart-enter~
  &Ctrl-D=  $return-eof~
])

command:binding = (binding-table [
 &'$'= $move-dot-eol~
 &0=   $move-dot-sol~
 &D=   $kill-line-right~
 &b=   $move-dot-left-word~
 &h=   $move-dot-left~
 &i=   $listing:close~
 &j=   $move-dot-down~
 &k=   $move-dot-up~
 &l=   $move-dot-right~
 &w=   $move-dot-right-word~
 &x=   $kill-rune-right~
])

listing:binding = (binding-table [
  &Up=        $listing:up~
  &Down=      $listing:down~
  &Tab=       $listing:down-cycle~
  &Shift-Tab= $listing:up-cycle~
  &Ctrl-'['=  $close-listing~
])

histlist:binding = (binding-table [
  &Ctrl-D= $histlist:toggle-dedup~
])

navigation:binding = (binding-table [
  &Ctrl-'['= $close-listing~
  &Left=     $navigation:left~
  &Right=    $navigation:right~
  &Up=       $navigation:up~
  &Down=     $navigation:down~
  &PageUp=   $navigation:page-up~
  &PageDown= $navigation:page-down~
  &Alt-Up=   $navigation:file-preview-up~
  &Alt-Down= $navigation:file-preview-down~
  &Enter=    $navigation:insert-selected-and-quit~
  &Alt-Enter= $navigation:insert-selected~
  &Ctrl-F=   $navigation:trigger-filter~
  &Ctrl-H=   $navigation:trigger-shown-hidden~
])

completion:binding = (binding-table [
  &Ctrl-'['= $completion:close~
  &Down=     $completion:down~
  &Up=       $completion:up~
  &Tab=      $completion:down-cycle~
  &Shift-Tab=$completion:up-cycle~
  &Left=     $completion:left~
  &Right=    $completion:right~
])

history:binding = (binding-table [
  &Up=       $history:up~
  &Down=     $history:down-or-quit~
  &Ctrl-'['= $history:close~
])

lastcmd:binding = (binding-table [
  &Alt-,=  $listing:accept~
])

#  &Up=        $listing:up~
#  &Down=      $listing:down~
#  &Tab=       $listing:down-cycle~
#  &Shift-Tab= $listing:up-cycle~
#
#  &Ctrl-F=    $listing:toggle-filtering~
#
#  &Alt-Enter= $listing:accept~
#  &Enter=     $listing:accept-close~
#  &Alt-,=     $listing:accept-close~
#  &Ctrl-'['=  $reset-mode~
#
#  &Default=   $listing:default~
`

// vi: set et:
<commit_msg>cliedit: Bind Alt-. to edit:insert-last-word.<commit_after>package cliedit

// Elvish code for default bindings, assuming the editor ns as the global ns.
const defaultBindingsElv = `
insert:binding = (binding-table [
  &Left=  $move-dot-left~
  &Right= $move-dot-right~

  &Ctrl-Left=  $move-dot-left-word~
  &Ctrl-Right= $move-dot-right-word~
  &Alt-Left=   $move-dot-left-word~
  &Alt-Right=  $move-dot-right-word~
  &Alt-b=      $move-dot-left-word~
  &Alt-f=      $move-dot-right-word~

  &Home= $move-dot-sol~
  &End=  $move-dot-eol~

  &Backspace= $kill-rune-left~
  &Delete=    $kill-rune-right~
  &Ctrl-W=    $kill-word-left~
  &Ctrl-U=    $kill-line-left~
  &Ctrl-K=    $kill-line-right~

  &Ctrl-V= $insert-raw~

  &Alt-,=  $lastcmd:start~
  &Alt-.=  $insert-last-word~
  &Ctrl-R= $histlist:start~
  &Ctrl-L= $location:start~
  &Ctrl-N= $navigation:start~
  &Tab=    $completion:smart-start~
  &Up=     $history:start~

  &Enter=   $smart-enter~
  &Ctrl-D=  $return-eof~
])

command:binding = (binding-table [
 &'$'= $move-dot-eol~
 &0=   $move-dot-sol~
 &D=   $kill-line-right~
 &b=   $move-dot-left-word~
 &h=   $move-dot-left~
 &i=   $listing:close~
 &j=   $move-dot-down~
 &k=   $move-dot-up~
 &l=   $move-dot-right~
 &w=   $move-dot-right-word~
 &x=   $kill-rune-right~
])

listing:binding = (binding-table [
  &Up=        $listing:up~
  &Down=      $listing:down~
  &Tab=       $listing:down-cycle~
  &Shift-Tab= $listing:up-cycle~
  &Ctrl-'['=  $close-listing~
])

histlist:binding = (binding-table [
  &Ctrl-D= $histlist:toggle-dedup~
])

navigation:binding = (binding-table [
  &Ctrl-'['= $close-listing~
  &Left=     $navigation:left~
  &Right=    $navigation:right~
  &Up=       $navigation:up~
  &Down=     $navigation:down~
  &PageUp=   $navigation:page-up~
  &PageDown= $navigation:page-down~
  &Alt-Up=   $navigation:file-preview-up~
  &Alt-Down= $navigation:file-preview-down~
  &Enter=    $navigation:insert-selected-and-quit~
  &Alt-Enter= $navigation:insert-selected~
  &Ctrl-F=   $navigation:trigger-filter~
  &Ctrl-H=   $navigation:trigger-shown-hidden~
])

completion:binding = (binding-table [
  &Ctrl-'['= $completion:close~
  &Down=     $completion:down~
  &Up=       $completion:up~
  &Tab=      $completion:down-cycle~
  &Shift-Tab=$completion:up-cycle~
  &Left=     $completion:left~
  &Right=    $completion:right~
])

history:binding = (binding-table [
  &Up=       $history:up~
  &Down=     $history:down-or-quit~
  &Ctrl-'['= $history:close~
])

lastcmd:binding = (binding-table [
  &Alt-,=  $listing:accept~
])

#  &Up=        $listing:up~
#  &Down=      $listing:down~
#  &Tab=       $listing:down-cycle~
#  &Shift-Tab= $listing:up-cycle~
#
#  &Ctrl-F=    $listing:toggle-filtering~
#
#  &Alt-Enter= $listing:accept~
#  &Enter=     $listing:accept-close~
#  &Alt-,=     $listing:accept-close~
#  &Ctrl-'['=  $reset-mode~
#
#  &Default=   $listing:default~
`

// vi: set et:
<|endoftext|>


<commit_before>// Copyright (c) 2015, Air Computing Inc. <oss@aerofs.com>
// All rights reserved.

package server

import (
	"bytes"
	"fmt"
	"github.com/aerofs/lipwig/ssmp"
	"sync"
)

// A Dispatcher parses incoming requests and reacts to them appropriately.
// All methods are safe to call from multiple goroutines simultaneously.
type Dispatcher struct {
	topics      *TopicManager
	connections *ConnectionManager
	handlers    map[string]handler

	bufPool sync.Pool
}

// NewDispatcher creates a SSMP dispatcher using the given TopicManager and ConnectionManager.
func NewDispatcher(topics *TopicManager, connections *ConnectionManager) *Dispatcher {
	return &Dispatcher{
		topics:      topics,
		connections: connections,
		handlers: map[string]handler{
			ssmp.SUBSCRIBE:   h(onSubscribe, fieldTo|fieldOption),
			ssmp.UNSUBSCRIBE: h(onUnsubscribe, fieldTo),
			ssmp.UCAST:       h(onUcast, fieldTo|fieldPayload),
			ssmp.MCAST:       h(onMcast, fieldTo|fieldPayload),
			ssmp.BCAST:       h(onBcast, fieldPayload),
			ssmp.PING:        h(onPing, 0),
			ssmp.PONG:        h(onPong, 0),
			ssmp.CLOSE:       h(onClose, 0),
		},
		bufPool: sync.Pool{
			New: func() interface{} {
				return new(bytes.Buffer)
			},
		},
	}
}

// Dispatch parses req, reacts appropriately and sends a response to c.
func (d *Dispatcher) Dispatch(c *Connection, verb []byte) bool {
	if ssmp.Equal(verb, ssmp.LOGIN) {
		fmt.Println("attempted re-login")
		c.Write(respNotAllowed)
		return false
	}
	h := d.handlers[string(verb)]
	if h.h == nil {
		// discard unknown command
		if _, err := c.r.DecodeCompat(); err != nil {
			return false
		}
		fmt.Println("unsupported command:", verb)
		c.Write(respNotImplemented)
		return true
	}
	var err error
	var to []byte
	var payload []byte
	if (h.f & fieldTo) != 0 {
		if to, err = c.r.DecodeId(); err != nil {
			return false
		}
	}
	if (h.f & fieldPayload) != 0 {
		if (h.f&fieldOption) == fieldOption && c.r.AtEnd() {
			payload = []byte{}
		} else if payload, err = c.r.DecodePayload(); err != nil {
			return false
		}
	}
	if !c.r.AtEnd() {
		return false
	}
	h.h(c, to, payload, c.r.RawMessage(), d)
	return true
}

func (d *Dispatcher) GetConnection(user []byte) *Connection {
	return d.connections.GetConnection(user)
}

func (d *Dispatcher) RemoveConnection(c *Connection) {
	d.connections.RemoveConnection(c)
}

func (d *Dispatcher) buffer() *bytes.Buffer {
	buf := d.bufPool.Get().(*bytes.Buffer)
	buf.Reset()
	return buf
}

func (d *Dispatcher) release(b *bytes.Buffer) {
	d.bufPool.Put(b)
}

////////////////////////////////////////////////////////////////////////////////

type handlerFunc func(*Connection, []byte, []byte, []byte, *Dispatcher)

const (
	fieldTo      = 1
	fieldPayload = 2
	fieldOption  = 6
)

type handler struct {
	f int32
	h handlerFunc
}

func h(h handlerFunc, f int32) handler {
	return handler{f: f, h: h}
}

func onSubscribe(c *Connection, n, option, s []byte, d *Dispatcher) {
	from := c.User
	if from == ssmp.Anonymous {
		c.Write(respNotAllowed)
		return
	}
	presence := ssmp.Equal(option, ssmp.PRESENCE)
	if len(option) > 0 && !presence {
		fmt.Println("unrecognized option:", option)
		c.Write(respBadRequest)
		return
	}
	t := d.topics.GetOrCreateTopic(n)
	if !t.Subscribe(c, presence) {
		// already subscribed
		c.Write(respConflict)
		return
	}

	c.Subscribe(t)
	c.Write(respOk)

	// notify existing subscribers of new sub
	buf := d.buffer()
	buf.Grow(5 + len(from) + len(s))
	buf.WriteString(respEvent)
	buf.WriteString(from)
	buf.WriteByte(' ')
	buf.Write(s)
	event := buf.Bytes()
	batch := event[4+len(from) : 15+len(from)+len(n)]

	var buf2 *bytes.Buffer = nil
	if presence {
		buf2 = d.buffer()
	}

	t.ForAll(func(cc *Connection, wantsPresence bool) {
		if c == cc {
			return
		}
		if wantsPresence {
			cc.Write(event)
		}
		if presence {
			buf2.WriteString(respEvent)
			buf2.WriteString(cc.User)
			buf2.Write(batch)
			if wantsPresence {
				buf2.WriteString(" PRESENCE\n")
			} else {
				buf2.WriteByte('\n')
			}
			if buf2.Len() > 512 {
				c.Write(buf2.Bytes())
				buf2.Reset()
			}
		}
	})
	d.release(buf)
	if buf2 != nil {
		if buf2.Len() > 0 {
			c.Write(buf2.Bytes())
		}
		d.release(buf2)
	}
}

func onUnsubscribe(c *Connection, n, _, s []byte, d *Dispatcher) {
	from := c.User
	if from == ssmp.Anonymous {
		c.Write(respNotAllowed)
		return
	}
	t := d.topics.GetTopic(n)
	if t == nil || !t.Unsubscribe(c) {
		c.Write(respNotFound)
		return
	}
	c.Unsubscribe(n)
	buf := d.buffer()
	buf.Grow(5 + len(from) + len(s))
	buf.WriteString(respEvent)
	buf.WriteString(from)
	buf.WriteByte(' ')
	buf.Write(s)
	event := buf.Bytes()
	t.ForAll(func(cc *Connection, wantsPresence bool) {
		if wantsPresence {
			cc.Write(event)
		}
	})
	d.release(buf)
	c.Write(respOk)
}

func onBcast(c *Connection, _, _, s []byte, d *Dispatcher) {
	from := c.User
	if from == ssmp.Anonymous {
		c.Write(respNotAllowed)
		return
	}
	buf := d.buffer()
	buf.Grow(5 + len(from) + len(s))
	buf.WriteString(respEvent)
	buf.WriteString(from)
	buf.WriteByte(' ')
	buf.Write(s)
	c.Broadcast(buf.Bytes())
	d.release(buf)
	c.Write(respOk)
}

func onUcast(c *Connection, u, _, s []byte, d *Dispatcher) {
	from := c.User
	cc := d.connections.GetConnection(u)
	if cc == nil {
		c.Write(respNotFound)
	} else {
		buf := d.buffer()
		buf.Grow(5 + len(from) + len(s))
		buf.WriteString(respEvent)
		buf.WriteString(from)
		buf.WriteByte(' ')
		buf.Write(s)
		cc.Write(buf.Bytes())
		d.release(buf)
		c.Write(respOk)
	}
}

func onMcast(c *Connection, n, _, s []byte, d *Dispatcher) {
	from := c.User
	t := d.topics.GetTopic(n)
	if t != nil {
		buf := d.buffer()
		buf.Grow(5 + len(from) + len(s))
		buf.WriteString(respEvent)
		buf.WriteString(from)
		buf.WriteByte(' ')
		buf.Write(s)
		msg := buf.Bytes()
		t.ForAll(func(cc *Connection, _ bool) {
			if c != cc {
				cc.Write(msg)
			}
		})
		d.release(buf)
	}
	c.Write(respOk)
}

var pong []byte = []byte(respEvent + ". " + ssmp.PONG + "\n")

func onPing(c *Connection, _, _, _ []byte, _ *Dispatcher) {
	c.Write(pong)
}

func onPong(c *Connection, _, _, _ []byte, _ *Dispatcher) {
	// nothing to see here...
}

func onClose(c *Connection, _, _, _ []byte, _ *Dispatcher) {
	c.Write(respOk)
	c.Close()
}
<commit_msg>Log string instead of byte slice for wrong command<commit_after>// Copyright (c) 2015, Air Computing Inc. <oss@aerofs.com>
// All rights reserved.

package server

import (
	"bytes"
	"fmt"
	"github.com/aerofs/lipwig/ssmp"
	"sync"
)

// A Dispatcher parses incoming requests and reacts to them appropriately.
// All methods are safe to call from multiple goroutines simultaneously.
type Dispatcher struct {
	topics      *TopicManager
	connections *ConnectionManager
	handlers    map[string]handler

	bufPool sync.Pool
}

// NewDispatcher creates a SSMP dispatcher using the given TopicManager and ConnectionManager.
func NewDispatcher(topics *TopicManager, connections *ConnectionManager) *Dispatcher {
	return &Dispatcher{
		topics:      topics,
		connections: connections,
		handlers: map[string]handler{
			ssmp.SUBSCRIBE:   h(onSubscribe, fieldTo|fieldOption),
			ssmp.UNSUBSCRIBE: h(onUnsubscribe, fieldTo),
			ssmp.UCAST:       h(onUcast, fieldTo|fieldPayload),
			ssmp.MCAST:       h(onMcast, fieldTo|fieldPayload),
			ssmp.BCAST:       h(onBcast, fieldPayload),
			ssmp.PING:        h(onPing, 0),
			ssmp.PONG:        h(onPong, 0),
			ssmp.CLOSE:       h(onClose, 0),
		},
		bufPool: sync.Pool{
			New: func() interface{} {
				return new(bytes.Buffer)
			},
		},
	}
}

// Dispatch parses req, reacts appropriately and sends a response to c.
func (d *Dispatcher) Dispatch(c *Connection, verb []byte) bool {
	if ssmp.Equal(verb, ssmp.LOGIN) {
		fmt.Println("attempted re-login")
		c.Write(respNotAllowed)
		return false
	}
	h := d.handlers[string(verb)]
	if h.h == nil {
		// discard unknown command
		if _, err := c.r.DecodeCompat(); err != nil {
			return false
		}
		fmt.Println("unsupported command:", string(verb))
		c.Write(respNotImplemented)
		return true
	}
	var err error
	var to []byte
	var payload []byte
	if (h.f & fieldTo) != 0 {
		if to, err = c.r.DecodeId(); err != nil {
			return false
		}
	}
	if (h.f & fieldPayload) != 0 {
		if (h.f&fieldOption) == fieldOption && c.r.AtEnd() {
			payload = []byte{}
		} else if payload, err = c.r.DecodePayload(); err != nil {
			return false
		}
	}
	if !c.r.AtEnd() {
		return false
	}
	h.h(c, to, payload, c.r.RawMessage(), d)
	return true
}

func (d *Dispatcher) GetConnection(user []byte) *Connection {
	return d.connections.GetConnection(user)
}

func (d *Dispatcher) RemoveConnection(c *Connection) {
	d.connections.RemoveConnection(c)
}

func (d *Dispatcher) buffer() *bytes.Buffer {
	buf := d.bufPool.Get().(*bytes.Buffer)
	buf.Reset()
	return buf
}

func (d *Dispatcher) release(b *bytes.Buffer) {
	d.bufPool.Put(b)
}

////////////////////////////////////////////////////////////////////////////////

type handlerFunc func(*Connection, []byte, []byte, []byte, *Dispatcher)

const (
	fieldTo      = 1
	fieldPayload = 2
	fieldOption  = 6
)

type handler struct {
	f int32
	h handlerFunc
}

func h(h handlerFunc, f int32) handler {
	return handler{f: f, h: h}
}

func onSubscribe(c *Connection, n, option, s []byte, d *Dispatcher) {
	from := c.User
	if from == ssmp.Anonymous {
		c.Write(respNotAllowed)
		return
	}
	presence := ssmp.Equal(option, ssmp.PRESENCE)
	if len(option) > 0 && !presence {
		fmt.Println("unrecognized option:", option)
		c.Write(respBadRequest)
		return
	}
	t := d.topics.GetOrCreateTopic(n)
	if !t.Subscribe(c, presence) {
		// already subscribed
		c.Write(respConflict)
		return
	}

	c.Subscribe(t)
	c.Write(respOk)

	// notify existing subscribers of new sub
	buf := d.buffer()
	buf.Grow(5 + len(from) + len(s))
	buf.WriteString(respEvent)
	buf.WriteString(from)
	buf.WriteByte(' ')
	buf.Write(s)
	event := buf.Bytes()
	batch := event[4+len(from) : 15+len(from)+len(n)]

	var buf2 *bytes.Buffer = nil
	if presence {
		buf2 = d.buffer()
	}

	t.ForAll(func(cc *Connection, wantsPresence bool) {
		if c == cc {
			return
		}
		if wantsPresence {
			cc.Write(event)
		}
		if presence {
			buf2.WriteString(respEvent)
			buf2.WriteString(cc.User)
			buf2.Write(batch)
			if wantsPresence {
				buf2.WriteString(" PRESENCE\n")
			} else {
				buf2.WriteByte('\n')
			}
			if buf2.Len() > 512 {
				c.Write(buf2.Bytes())
				buf2.Reset()
			}
		}
	})
	d.release(buf)
	if buf2 != nil {
		if buf2.Len() > 0 {
			c.Write(buf2.Bytes())
		}
		d.release(buf2)
	}
}

func onUnsubscribe(c *Connection, n, _, s []byte, d *Dispatcher) {
	from := c.User
	if from == ssmp.Anonymous {
		c.Write(respNotAllowed)
		return
	}
	t := d.topics.GetTopic(n)
	if t == nil || !t.Unsubscribe(c) {
		c.Write(respNotFound)
		return
	}
	c.Unsubscribe(n)
	buf := d.buffer()
	buf.Grow(5 + len(from) + len(s))
	buf.WriteString(respEvent)
	buf.WriteString(from)
	buf.WriteByte(' ')
	buf.Write(s)
	event := buf.Bytes()
	t.ForAll(func(cc *Connection, wantsPresence bool) {
		if wantsPresence {
			cc.Write(event)
		}
	})
	d.release(buf)
	c.Write(respOk)
}

func onBcast(c *Connection, _, _, s []byte, d *Dispatcher) {
	from := c.User
	if from == ssmp.Anonymous {
		c.Write(respNotAllowed)
		return
	}
	buf := d.buffer()
	buf.Grow(5 + len(from) + len(s))
	buf.WriteString(respEvent)
	buf.WriteString(from)
	buf.WriteByte(' ')
	buf.Write(s)
	c.Broadcast(buf.Bytes())
	d.release(buf)
	c.Write(respOk)
}

func onUcast(c *Connection, u, _, s []byte, d *Dispatcher) {
	from := c.User
	cc := d.connections.GetConnection(u)
	if cc == nil {
		c.Write(respNotFound)
	} else {
		buf := d.buffer()
		buf.Grow(5 + len(from) + len(s))
		buf.WriteString(respEvent)
		buf.WriteString(from)
		buf.WriteByte(' ')
		buf.Write(s)
		cc.Write(buf.Bytes())
		d.release(buf)
		c.Write(respOk)
	}
}

func onMcast(c *Connection, n, _, s []byte, d *Dispatcher) {
	from := c.User
	t := d.topics.GetTopic(n)
	if t != nil {
		buf := d.buffer()
		buf.Grow(5 + len(from) + len(s))
		buf.WriteString(respEvent)
		buf.WriteString(from)
		buf.WriteByte(' ')
		buf.Write(s)
		msg := buf.Bytes()
		t.ForAll(func(cc *Connection, _ bool) {
			if c != cc {
				cc.Write(msg)
			}
		})
		d.release(buf)
	}
	c.Write(respOk)
}

var pong []byte = []byte(respEvent + ". " + ssmp.PONG + "\n")

func onPing(c *Connection, _, _, _ []byte, _ *Dispatcher) {
	c.Write(pong)
}

func onPong(c *Connection, _, _, _ []byte, _ *Dispatcher) {
	// nothing to see here...
}

func onClose(c *Connection, _, _, _ []byte, _ *Dispatcher) {
	c.Write(respOk)
	c.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"text/template"

	"github.com/jroimartin/monmq"
	"github.com/jroimartin/orujo"
)

type MonmqCmd struct {
	Target  string
	Command string
}

type Filters struct {
	Ip       string
	Ports    []string
	Services []string
	Regexp   string
}

type Banner struct {
	Ip      string
	Port    string
	Service string
	Content string
}

func (s *server) tasksHandler(w http.ResponseWriter, r *http.Request) {
	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		orujo.RegisterError(w, fmt.Errorf("Reading POST:", err))
		return
	}
	tasks := strings.Split(string(data), ",")
	tm := newTaskManager(s.client, s.database)
	go tm.runTasks(tasks)
	fmt.Fprintln(w, "{\"status\": \"success\"}")
}

func (s *server) statusHandler(w http.ResponseWriter, r *http.Request) {
	switch {
	case r.Method == "POST":
		data, err := ioutil.ReadAll(r.Body)
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			orujo.RegisterError(w, fmt.Errorf("Reading POST:", err))
			return
		}
		var cmd MonmqCmd
		if err = json.Unmarshal(data, &cmd); err != nil {
			w.WriteHeader(http.StatusBadRequest)
			orujo.RegisterError(w, fmt.Errorf("Parsing json:", err))
			return
		}
		var command monmq.Command
		switch {
		case cmd.Command == "softshutdown":
			command = monmq.SoftShutdown
		case cmd.Command == "hardshutdown":
			command = monmq.HardShutdown
		case cmd.Command == "pause":
			command = monmq.Pause
		case cmd.Command == "resume":
			command = monmq.Resume
		}
		if err = s.supervisor.Invoke(command, cmd.Target); err != nil {
			w.WriteHeader(http.StatusBadRequest)
			orujo.RegisterError(w, fmt.Errorf("Invoking monmq command:", err))
			return
		}
	case r.Method == "GET":
		b, err := json.Marshal(s.supervisor.Status())
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			orujo.RegisterError(w, fmt.Errorf("error marshaling status:", err))
			return
		}
		fmt.Fprintf(w, "%s", b)
	}
}

func (s *server) queryHandler(w http.ResponseWriter, r *http.Request) {
	f := extractFilters(r)
	fmt.Println(f.Ip, f.Ports, f.Services, f.Regexp)

	t := template.Must(template.New("query").Parse(queryTemplate))
	query := &bytes.Buffer{}
	err := t.Execute(query, f)
	if err != nil {
		log.Println("executing template:", err)
	}

	stmt, err := s.database.Prepare(query.String())
	if err != nil {
		log.Println("preparing statement:", err)
	}

	data := make([]interface{}, 0, len(f.Ports))
	if f.Ip != "" {
		data = append(data, f.Ip)
	}
	for _, v := range f.Ports {
		data = append(data, v)
	}
	for _, v := range f.Services {
		data = append(data, v)
	}
	if f.Regexp != "" {
		data = append(data, f.Regexp)
	}

	rows, err := stmt.Query(data...)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		orujo.RegisterError(w, fmt.Errorf("error querying:", err))
		return
	}
	defer rows.Close()

	var result []Banner
	for rows.Next() {
		var curr Banner
		if err := rows.Scan(&curr.Ip, &curr.Port, &curr.Service, &curr.Content); err != nil {
			log.Fatal(err)
		}
		result = append(result, curr)
	}
	jsoned, err := json.Marshal(result)
	if err != nil {
		log.Println("marshaling:", err)
	}
	fmt.Fprintf(w, string(jsoned))
}

const (
	queryTemplate = `SELECT DISTINCT INET_NTOA(ip), port, service, content FROM banners
{{if or .Ip .Ports .Services .Regexp}} WHERE{{end}}
{{if .Ip}} ip = INET_ATON((?)){{end}}
{{if and .Ip .Ports}} AND{{end}}{{if .Ports}} port IN ({{range $i, $v := .Ports}}{{if $i}},{{end}}?{{end}}){{end}}
{{if and .Services (or .Ports .Services)}} AND{{end}}{{if .Services}} service IN ({{range $i, $v := .Services}}{{if $i}},{{end}}?{{end}}){{end}}
{{if and .Regexp (or .Ip .Ports .Services)}} AND{{end}}{{if .Regexp}} content regexp (?){{end}};`
)

func extractFilters(request *http.Request) Filters {
	var p, s []string
	var r string

	values := request.URL.Query()
	ip := strings.TrimPrefix(request.URL.Path, "/ips")
	if ip != "" {
		ip = strings.TrimPrefix(ip, "/")
	}
	if values["port"] != nil {
		p = strings.Split(values["port"][0], ",")
	}
	if values["service"] != nil {
		s = strings.Split(values["service"][0], ",")
	}
	if values["regexp"] != nil {
		r = values["regexp"][0]
	}
	filters := Filters{
		Ip:       ip,
		Ports:    p,
		Services: s,
		Regexp:   r,
	}
	return filters
}
<commit_msg>Removed debug print<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"text/template"

	"github.com/jroimartin/monmq"
	"github.com/jroimartin/orujo"
)

type MonmqCmd struct {
	Target  string
	Command string
}

type Filters struct {
	Ip       string
	Ports    []string
	Services []string
	Regexp   string
}

type Banner struct {
	Ip      string
	Port    string
	Service string
	Content string
}

func (s *server) tasksHandler(w http.ResponseWriter, r *http.Request) {
	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		orujo.RegisterError(w, fmt.Errorf("Reading POST:", err))
		return
	}
	tasks := strings.Split(string(data), ",")
	tm := newTaskManager(s.client, s.database)
	go tm.runTasks(tasks)
	fmt.Fprintln(w, "{\"status\": \"success\"}")
}

func (s *server) statusHandler(w http.ResponseWriter, r *http.Request) {
	switch {
	case r.Method == "POST":
		data, err := ioutil.ReadAll(r.Body)
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			orujo.RegisterError(w, fmt.Errorf("Reading POST:", err))
			return
		}
		var cmd MonmqCmd
		if err = json.Unmarshal(data, &cmd); err != nil {
			w.WriteHeader(http.StatusBadRequest)
			orujo.RegisterError(w, fmt.Errorf("Parsing json:", err))
			return
		}
		var command monmq.Command
		switch {
		case cmd.Command == "softshutdown":
			command = monmq.SoftShutdown
		case cmd.Command == "hardshutdown":
			command = monmq.HardShutdown
		case cmd.Command == "pause":
			command = monmq.Pause
		case cmd.Command == "resume":
			command = monmq.Resume
		}
		if err = s.supervisor.Invoke(command, cmd.Target); err != nil {
			w.WriteHeader(http.StatusBadRequest)
			orujo.RegisterError(w, fmt.Errorf("Invoking monmq command:", err))
			return
		}
	case r.Method == "GET":
		b, err := json.Marshal(s.supervisor.Status())
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			orujo.RegisterError(w, fmt.Errorf("error marshaling status:", err))
			return
		}
		fmt.Fprintf(w, "%s", b)
	}
}

func (s *server) queryHandler(w http.ResponseWriter, r *http.Request) {
	f := extractFilters(r)

	t := template.Must(template.New("query").Parse(queryTemplate))
	query := &bytes.Buffer{}
	err := t.Execute(query, f)
	if err != nil {
		log.Println("executing template:", err)
	}

	stmt, err := s.database.Prepare(query.String())
	if err != nil {
		log.Println("preparing statement:", err)
	}

	data := make([]interface{}, 0, len(f.Ports))
	if f.Ip != "" {
		data = append(data, f.Ip)
	}
	for _, v := range f.Ports {
		data = append(data, v)
	}
	for _, v := range f.Services {
		data = append(data, v)
	}
	if f.Regexp != "" {
		data = append(data, f.Regexp)
	}

	rows, err := stmt.Query(data...)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		orujo.RegisterError(w, fmt.Errorf("error querying:", err))
		return
	}
	defer rows.Close()

	var result []Banner
	for rows.Next() {
		var curr Banner
		if err := rows.Scan(&curr.Ip, &curr.Port, &curr.Service, &curr.Content); err != nil {
			log.Fatal(err)
		}
		result = append(result, curr)
	}
	jsoned, err := json.Marshal(result)
	if err != nil {
		log.Println("marshaling:", err)
	}
	fmt.Fprintf(w, string(jsoned))
}

const (
	queryTemplate = `SELECT DISTINCT INET_NTOA(ip), port, service, content FROM banners
{{if or .Ip .Ports .Services .Regexp}} WHERE{{end}}
{{if .Ip}} ip = INET_ATON((?)){{end}}
{{if and .Ip .Ports}} AND{{end}}{{if .Ports}} port IN ({{range $i, $v := .Ports}}{{if $i}},{{end}}?{{end}}){{end}}
{{if and .Services (or .Ports .Services)}} AND{{end}}{{if .Services}} service IN ({{range $i, $v := .Services}}{{if $i}},{{end}}?{{end}}){{end}}
{{if and .Regexp (or .Ip .Ports .Services)}} AND{{end}}{{if .Regexp}} content regexp (?){{end}};`
)

func extractFilters(request *http.Request) Filters {
	var p, s []string
	var r string

	values := request.URL.Query()
	ip := strings.TrimPrefix(request.URL.Path, "/ips")
	if ip != "" {
		ip = strings.TrimPrefix(ip, "/")
	}
	if values["port"] != nil {
		p = strings.Split(values["port"][0], ",")
	}
	if values["service"] != nil {
		s = strings.Split(values["service"][0], ",")
	}
	if values["regexp"] != nil {
		r = values["regexp"][0]
	}
	filters := Filters{
		Ip:       ip,
		Ports:    p,
		Services: s,
		Regexp:   r,
	}
	return filters
}
<|endoftext|>


<commit_before>package string

import (
	"fmt"
	"github.com/qb0C80aE/clay/logging"
	mapstructutilpkg "github.com/qb0C80aE/clay/util/mapstruct"
	"strings"
)

var utility = &Utility{}

// Utility handles string operation
type Utility struct {
}

// GetUtility returns the instance of utility
func GetUtility() *Utility {
	return utility
}

// Split splits string by given separator into an slice
func (receiver *Utility) Split(value interface{}, separator string) interface{} {
	data := fmt.Sprintf("%v", value)
	return strings.Split(data, separator)
}

// Join joins given slice with give separator into a string
func (receiver *Utility) Join(slice interface{}, separator string) (interface{}, error) {
	interfaceSlice, err := mapstructutilpkg.GetUtility().SliceToInterfaceSlice(slice)
	if err != nil {
		logging.Logger().Debug(err.Error())
		return nil, err
	}
	stringSlice := make([]string, len(interfaceSlice))

	for index, item := range interfaceSlice {
		stringSlice[index] = fmt.Sprintf("%v", item)
	}

	return strings.Join(stringSlice, separator), nil
}

// Trim eliminate cutset string from both side of given string
func (receiver *Utility) Trim(value interface{}, cutset string) interface{} {
	data := fmt.Sprintf("%v", value)
	return strings.Trim(data, cutset)
}
<commit_msg>Add Sprintf to String utility in order to enable scripts format strings<commit_after>package string

import (
	"fmt"
	"github.com/qb0C80aE/clay/logging"
	mapstructutilpkg "github.com/qb0C80aE/clay/util/mapstruct"
	"strings"
)

var utility = &Utility{}

// Utility handles string operation
type Utility struct {
}

// GetUtility returns the instance of utility
func GetUtility() *Utility {
	return utility
}

// Sprintf apply sprintf to given strings
func (receiver *Utility) Sprintf(format string, parameters ...interface{}) interface{} {
	return fmt.Sprintf(format, parameters...)
}

// Split splits string by given separator into an slice
func (receiver *Utility) Split(value interface{}, separator string) interface{} {
	data := fmt.Sprintf("%v", value)
	return strings.Split(data, separator)
}

// Join joins given slice with give separator into a string
func (receiver *Utility) Join(slice interface{}, separator string) (interface{}, error) {
	interfaceSlice, err := mapstructutilpkg.GetUtility().SliceToInterfaceSlice(slice)
	if err != nil {
		logging.Logger().Debug(err.Error())
		return nil, err
	}
	stringSlice := make([]string, len(interfaceSlice))

	for index, item := range interfaceSlice {
		stringSlice[index] = fmt.Sprintf("%v", item)
	}

	return strings.Join(stringSlice, separator), nil
}

// Trim eliminate cutset string from both side of given string
func (receiver *Utility) Trim(value interface{}, cutset string) interface{} {
	data := fmt.Sprintf("%v", value)
	return strings.Trim(data, cutset)
}
<|endoftext|>


<commit_before>package bip39

import (
	"crypto/rand"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"errors"
	"math/big"
	"strings"

	"github.com/tyler-smith/go-bip39/wordlists"
	"golang.org/x/crypto/pbkdf2"
)

var (
	// Some bitwise operands for working with big.Ints
	last11BitsMask          = big.NewInt(2047)
	rightShift11BitsDivider = big.NewInt(2048)
	bigOne                  = big.NewInt(1)
	bigTwo                  = big.NewInt(2)

	// wordList is the set of words to use
	wordList []string

	// wordMap is a reverse lookup map for wordList
	wordMap map[string]int
)

var (
	// ErrInvalidMnemonic is returned when trying to use a malformed mnemonic.
	ErrInvalidMnemonic = errors.New("Invalid menomic")

	// ErrEntropyLengthInvalid is returned when trying to use an entropy set with
	// an invalid size.
	ErrEntropyLengthInvalid = errors.New("Entropy length must be [128, 256] and a multiple of 32")

	// ErrValidatedSeedLengthMismatch is returned when a validated seed is not the
	// same size as the given seed. This should never happen is present only as a
	// sanity assertion.
	ErrValidatedSeedLengthMismatch = errors.New("Seed length does not match validated seed length")

	// ErrChecksumIncorrect is returned when entropy has the incorrect checksum.
	ErrChecksumIncorrect = errors.New("Checksum incorrect")
)

func init() {
	SetWordList(wordlists.English)
}

// SetWordList sets the list of words to use for mnemonics. Currently the list
// that is set is used package-wide.
func SetWordList(list []string) {
	wordList = list
	wordMap = map[string]int{}
	for i, v := range wordList {
		wordMap[v] = i
	}
}

// NewEntropy will create random entropy bytes
// so long as the requested size bitSize is an appropriate size.
func NewEntropy(bitSize int) ([]byte, error) {
	err := validateEntropyBitSize(bitSize)
	if err != nil {
		return nil, err
	}

	entropy := make([]byte, bitSize/8)
	_, err = rand.Read(entropy)
	return entropy, err
}

// NewMnemonic will return a string consisting of the mnemonic words for
// the given entropy.
// If the provide entropy is invalid, an error will be returned.
func NewMnemonic(entropy []byte) (string, error) {
	// Compute some lengths for convenience
	entropyBitLength := len(entropy) * 8
	checksumBitLength := entropyBitLength / 32
	sentenceLength := (entropyBitLength + checksumBitLength) / 11

	err := validateEntropyBitSize(entropyBitLength)
	if err != nil {
		return "", err
	}

	// Add checksum to entropy
	entropy = addChecksum(entropy)

	// Break entropy up into sentenceLength chunks of 11 bits
	// For each word AND mask the rightmost 11 bits and find the word at that index
	// Then bitshift entropy 11 bits right and repeat
	// Add to the last empty slot so we can work with LSBs instead of MSB

	// Entropy as an int so we can bitmask without worrying about bytes slices
	entropyInt := new(big.Int).SetBytes(entropy)

	// Slice to hold words in
	words := make([]string, sentenceLength)

	// Throw away big int for AND masking
	word := big.NewInt(0)

	for i := sentenceLength - 1; i >= 0; i-- {
		// Get 11 right most bits and bitshift 11 to the right for next time
		word.And(entropyInt, last11BitsMask)
		entropyInt.Div(entropyInt, rightShift11BitsDivider)

		// Get the bytes representing the 11 bits as a 2 byte slice
		wordBytes := padByteSlice(word.Bytes(), 2)

		// Convert bytes to an index and add that word to the list
		words[i] = wordList[binary.BigEndian.Uint16(wordBytes)]
	}

	return strings.Join(words, " "), nil
}

// MnemonicToByteArray takes a mnemonic string and turns it into a byte array
// suitable for creating another mnemonic.
// An error is returned if the mnemonic is invalid.
func MnemonicToByteArray(mnemonic string) ([]byte, error) {
	var (
		mnemonicSlice    = strings.Split(mnemonic, " ")
		entropyBitSize   = len(mnemonicSlice) * 11
		checksumBitSize  = entropyBitSize % 32
		fullByteSize     = (entropyBitSize-checksumBitSize)/8 + 1
		checksumByteSize = fullByteSize - (fullByteSize % 4)
	)

	// Pre validate that the mnemonic is well formed and only contains words that
	// are present in the word list
	if !IsMnemonicValid(mnemonic) {
		return nil, ErrInvalidMnemonic
	}

	// Convert word indices to a `big.Int` representing the entropy
	checksummedEntropy := big.NewInt(0)
	modulo := big.NewInt(2048)
	for _, v := range mnemonicSlice {
		index := big.NewInt(int64(wordMap[v]))
		checksummedEntropy.Mul(checksummedEntropy, modulo)
		checksummedEntropy.Add(checksummedEntropy, index)
	}

	// Calculate the unchecksummed entropy so we can validate that the checksum is
	// correct
	checksumModulo := big.NewInt(0).Exp(bigTwo, big.NewInt(int64(checksumBitSize)), nil)
	rawEntropy := big.NewInt(0).Div(checksummedEntropy, checksumModulo)

	// Convert `big.Int`s to byte padded byte slices
	rawEntropyBytes := padByteSlice(rawEntropy.Bytes(), checksumByteSize)
	checksummedEntropyBytes := padByteSlice(checksummedEntropy.Bytes(), fullByteSize)

	// Validate that the checksum is correct
	newChecksummedEntropyBytes := padByteSlice(addChecksum(rawEntropyBytes), fullByteSize)
	if !compareByteSlices(checksummedEntropyBytes, newChecksummedEntropyBytes) {
		return nil, ErrChecksumIncorrect
	}

	return checksummedEntropyBytes, nil
}

// NewSeedWithErrorChecking creates a hashed seed output given the mnemonic string and a password.
// An error is returned if the mnemonic is not convertible to a byte array.
func NewSeedWithErrorChecking(mnemonic string, password string) ([]byte, error) {
	_, err := MnemonicToByteArray(mnemonic)
	if err != nil {
		return nil, err
	}
	return NewSeed(mnemonic, password), nil
}

// NewSeed creates a hashed seed output given a provided string and password.
// No checking is performed to validate that the string provided is a valid mnemonic.
func NewSeed(mnemonic string, password string) []byte {
	return pbkdf2.Key([]byte(mnemonic), []byte("mnemonic"+password), 2048, 64, sha512.New)
}

// IsMnemonicValid attempts to verify that the provided mnemonic is valid.
// Validity is determined by both the number of words being appropriate,
// and that all the words in the mnemonic are present in the word list.
func IsMnemonicValid(mnemonic string) bool {
	// Create a list of all the words in the mnemonic sentence
	words := strings.Fields(mnemonic)

	// Get word count
	wordCount := len(words)

	// The number of words should be 12, 15, 18, 21 or 24
	if wordCount%3 != 0 || wordCount < 12 || wordCount > 24 {
		return false
	}

	// Check if all words belong in the wordlist
	for _, word := range words {
		if _, ok := wordMap[word]; !ok {
			return false
		}
	}

	return true
}

// Appends to data the first (len(data) / 32)bits of the result of sha256(data)
// Currently only supports data up to 32 bytes
func addChecksum(data []byte) []byte {
	// Get first byte of sha256
	hasher := sha256.New()
	hasher.Write(data)
	hash := hasher.Sum(nil)
	firstChecksumByte := hash[0]

	// len() is in bytes so we divide by 4
	checksumBitLength := uint(len(data) / 4)

	// For each bit of check sum we want we shift the data one the left
	// and then set the (new) right most bit equal to checksum bit at that index
	// staring from the left
	dataBigInt := new(big.Int).SetBytes(data)
	for i := uint(0); i < checksumBitLength; i++ {
		// Bitshift 1 left
		dataBigInt.Mul(dataBigInt, bigTwo)

		// Set rightmost bit if leftmost checksum bit is set
		if uint8(firstChecksumByte&(1<<(7-i))) > 0 {
			dataBigInt.Or(dataBigInt, bigOne)
		}
	}

	return dataBigInt.Bytes()
}

// validateEntropyBitSize ensures that entropy is the correct size for being a
// mnemonic.
func validateEntropyBitSize(bitSize int) error {
	if (bitSize%32) != 0 || bitSize < 128 || bitSize > 256 {
		return ErrEntropyLengthInvalid
	}
	return nil
}

// padByteSlice returns a byte slice of the given size with contents of the
// given slice left padded and any empty spaces filled with 0's.
func padByteSlice(slice []byte, length int) []byte {
	if len(slice) >= length {
		return slice
	}
	newSlice := make([]byte, length-len(slice))
	return append(newSlice, slice...)
}

// compareByteSlices returns true of the byte slices have equal contents and
// returns false otherwise.
func compareByteSlices(a, b []byte) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}
<commit_msg>improve padByteSlice<commit_after>package bip39

import (
	"crypto/rand"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"errors"
	"math/big"
	"strings"

	"github.com/tyler-smith/go-bip39/wordlists"
	"golang.org/x/crypto/pbkdf2"
)

var (
	// Some bitwise operands for working with big.Ints
	last11BitsMask          = big.NewInt(2047)
	rightShift11BitsDivider = big.NewInt(2048)
	bigOne                  = big.NewInt(1)
	bigTwo                  = big.NewInt(2)

	// wordList is the set of words to use
	wordList []string

	// wordMap is a reverse lookup map for wordList
	wordMap map[string]int
)

var (
	// ErrInvalidMnemonic is returned when trying to use a malformed mnemonic.
	ErrInvalidMnemonic = errors.New("Invalid menomic")

	// ErrEntropyLengthInvalid is returned when trying to use an entropy set with
	// an invalid size.
	ErrEntropyLengthInvalid = errors.New("Entropy length must be [128, 256] and a multiple of 32")

	// ErrValidatedSeedLengthMismatch is returned when a validated seed is not the
	// same size as the given seed. This should never happen is present only as a
	// sanity assertion.
	ErrValidatedSeedLengthMismatch = errors.New("Seed length does not match validated seed length")

	// ErrChecksumIncorrect is returned when entropy has the incorrect checksum.
	ErrChecksumIncorrect = errors.New("Checksum incorrect")
)

func init() {
	SetWordList(wordlists.English)
}

// SetWordList sets the list of words to use for mnemonics. Currently the list
// that is set is used package-wide.
func SetWordList(list []string) {
	wordList = list
	wordMap = map[string]int{}
	for i, v := range wordList {
		wordMap[v] = i
	}
}

// NewEntropy will create random entropy bytes
// so long as the requested size bitSize is an appropriate size.
func NewEntropy(bitSize int) ([]byte, error) {
	err := validateEntropyBitSize(bitSize)
	if err != nil {
		return nil, err
	}

	entropy := make([]byte, bitSize/8)
	_, err = rand.Read(entropy)
	return entropy, err
}

// NewMnemonic will return a string consisting of the mnemonic words for
// the given entropy.
// If the provide entropy is invalid, an error will be returned.
func NewMnemonic(entropy []byte) (string, error) {
	// Compute some lengths for convenience
	entropyBitLength := len(entropy) * 8
	checksumBitLength := entropyBitLength / 32
	sentenceLength := (entropyBitLength + checksumBitLength) / 11

	err := validateEntropyBitSize(entropyBitLength)
	if err != nil {
		return "", err
	}

	// Add checksum to entropy
	entropy = addChecksum(entropy)

	// Break entropy up into sentenceLength chunks of 11 bits
	// For each word AND mask the rightmost 11 bits and find the word at that index
	// Then bitshift entropy 11 bits right and repeat
	// Add to the last empty slot so we can work with LSBs instead of MSB

	// Entropy as an int so we can bitmask without worrying about bytes slices
	entropyInt := new(big.Int).SetBytes(entropy)

	// Slice to hold words in
	words := make([]string, sentenceLength)

	// Throw away big int for AND masking
	word := big.NewInt(0)

	for i := sentenceLength - 1; i >= 0; i-- {
		// Get 11 right most bits and bitshift 11 to the right for next time
		word.And(entropyInt, last11BitsMask)
		entropyInt.Div(entropyInt, rightShift11BitsDivider)

		// Get the bytes representing the 11 bits as a 2 byte slice
		wordBytes := padByteSlice(word.Bytes(), 2)

		// Convert bytes to an index and add that word to the list
		words[i] = wordList[binary.BigEndian.Uint16(wordBytes)]
	}

	return strings.Join(words, " "), nil
}

// MnemonicToByteArray takes a mnemonic string and turns it into a byte array
// suitable for creating another mnemonic.
// An error is returned if the mnemonic is invalid.
func MnemonicToByteArray(mnemonic string) ([]byte, error) {
	var (
		mnemonicSlice    = strings.Split(mnemonic, " ")
		entropyBitSize   = len(mnemonicSlice) * 11
		checksumBitSize  = entropyBitSize % 32
		fullByteSize     = (entropyBitSize-checksumBitSize)/8 + 1
		checksumByteSize = fullByteSize - (fullByteSize % 4)
	)

	// Pre validate that the mnemonic is well formed and only contains words that
	// are present in the word list
	if !IsMnemonicValid(mnemonic) {
		return nil, ErrInvalidMnemonic
	}

	// Convert word indices to a `big.Int` representing the entropy
	checksummedEntropy := big.NewInt(0)
	modulo := big.NewInt(2048)
	for _, v := range mnemonicSlice {
		index := big.NewInt(int64(wordMap[v]))
		checksummedEntropy.Mul(checksummedEntropy, modulo)
		checksummedEntropy.Add(checksummedEntropy, index)
	}

	// Calculate the unchecksummed entropy so we can validate that the checksum is
	// correct
	checksumModulo := big.NewInt(0).Exp(bigTwo, big.NewInt(int64(checksumBitSize)), nil)
	rawEntropy := big.NewInt(0).Div(checksummedEntropy, checksumModulo)

	// Convert `big.Int`s to byte padded byte slices
	rawEntropyBytes := padByteSlice(rawEntropy.Bytes(), checksumByteSize)
	checksummedEntropyBytes := padByteSlice(checksummedEntropy.Bytes(), fullByteSize)

	// Validate that the checksum is correct
	newChecksummedEntropyBytes := padByteSlice(addChecksum(rawEntropyBytes), fullByteSize)
	if !compareByteSlices(checksummedEntropyBytes, newChecksummedEntropyBytes) {
		return nil, ErrChecksumIncorrect
	}

	return checksummedEntropyBytes, nil
}

// NewSeedWithErrorChecking creates a hashed seed output given the mnemonic string and a password.
// An error is returned if the mnemonic is not convertible to a byte array.
func NewSeedWithErrorChecking(mnemonic string, password string) ([]byte, error) {
	_, err := MnemonicToByteArray(mnemonic)
	if err != nil {
		return nil, err
	}
	return NewSeed(mnemonic, password), nil
}

// NewSeed creates a hashed seed output given a provided string and password.
// No checking is performed to validate that the string provided is a valid mnemonic.
func NewSeed(mnemonic string, password string) []byte {
	return pbkdf2.Key([]byte(mnemonic), []byte("mnemonic"+password), 2048, 64, sha512.New)
}

// IsMnemonicValid attempts to verify that the provided mnemonic is valid.
// Validity is determined by both the number of words being appropriate,
// and that all the words in the mnemonic are present in the word list.
func IsMnemonicValid(mnemonic string) bool {
	// Create a list of all the words in the mnemonic sentence
	words := strings.Fields(mnemonic)

	// Get word count
	wordCount := len(words)

	// The number of words should be 12, 15, 18, 21 or 24
	if wordCount%3 != 0 || wordCount < 12 || wordCount > 24 {
		return false
	}

	// Check if all words belong in the wordlist
	for _, word := range words {
		if _, ok := wordMap[word]; !ok {
			return false
		}
	}

	return true
}

// Appends to data the first (len(data) / 32)bits of the result of sha256(data)
// Currently only supports data up to 32 bytes
func addChecksum(data []byte) []byte {
	// Get first byte of sha256
	hasher := sha256.New()
	hasher.Write(data)
	hash := hasher.Sum(nil)
	firstChecksumByte := hash[0]

	// len() is in bytes so we divide by 4
	checksumBitLength := uint(len(data) / 4)

	// For each bit of check sum we want we shift the data one the left
	// and then set the (new) right most bit equal to checksum bit at that index
	// staring from the left
	dataBigInt := new(big.Int).SetBytes(data)
	for i := uint(0); i < checksumBitLength; i++ {
		// Bitshift 1 left
		dataBigInt.Mul(dataBigInt, bigTwo)

		// Set rightmost bit if leftmost checksum bit is set
		if uint8(firstChecksumByte&(1<<(7-i))) > 0 {
			dataBigInt.Or(dataBigInt, bigOne)
		}
	}

	return dataBigInt.Bytes()
}

// validateEntropyBitSize ensures that entropy is the correct size for being a
// mnemonic.
func validateEntropyBitSize(bitSize int) error {
	if (bitSize%32) != 0 || bitSize < 128 || bitSize > 256 {
		return ErrEntropyLengthInvalid
	}
	return nil
}

// padByteSlice returns a byte slice of the given size with contents of the
// given slice left padded and any empty spaces filled with 0's.
func padByteSlice(slice []byte, length int) []byte {
	offset := length - len(slice)
	if offset <= 0 {
		return slice
	}
	newSlice := make([]byte, length)
	copy(newSlice[offset:], slice)
	return newSlice
}

// compareByteSlices returns true of the byte slices have equal contents and
// returns false otherwise.
func compareByteSlices(a, b []byte) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}
<|endoftext|>