diff --git a/bfa_client/src/bfa/node.go b/bfa_client/src/bfa/node.go index 40255832406490c9f33bceb94e2263b4f91f0655..4eba41587d817c3c1c5186601bb897e22c185795 100644 --- a/bfa_client/src/bfa/node.go +++ b/bfa_client/src/bfa/node.go @@ -49,42 +49,42 @@ func (u *Uint64) UnmarshalJSON(b []byte) (err error) { return } -// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction +// RPCTransaction represents a transaction type RPCTransaction struct { - BlockHash string `json:"blockHash"` - BlockNumber Uint64 `json:"blockNumber"` - From string `json:"from"` - Gas Uint64 `json:"gas"` - GasPrice *BigInt `json:"gasPrice"` - Hash string `json:"hash"` - Input string `json:"input"` - Nonce Uint64 `json:"nonce"` - To string `json:"to"` - TransactionIndex Uint64 `json:"transactionIndex"` - Value *BigInt `json:"value"` - V *BigInt `json:"v"` - R *BigInt `json:"r"` - S *BigInt `json:"s"` + BlockHash common.Hash `json:"blockHash"` + BlockNumber Uint64 `json:"blockNumber"` + From common.Address `json:"from"` + Gas Uint64 `json:"gas"` + GasPrice *BigInt `json:"gasPrice"` + Hash common.Hash `json:"hash"` + Input string `json:"input"` + Nonce Uint64 `json:"nonce"` + To common.Address `json:"to"` + TransactionIndex Uint64 `json:"transactionIndex"` + Value *BigInt `json:"value"` + V *BigInt `json:"v"` + R *BigInt `json:"r"` + S *BigInt `json:"s"` } type Block struct { - ParentHash string `json:"parentHash"` - Coinbase string `json:"miner"` - Root string `json:"stateRoot"` - TxHash string `json:"transactionsRoot"` - ReceiptHash string `json:"receiptsRoot"` - Bloom string `json:"logsBloom"` + ParentHash common.Hash `json:"parentHash"` + Coinbase common.Address `json:"miner"` + Root common.Hash `json:"stateRoot"` + TxHash common.Hash `json:"transactionsRoot"` + ReceiptHash common.Hash `json:"receiptsRoot"` + Bloom types.Bloom `json:"logsBloom"` Difficulty Uint64 `json:"difficulty"` Number Uint64 `json:"number"` GasLimit Uint64 `json:"gasLimit"` GasUsed Uint64 `json:"gasUsed"` Time Uint64 `json:"timestamp"` - Extra string `json:"extraData"` - MixDigest string `json:"mixHash"` + Extra []byte `json:"extraData"` + MixDigest common.Hash `json:"mixHash"` Nonce Uint64 `json:"nonce"` Transactions []RPCTransaction `json:"transactions"` TotalDifficulty Uint64 `json:"totalDifficulty"` - Signer string `json:"signer"` + Signer common.Address `json:"signer"` } type Snapshot struct { @@ -200,7 +200,7 @@ func (node *Node) HeaderByNumber(blockNumber int64) types.Header { number string resp types.Header ) - if blockNumber < 0 { + if blockNumber < 0 || blockNumber > node.BlockNumber() { number = Latest } else { number = fmt.Sprintf("0x%x", blockNumber) @@ -213,7 +213,7 @@ func (node *Node) BlockByNumber(blockNumber int64) (block Block) { var ( number string ) - if blockNumber < 0 { + if blockNumber < 0 || blockNumber > node.BlockNumber() { number = Latest } else { number = fmt.Sprintf("0x%x", blockNumber) @@ -223,10 +223,12 @@ func (node *Node) BlockByNumber(blockNumber int64) (block Block) { return } -func (node *Node) BlockSigner(blockNumber int64) (signer string) { +func (node *Node) BlockSigner(blockNumber int64) (signer common.Address) { + if blockNumber == 0 { // we return an empty signer for genesis block + return + } header := node.HeaderByNumber(blockNumber) - signer, err := GetSigner(&header) - Check(err) + signer = GetSigner(&header) return } @@ -241,7 +243,7 @@ func (node *Node) SnapshotAtHash(hash common.Hash) (snapshot Snapshot) { } func (node *Node) SnapshotAtBlock(blockNumber int64) (snapshot Snapshot) { - if blockNumber < 0 { + if blockNumber < 0 || blockNumber >= node.BlockNumber() { return node.GetSnapshot() } node.Call(&snapshot, "clique_getSnapshot", Int64ToHex(blockNumber)) @@ -353,7 +355,7 @@ func (node *Node) SealersStatus(blockNumber int64) (status map[string]*SealerSta blockNumber = block.Number.Int64() until := Max(1, blockNumber-5*notSeen) for notSeen > 0 { - signer, _ := GetSigner(&block) + signer := BytesToHex(GetSigner(&block).Bytes()) if status[signer].LastBlock == 0 { status[signer].LastBlock = block.Number.Int64() status[signer].Time = block.Time.Uint64() diff --git a/bfa_client/src/client/bfa_client.go b/bfa_client/src/client/bfa_client.go index 99745668f1f809fc5f8dfc7c3b1c3b78b3745921..2749e102b3b80e21a6fc462303204ac1a2185921 100644 --- a/bfa_client/src/client/bfa_client.go +++ b/bfa_client/src/client/bfa_client.go @@ -66,12 +66,16 @@ func usage(errorCode int) { os.Exit(errorCode) } -func parseFlags() { +func parseFlags(allowAdditionalArgs bool) { err := flags.Parse(os.Args[2:]) util.Check(err) if help { usage(0) } + if flags.NArg() > 0 && !allowAdditionalArgs { + _, _ = fmt.Fprintln(os.Stderr, "Demasiados argumentos") + usage(1) + } } func proposals() { @@ -79,7 +83,7 @@ func proposals() { description = "Detalla el estado de las votaciones en curso" setFlags() flags.Int64Var(&blockNumber, "block-number", latest, "Número del bloque en el cual se quiere conocer el estado de la propuesta (-1 para el último)") - parseFlags() + parseFlags(false) url = updateURL(url) node, err := bfa.Dial(url) util.Check(err) @@ -157,7 +161,7 @@ func sealers() { 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() + parseFlags(false) if blockNumber == 0 { panic("El bloque génesis no tiene firmantes") } @@ -263,13 +267,13 @@ func autovote() { - No permite votar para eliminarse a uno mismo de la lista de selladores.`, minSigners, threshold) flags.IntVar(&threshold, "threshold", voteThreshold, "Cantidad mÃnima de votos en una propuesta para habilitar el voto automático.") setFlags() - parseFlags() - util.PanicIf(threshold < voteThreshold, "No se puede especificar una cantidad de votos inferior a %v.", voteThreshold) + parseFlags(false) + util.DieIf(threshold < voteThreshold, "No se puede especificar una cantidad de votos inferior a %v.", voteThreshold) 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") + util.DieIf(!node.IsSealer(bfa.Self), "Solo los selladores pueden votar") votes := node.Votes(latest) genesisSigners := node.SealersAtBlock(0) self, err := node.Coinbase() @@ -279,7 +283,7 @@ func autovote() { removedSealers += 1 } } - util.PanicIf(len(votes.Signers)-removedSealers < minSigners, "No se puede emitir un voto automático que reduzca la cantidad de selladores por debajo de %v.", minSigners) + util.DieIf(len(votes.Signers)-removedSealers < minSigners, "No se puede emitir un voto automático que reduzca la cantidad de selladores por debajo de %v.", minSigners) for _, proposal := range votes.Proposals { isSealer := util.Contains(votes.Signers, proposal) switch { @@ -317,12 +321,12 @@ func propose() { otherArgs = "[propuesta...]" setFlags() flags.BoolVar(&authorize, "authorize", true, "Sentido del voto (true: a favor, false: en contra).") - parseFlags() + parseFlags(true) 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") + util.DieIf(!node.IsSealer(bfa.Self), "Solo los selladores pueden votar") votes := node.Votes(latest) if flags.NArg() == 0 { panic("No se especificaron candidatos por los cuales votar") @@ -372,7 +376,7 @@ func status() { } description = "Muestra el estado del nodo." setFlags() - parseFlags() + parseFlags(false) url = updateURL(url) node, err := bfa.Dial(url) util.Check(err) @@ -402,7 +406,7 @@ func block() { 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)") - parseFlags() + parseFlags(false) url = updateURL(url) node, err := bfa.Dial(url) util.Check(err) @@ -416,7 +420,7 @@ func snapshot() { description = "Muestra el snapshot en un bloque" 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)") - parseFlags() + parseFlags(false) url = updateURL(url) node, err := bfa.Dial(url) util.Check(err) diff --git a/bfa_client/src/clique/clique.go b/bfa_client/src/clique/clique.go index 87871e496b26e5a1fbdeef389d0e7c3f7ab9b20f..79cc23a7d8103ff521e74f9fae7537e642797545 100644 --- a/bfa_client/src/clique/clique.go +++ b/bfa_client/src/clique/clique.go @@ -6,7 +6,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/rlp" - "../util" ) func sigHash(header *types.Header) (hash common.Hash) { @@ -33,12 +32,13 @@ func sigHash(header *types.Header) (hash common.Hash) { return hash } -func GetSigner(header *types.Header) (signer string, err error) { +func GetSigner(header *types.Header) (address common.Address) { signature := header.Extra[len(header.Extra)-65:] hash := sigHash(header).Bytes() pubkey, err := crypto.Ecrecover(hash, signature) - address := make([]byte, 20) - copy(address, crypto.Keccak256(pubkey[1:])[12:]) - signer = util.BytesToHex(address) + if err != nil { + panic(err) + } + copy(address[:], crypto.Keccak256(pubkey[1:])[12:]) return } diff --git a/bfa_client/src/util/util.go b/bfa_client/src/util/util.go index 0e651cca4d1653458e9e24e61e364ca9870c241f..95696a896cad3552bef8ec76f7365e1e43c1daad 100644 --- a/bfa_client/src/util/util.go +++ b/bfa_client/src/util/util.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "github.com/ethereum/go-ethereum/common" + "log" "runtime" "strconv" ) @@ -29,7 +30,7 @@ func BytesToHex(b []byte) string { } func Int64ToHex(n int64) string { - return "0x"+strconv.FormatInt(n,16) + return "0x" + strconv.FormatInt(n, 16) } func PrintDebug(prefix, suffix string) { @@ -51,24 +52,20 @@ func Max(a, b int64) int64 { return b } -func PrintJson(s interface{}){ +func PrintJson(s interface{}) { v, err := json.MarshalIndent(s, "", " ") Check(err) fmt.Println(string(v)) return } - func IsAddress(address string) bool { bytes, err := hex.DecodeString(address[2:]) return err == nil && len(bytes) == common.AddressLength } -func PanicIf(cond bool, format string, args ...interface{}){ +func DieIf(cond bool, format string, args ...interface{}) { if cond { - panic(fmt.Sprintf(format, args...)) + log.Fatalf(format, args...) } } - - -