Skip to content
Snippets Groups Projects
Commit ffc5b819 authored by Miguel Montes's avatar Miguel Montes
Browse files

Cambio de presentación de la información sobre selladores

Agregada presentación de información de balance
Agregada información sobre el nodo
parent 81453a5e
No related branches found
No related tags found
No related merge requests found
......@@ -7,7 +7,9 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc"
"math/big"
"sort"
)
......@@ -45,26 +47,61 @@ type SealerInfo struct {
}
type SealerStatus struct {
LastBlock int64 `json:"lastBlockSigned"`
Time uint64 `json:"timestamp"`
Difficulty uint64 `json:"difficulty"`
LastBlock int64 `json:"lastBlockSigned"`
Time uint64 `json:"timestamp"`
Difficulty uint64 `json:"difficulty"`
Balance *big.Int `json:"balance"`
}
const (
Latest = "latest"
Self = "self"
Latest = "latest"
Self = "self"
Network = 47525974938
Genesis = "0xe0e26f415af00fe32e1e8d94336355db43a78d9f59eb70910172b61fb670d99e"
)
func (node *Node) Call(result interface{}, method string, args ...interface{}) {
Check((*rpc.Client)(node).Call(result, method, args...))
}
func (node *Node) blockNumber() int64 {
func (node *Node) BlockNumber() int64 {
var bn rpc.BlockNumber
node.Call(&bn, "eth_blockNumber")
return bn.Int64()
}
func (node *Node) Accounts() (accounts []string) {
node.Call(&accounts, "eth_accounts")
return
}
func (node *Node) IsMining() (mining bool) {
node.Call(&mining, "eth_mining")
return
}
func (node *Node) PeerCount() (peerCount int64) {
node.Call(&peerCount, "net_peerCount")
return
}
func (node *Node) BalanceAtBlock(account string, blockNumber int64) *big.Int {
var (
balance string
block = Latest
)
if blockNumber >= 0 {
block = Int64ToHex(blockNumber)
}
node.Call(&balance, "eth_getBalance", account, block)
n, _ := new(big.Int).SetString(balance, 0)
return n
}
func (node *Node) Balance(account string) *big.Int {
return node.BalanceAtBlock(account, -1)
}
func (node *Node) Coinbase() (coinbase string, err error) {
defer func() {
if e := recover(); e != nil {
......@@ -84,7 +121,7 @@ func (node *Node) Coinbase() (coinbase string, err error) {
return
}
func (node *Node) GetBlockByNumber(blockNumber int64) types.Header {
func (node *Node) BlockByNumber(blockNumber int64) types.Header {
var (
number string
resp types.Header
......@@ -98,8 +135,8 @@ func (node *Node) GetBlockByNumber(blockNumber int64) types.Header {
return resp
}
func (node *Node) GetBlockSigner(blockNumber int64) (signer string) {
header := node.GetBlockByNumber(blockNumber)
func (node *Node) BlockSigner(blockNumber int64) (signer string) {
header := node.BlockByNumber(blockNumber)
signer, err := GetSigner(&header)
Check(err)
return
......@@ -110,12 +147,12 @@ func (node *Node) GetSnapshot() (snapshot Snapshot) {
return
}
func (node *Node) GetSnapshotAtHash(hash common.Hash) (snapshot Snapshot) {
func (node *Node) SnapshotAtHash(hash common.Hash) (snapshot Snapshot) {
node.Call(&snapshot, "clique_getSnapshotAtHash", hash)
return
}
func (node *Node) GetSnapshotAtBlock(blockNumber int64) (snapshot Snapshot) {
func (node *Node) SnapshotAtBlock(blockNumber int64) (snapshot Snapshot) {
if blockNumber < 0 {
return node.GetSnapshot()
}
......@@ -123,7 +160,7 @@ func (node *Node) GetSnapshotAtBlock(blockNumber int64) (snapshot Snapshot) {
return
}
func (node *Node) GetSigners() (signers []string) {
func (node *Node) Sealers() (signers []string) {
var s []common.Address
node.Call(&s, "clique_getSigners", nil)
for _, signer := range s {
......@@ -132,7 +169,12 @@ func (node *Node) GetSigners() (signers []string) {
return
}
func (node *Node) GetSignersAtHash(hash common.Hash) (signers []string) {
func (node *Node) NodeInfo() (nodeInfo p2p.NodeInfo) {
node.Call(&nodeInfo, "admin_nodeInfo", nil)
return
}
func (node *Node) SealersAtHash(hash common.Hash) (signers []string) {
var s []common.Address
node.Call(&signers, "clique_getSignersAtHash", hash)
for _, signer := range s {
......@@ -141,10 +183,10 @@ func (node *Node) GetSignersAtHash(hash common.Hash) (signers []string) {
return
}
func (node *Node) GetSignersAtBlock(blockNumber int64) (signers []string) {
func (node *Node) SealersAtBlock(blockNumber int64) (signers []string) {
var s []common.Address
if blockNumber < 0 {
return node.GetSigners()
return node.Sealers()
}
node.Call(&s, "clique_getSigners", Int64ToHex(blockNumber))
for _, signer := range s {
......@@ -160,7 +202,7 @@ func (node *Node) IsSealer(address string) bool {
return false
}
}
return Contains(node.GetSigners(), address)
return Contains(node.Sealers(), address)
}
func (node *Node) Propose(address string, vote bool) {
......@@ -168,14 +210,14 @@ func (node *Node) Propose(address string, vote bool) {
return
}
func (node *Node) GetVotes(blockNumber int64) (votes Proposals) {
func (node *Node) Votes(blockNumber int64) (votes Proposals) {
var (
snapshot Snapshot
)
if blockNumber < 0 {
snapshot = node.GetSnapshot()
} else {
snapshot = node.GetSnapshotAtBlock(blockNumber)
snapshot = node.SnapshotAtBlock(blockNumber)
}
votes.BlockNumber = int64(snapshot.Number)
for signer := range snapshot.Signers {
......@@ -213,11 +255,13 @@ func (node *Node) SealersStatus(blockNumber int64) (status map[string]*SealerSta
return
}
status = make(map[string]*SealerStatus)
for _, address := range node.GetSignersAtBlock(blockNumber) {
status[address] = &SealerStatus{}
for _, address := range node.SealersAtBlock(blockNumber) {
status[address] = &SealerStatus{
Balance: node.BalanceAtBlock(address, blockNumber),
}
}
notSeen := int64(len(status))
block := node.GetBlockByNumber(blockNumber)
block := node.BlockByNumber(blockNumber)
blockNumber = block.Number.Int64()
until := Max(1, blockNumber-5*notSeen)
for notSeen > 0 {
......@@ -232,21 +276,21 @@ func (node *Node) SealersStatus(blockNumber int64) (status map[string]*SealerSta
break
}
blockNumber--
block = node.GetBlockByNumber(blockNumber)
block = node.BlockByNumber(blockNumber)
}
return status
}
func (node *Node) GetSealerInception(address string) (since int64) {
if signers := node.GetSigners(); !Contains(signers, address) {
func (node *Node) SealerInception(address string) (since int64) {
if signers := node.Sealers(); !Contains(signers, address) {
return -1
}
lo := int64(0)
hi := node.blockNumber()
hi := node.BlockNumber()
for lo < hi {
mid := lo + (hi-lo)/2
signers := node.GetSignersAtBlock(mid)
signers := node.SealersAtBlock(mid)
if Contains(signers, address) {
hi = mid
} else {
......@@ -256,11 +300,11 @@ func (node *Node) GetSealerInception(address string) (since int64) {
return hi
}
func (node *Node) getSignerFirstBlock(signer string, since int64, until int64) (blockNumber int64) {
func (node *Node) signerFirstBlock(signer string, since int64, until int64) (blockNumber int64) {
if since < 0 {
return -1
}
//snapshot := node.GetSnapshotAtBlock(since)
//snapshot := node.SnapshotAtBlock(since)
var (
count int64 = 20
found int64 = -1
......@@ -320,7 +364,7 @@ func (node *Node) getSignerFirstBlock(signer string, since int64, until int64) (
}
}
func (node *Node) getSignerLastBlock(signer string, since int64, until int64) (blockNumber int64) {
func (node *Node) signerLastBlock(signer string, since int64, until int64) (blockNumber int64) {
if since < 0 {
return -1
}
......@@ -390,7 +434,7 @@ func (node *Node) searchSnapshotForward(blockNumber int64, signer string, count
return
}
for count > 0 {
snapshot := node.GetSnapshotAtBlock(blockNumber + count - 1)
snapshot := node.SnapshotAtBlock(blockNumber + count - 1)
recents := int64(len(snapshot.Recents))
visited += recents
count -= recents
......@@ -410,7 +454,7 @@ func (node *Node) searchSnapshotBackward(blockNumber int64, signer string, count
}
count = Min(count, blockNumber) // Never search below block 1
for {
snapshot := node.GetSnapshotAtBlock(blockNumber - visited)
snapshot := node.SnapshotAtBlock(blockNumber - visited)
visited += int64(len(snapshot.Recents))
if count == 0 {
count = Min(blockNumber, int64(2*len(snapshot.Signers)))
......@@ -429,13 +473,13 @@ func (node *Node) searchSnapshotBackward(blockNumber int64, signer string, count
func (node *Node) SealerInfo(sealer string) (info SealerInfo, err error) {
info.Address = sealer
info.CurrentBlock = node.blockNumber()
info.Since = node.GetSealerInception(sealer)
info.CurrentBlock = node.BlockNumber()
info.Since = node.SealerInception(sealer)
if info.Since == -1 {
return info, fmt.Errorf("%q is not a sealer", sealer)
}
info.FirstBlock = node.getSignerFirstBlock(sealer, info.Since+1, info.CurrentBlock)
info.LastBlock = node.getSignerLastBlock(sealer, info.FirstBlock, info.CurrentBlock)
info.FirstBlock = node.signerFirstBlock(sealer, info.Since+1, info.CurrentBlock)
info.LastBlock = node.signerLastBlock(sealer, info.FirstBlock, info.CurrentBlock)
return
}
......
......@@ -6,6 +6,7 @@ import (
"flag"
"fmt"
"log"
"math/big"
"os"
"path"
"sort"
......@@ -26,7 +27,7 @@ var (
url string
json bool
help bool
flags flag.FlagSet
flags = flag.NewFlagSet("", flag.ExitOnError)
command string
description string
otherArgs string
......@@ -83,7 +84,7 @@ func proposals() {
node, err := bfa.Dial(url)
util.Check(err)
defer node.Close()
votes := node.GetVotes(blockNumber)
votes := node.Votes(blockNumber)
if json {
util.PrintJson(votes)
return
......@@ -140,16 +141,21 @@ func parseFormatString(s string) (format string) {
func sealers() {
var (
blockNumber int64
status bool
lastBlock bool
timestamp bool
difficulty bool
balance bool
header bool
format string
length int64 = 10 // timestamp length
)
description = "Presenta la lista de selladores. Opcionalmente indica el último bloque sellado por cada uno."
setFlags()
flags.Int64Var(&blockNumber, "block-number", latest, "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 0 si un nodo no ha sellado en las últimas 5 rondas.")
flags.BoolVar(&timestamp, "timestamp", false, "Muestra el timestamp del sellado en lugar del número de bloque.")
flags.BoolVar(&lastBlock, "last-block", false, "Muestra el último bloque sellado por cada sellador, o 0 si un nodo no ha sellado en las últimas 5 rondas.")
flags.BoolVar(&timestamp, "timestamp", false, "Muestra el timestamp del sellado.")
flags.BoolVar(&difficulty, "difficulty", false, "Muestra la dificultad del sellado (1: fuera de turno, 2: en turno).")
flags.BoolVar(&balance, "balance", false, "Muestra el saldo del sellador (en Wei).")
flags.BoolVar(&header, "header", true, "Muestra un encabezado en cada columna.")
flags.StringVar(&format, "format", "", "Formato del timestamp. Ignorado en formato json. Opciones: 'unix', 'rfc3339', 'long' ('YYYY-MM-DD hh:mm:ss'), 'short' ('hh:mm:ss') o un formato específico. Ejemplo 'DD/MM/YY hh.mm.ss'. También se admite el formato del paquete 'time' de go.")
parseFlags()
if blockNumber == 0 {
......@@ -159,42 +165,80 @@ func sealers() {
node, err := bfa.Dial(url)
util.Check(err)
defer node.Close()
if status {
extended := lastBlock || timestamp || difficulty || balance
if extended {
sealers := node.SealersStatus(blockNumber)
if json {
util.PrintJson(sealers)
return
}
var list []string
var (
list []string
lastBlockLen int64
timestampLen int64
balanceLen int64
)
for sealer := range sealers {
list = append(list, sealer)
}
sort.Slice(list, func(i, j int) bool { return sealers[list[i]].LastBlock > sealers[list[j]].LastBlock })
if !timestamp {
length = util.Max(2, int64(len(strconv.FormatInt(sealers[list[0]].LastBlock, 10))))
} else {
switch {
case lastBlock:
sort.Slice(list, func(i, j int) bool { return sealers[list[i]].LastBlock > sealers[list[j]].LastBlock })
case timestamp:
sort.Slice(list, func(i, j int) bool { return sealers[list[i]].Time > sealers[list[j]].Time })
case difficulty:
sort.Slice(list, func(i, j int) bool { return sealers[list[i]].Difficulty > sealers[list[j]].Difficulty })
case balance:
sort.Slice(list, func(i, j int) bool { return sealers[list[i]].Balance.Cmp(sealers[list[j]].Balance) > 0 })
}
formatStr := "%42v"
if lastBlock {
formatStr += " %[2]*[3]v"
lastBlockLen = util.Max(2, int64(len(strconv.FormatInt(sealers[list[0]].LastBlock, 10))))
}
if timestamp {
formatStr += " %[4]*[5]v"
if len(format) > 0 {
format = parseFormatString(format)
length = int64(len(format))
timestampLen = int64(len(format))
} else {
timestampLen = 10
}
}
if difficulty {
formatStr += " %2[6]v"
}
if balance {
formatStr += " %[7]*[8]v"
balanceLen = 0
for _, s := range sealers {
balanceLen = util.Max(balanceLen, int64(len(s.Balance.String())))
}
}
formatStr += "\n"
if header {
fmt.Printf(formatStr,
fmt.Sprintf("%-24v", "Sealer"),
lastBlockLen, fmt.Sprintf("%*v", -lastBlockLen/2-2, "Last"),
timestampLen, fmt.Sprintf("%*v", -timestampLen/2-2, "Time"),
"Dif",
balanceLen, fmt.Sprintf("%*v", -balanceLen/2-4, "Balance"))
}
for _, sealer := range list {
var output interface{}
var formatedTimestamp interface{}
s := sealers[sealer]
if timestamp {
t := int64(sealers[sealer].Time)
t := int64(s.Time)
if len(format) > 0 && t > 0 {
output = time.Unix(t, 0).Format(format)
formatedTimestamp = time.Unix(t, 0).Format(format)
} else {
output = t
formatedTimestamp = t
}
} else {
output = sealers[sealer].LastBlock
}
fmt.Printf("%v: %*v\n", sealer, length, output)
fmt.Printf(formatStr, sealer, lastBlockLen, s.LastBlock, timestampLen, formatedTimestamp, s.Difficulty, balanceLen, s.Balance)
}
} else {
sealers := node.GetSignersAtBlock(blockNumber)
sealers := node.SealersAtBlock(blockNumber)
sort.Slice(sealers, func(i, j int) bool { return sealers[i] < sealers[j] })
if json {
util.PrintJson(sealers)
......@@ -226,8 +270,8 @@ func autovote() {
util.Check(err)
defer node.Close()
util.PanicIf(!node.IsSealer(bfa.Self), "Solo los selladores pueden votar")
votes := node.GetVotes(latest)
genesisSigners := node.GetSignersAtBlock(0)
votes := node.Votes(latest)
genesisSigners := node.SealersAtBlock(0)
self, err := node.Coinbase()
util.Check(err)
for _, tally := range votes.Tally {
......@@ -279,7 +323,7 @@ func propose() {
util.Check(err)
defer node.Close()
util.PanicIf(!node.IsSealer(bfa.Self), "Solo los selladores pueden votar")
votes := node.GetVotes(latest)
votes := node.Votes(latest)
if flags.NArg() == 0 {
panic("No se especificaron candidatos por los cuales votar")
}
......@@ -310,6 +354,45 @@ func propose() {
}
}
func status() {
nodeStatus := struct {
Enode string `json:"enode"`
Network uint64 `json:"network"`
Genesis string `json:"genesis"`
BFANetwork bool `json:"bfaNetwork"`
BFAGenesis bool `json:"bfaGenesis"`
Accounts map[string]*big.Int `json:"accounts"`
Coinbase string `json:"coinbase"`
IsSealer bool `json:"isSealer"`
IsMining bool `json:"isMining"`
BlockNumber int64 `json:"blockNumber"`
}{
Accounts: make(map[string]*big.Int),
}
description = "Muestra el estado del nodo."
setFlags()
parseFlags()
url = updateURL(url)
node, err := bfa.Dial(url)
util.Check(err)
defer node.Close()
for _, account := range node.Accounts() {
nodeStatus.Accounts[account] = node.Balance(account)
}
nodeStatus.Coinbase, _ = node.Coinbase()
nodeStatus.BlockNumber = node.BlockNumber()
nodeStatus.IsSealer = node.IsSealer(bfa.Self)
nodeStatus.IsMining = node.IsMining()
nodeInfo := node.NodeInfo()
nodeStatus.Enode = nodeInfo.Enode
ethInfo := nodeInfo.Protocols["eth"].(map[string]interface{})
nodeStatus.Genesis = ethInfo["genesis"].(string)
nodeStatus.Network = uint64(ethInfo["network"].(float64))
nodeStatus.BFAGenesis = nodeStatus.Genesis == bfa.Genesis
nodeStatus.BFANetwork = nodeStatus.Network == bfa.Network
util.PrintJson(nodeStatus)
}
func main() {
var (
commands = map[string]func(){
......@@ -317,6 +400,7 @@ func main() {
"sealers": sealers,
"vote": propose,
"autovote": autovote,
"status": status,
}
validCommands []string
)
......@@ -326,7 +410,6 @@ func main() {
defer func() {
if err := recover(); err != nil {
log.Printf("Error: %s", err)
usage(1)
}
}()
if len(os.Args) > 1 {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment