Newer
Older
"flag"
"fmt"
"log"
"os"
"path"
"sort"
"strconv"
"strings"
)
const (
DefaultURL = "http://localhost:8545"
var (
url string
json bool
help bool
flags flag.FlagSet
command string
description string
)
func setFlags() {
flags.BoolVar(&json, "json", false, "Produce salida en formato json")
flags.StringVar(&url, "url", "", "URL para conexión con geth. Ejemplo: '/home/bfa/bfa/network/node/geth.ipc' o 'http://localhost:8545'")
flags.BoolVar(&help, "h", false, "")
flags.BoolVar(&help, "help", false, "Muestra esta ayuda")
}
func updateURL(url string) (updated string) {
const (
defaultIPC = "/home/bfa/bfa/network/node/geth.ipc"
defaultHTTP = "http://localhost:8545"
)
if url != "" { // We accept the user selected URL
return
}
// First, we try IPC
updated = defaultIPC
if bfaNetworkDir := os.Getenv("BFANETWORKDIR"); bfaNetworkDir != "" {
updated = bfaNetworkDir + "/node/get.ipc"
}
if fileInfo, err := os.Stat(updated); err == nil && (fileInfo.Mode()&os.ModeSocket) != 0 {
return
}
updated = defaultHTTP
return
}
func usage(errorCode int) {
fmt.Fprintf(os.Stderr, "Uso: %v %v [opciones] %v\n%v\n", os.Args[0], command, otherArgs, description)
flags.PrintDefaults()
os.Exit(errorCode)
}
func parseFlags() {
flags.Parse(os.Args[2:])
if help {
usage(0)
}
}
func proposals() {
var blockNumber int64
description = "Detalla el estado de las votaciones en curso"
setFlags()
flags.Int64Var(&blockNumber, "block-number", -1, "Número del bloque en el cual se quiere conocer el estado de la propuesta (-1 para el último)")
parseFlags()
url = updateURL(url)
node, err := bfa.Dial(url)
util.Check(err)
defer node.Close()
votes := node.GetVotes(blockNumber)
if json {
util.PrintJson(votes)
return
}
fmt.Printf("Bloque: %d\nPropuestas en curso: %d\n", votes.BlockNumber, len(votes.Proposals))
for _, proposal := range votes.Proposals {
fmt.Printf("Propuesta: %v\n", proposal)
for _, signer := range votes.Signers {
b := votes.Votes[proposal][signer]
var v string
if b == nil {
v = ""
} else {
v = strconv.FormatBool(*b)
}
fmt.Printf("\t%v: %v\n", signer, v)
}
tally := votes.Tally[proposal]
fmt.Printf("A favor: %v, en contra: %v, no votaron: %v\n", tally.True, tally.False, tally.Null)
}
}
func sealers() {
var (
blockNumber int64
status bool
)
description = "Presenta la lista de selladores. Opcionalmente indica el último bloque sellado por cada uno."
setFlags()
flags.Int64Var(&blockNumber, "block-number", -1, "Número del bloque en el cual se quiere conocer la lista de selladores (-1 para el último)")
flags.BoolVar(&status, "status", false, "Indica el último bloque sellado por cada sellador, o -1 si un nodo no ha sellado en las últimas 5 rondas.")
parseFlags()
if blockNumber == 0{
panic("El bloque génesis no tiene firmantes")
}
url = updateURL(url)
node, err := bfa.Dial(url)
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
defer node.Close()
if status {
sealers := node.SealersStatus(blockNumber)
if json {
util.PrintJson(sealers)
return
}
var list []string
for sealer := range sealers {
list = append(list, sealer)
}
sort.Slice(list, func(i, j int) bool { return sealers[list[i]] > sealers[list[j]] })
length := util.Max(2, int64(len(strconv.FormatInt(sealers[list[0]], 10))))
for _, sealer := range list {
fmt.Printf("%v: %*d\n", sealer, length, sealers[sealer])
}
} else {
sealers := node.GetSignersAtBlock(blockNumber)
sort.Slice(sealers, func(i, j int) bool { return sealers[i] < sealers[j] })
if json {
util.PrintJson(sealers)
} else {
for _, sealer := range sealers {
fmt.Println(sealer)
}
}
}
proposals []string
)
description = "Vota por una propuesta."
setFlags()
flags.BoolVar(&all, "all", false, "Vota en todas las propuestas activas")
flags.BoolVar(&authorize, "authorize", true, "Sentido del voto (true: a favor, false: en contra)")
parseFlags()
url = updateURL(url)
node, err := bfa.Dial(url)
util.Check(err)
defer node.Close()
util.PanicIf(!node.IsSealer(bfa.Self), "Solo los selladores pueden votar")
if all {
votes := node.GetVotes(latest)
for _, proposal := range votes.Proposals {
proposals = append(proposals, proposal)
}
if flags.NArg() != 0 {
fmt.Fprintf(os.Stderr, "Se especificó -all. Ignorando argumentos adicionales.")
}
if flags.NArg() == 0 {
panic("No se especificaron candidatos por los cuales votar")
}
address := flags.Arg(i)
if !util.IsAddress(address){
panic(fmt.Sprintf("'%v' no es una dirección válida", address))
}
isSealer := node.IsSealer(address)
switch {
case isSealer && authorize: panic(fmt.Sprintf("'%v' ya es un sellador", address))
case !isSealer && !authorize: panic(fmt.Sprintf("'%v' no es un sellador", address))
}
proposals = append(proposals, flags.Arg(i))
}
node.Propose(proposal, authorize)
fmt.Printf("Voto por %v: %v\n", proposal, authorize)
commands = map[string]func(){
"proposals": proposals,
"sealers": sealers,
"vote": propose,
for command := range commands {
validCommands = append(validCommands, command)
}
defer func() {
if err := recover(); err != nil {
}
}()
if len(os.Args) > 1 {
command = os.Args[1]
}
if commands[command] == nil {
fmt.Fprintf(os.Stderr, "Uso: %v <%v> [opciones]\n", path.Base(os.Args[0]), strings.Join(validCommands, "|"))
fmt.Fprintf(os.Stderr, "Para ayuda: %v <command> -h\n", path.Base(os.Args[0]))