diff --git a/bfa_client/src/bfa/node.go b/bfa_client/src/bfa/node.go index 256d96db22ab8b450ea7e05082cae4b93de06d87..6e2617028fff271512bd6f0142d823a4b1025327 100644 --- a/bfa_client/src/bfa/node.go +++ b/bfa_client/src/bfa/node.go @@ -17,12 +17,12 @@ type Node rpc.Client type Address struct{ common.Address } type Snapshot struct { - Number uint64 `json:"number"` // Block number where the snapshot was created - Hash common.Hash `json:"hash"` // Block hash where the snapshot was created - Signers map[common.Address]struct{} `json:"signers"` // Set of authorized signers at this moment - Recents map[uint64]common.Address `json:"recents"` // Set of recent signers for spam protections - Votes []*clique.Vote `json:"votes"` // List of votes cast in chronological order - Tally map[common.Address]clique.Tally `json:"tally"` // Current vote tally to avoid recalculating + Number uint64 `json:"number"` // Block number where the snapshot was created + Hash common.Hash `json:"hash"` // Block hash where the snapshot was created + Signers map[Address]struct{} `json:"signers"` // Set of authorized signers at this moment + Recents map[uint64]Address `json:"recents"` // Set of recent signers for spam protections + Votes []*clique.Vote `json:"votes"` // List of votes cast in chronological order + Tally map[Address]clique.Tally `json:"tally"` // Current vote tally to avoid recalculating } type Tally struct { @@ -33,10 +33,10 @@ type Tally struct { type Proposals struct { BlockNumber int64 `json:"number"` // Block number where the snapshot was created - Proposals []string `json:"proposals"` // List of proposals being voted - Signers []string `json:"signers"` // List of authorized signers at this moment - Tally map[string]*Tally `json:"tally"` // Count of positive, negative and empty votes for a proposal - Votes map[string]map[string]*bool `json:"votes"` // List of votes for each proposal + Proposals []Address `json:"proposals"` // List of proposals being voted + Signers []Address `json:"signers"` // List of authorized signers at this moment + Tally map[Address]*Tally `json:"tally"` // Count of positive, negative and empty votes for a proposal + Votes map[Address]map[Address]*bool `json:"votes"` // List of votes for each proposal } type SealerStatus struct { @@ -58,6 +58,26 @@ func (address Address) MarshalText() ([]byte, error) { return []byte(address.Hex()), nil } +func (a Address) lessThan(b Address) bool { + for i, x := range a.Address { + if x < b.Address[i] { + return true + } + } + return false +} + +func ContainsAddress(slice []Address, address Address) bool { + for _, x := range slice { + if x == address { + return true + } + } + return false +} + + + func (node *Node) Call(result interface{}, method string, args ...interface{}) { Check((*rpc.Client)(node).Call(result, method, args...)) } @@ -220,8 +240,8 @@ func (node *Node) IsSealerAtBlock(address string, blockNumber int64) bool { return Contains(node.SealersAtBlock(blockNumber), address) } -func (node *Node) Propose(address string, vote bool) { - node.Call(nil, "clique_propose", address, vote) +func (node *Node) Propose(address Address, vote bool) { + node.Call(nil, "clique_propose", address.String(), vote) return } @@ -236,20 +256,20 @@ func (node *Node) Votes(blockNumber int64) (votes Proposals) { } votes.BlockNumber = int64(snapshot.Number) for signer := range snapshot.Signers { - votes.Signers = append(votes.Signers, BytesToHex(signer[:])) - sort.Strings(votes.Signers) + votes.Signers = append(votes.Signers, signer) + sort.Slice(votes.Signers, func(i int, j int) bool { return votes.Signers[i].lessThan(votes.Signers[j])}) } for proposal := range snapshot.Tally { - votes.Proposals = append(votes.Proposals, BytesToHex(proposal[:])) + votes.Proposals = append(votes.Proposals, proposal) } - sort.Strings(votes.Proposals) - votes.Votes = make(map[string]map[string]*bool) - votes.Tally = make(map[string]*Tally) + sort.Slice(votes.Proposals, func(i int, j int) bool { return votes.Proposals[i].lessThan(votes.Proposals[j])}) + votes.Votes = make(map[Address]map[Address]*bool) + votes.Tally = make(map[Address]*Tally) for _, v := range snapshot.Votes { - proposal := BytesToHex(v.Address[:]) - signer := BytesToHex(v.Signer[:]) + proposal := Address{v.Address} + signer := Address{v.Signer} if votes.Votes[proposal] == nil { - votes.Votes[proposal] = make(map[string]*bool) + votes.Votes[proposal] = make(map[Address]*bool) for _, signer := range votes.Signers { votes.Votes[proposal][signer] = nil } @@ -273,7 +293,8 @@ func (node *Node) LastBlockSignedBy(address string, upperLimit int64) (blockNumb for i := 0; i < 5; i++ { snapshot := node.SnapshotAtBlock(upperLimit) for number, sealer := range snapshot.Recents { - if BytesToHex(sealer[:]) == address { + a := Address{common.HexToAddress(address)} + if sealer == a { return int64(number) } } diff --git a/bfa_client/src/client/bfa_client.go b/bfa_client/src/client/bfa_client.go index 448d7882a1c09c71a466ff012295eb2c18c14cbc..e727b50f7f21a8b4f2f8ce54ce41cdb465cf7a2b 100644 --- a/bfa_client/src/client/bfa_client.go +++ b/bfa_client/src/client/bfa_client.go @@ -335,9 +335,10 @@ func autovote() { defer node.Close() util.Ensure(node.IsSealer(bfa.Self), "Solo los selladores pueden votar") votes := node.Votes(latest) - genesisSigners := node.SealersAtBlock(0) - self, err := node.Coinbase() + // genesisSigners := node.SealersAtBlock(0) + s, err := node.Coinbase() util.Check(err) + self := bfa.Address{common.HexToAddress(s)} for _, tally := range votes.Tally { if tally.False >= threshold { // We are trying to remove a sealer removedSealers += 1 @@ -345,7 +346,7 @@ func autovote() { } util.Ensure(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) + isSealer := bfa.ContainsAddress(votes.Signers, proposal) switch { case votes.Votes[proposal][self] != nil: continue // Already voted @@ -353,16 +354,17 @@ func autovote() { continue // There aren't enough votes to enable autovote case !isSealer && votes.Tally[proposal].True < threshold: continue // There aren't enough votes to enable autovote - case util.Contains(genesisSigners, proposal) && isSealer: - log.Printf("No se puede quitar en forma automática a un sellador del bloque génesis: %v.\n", proposal) - continue + // TODO: Restaurar este caso + // case bfa.ContainsAddress(genesisSigners, proposal) && isSealer: + // log.Printf("No se puede quitar en forma automática a un sellador del bloque génesis: %v.\n", proposal) + // continue case proposal == self: log.Println("No se puede votar para eliminarse uno mismo de la lista de selladores.") continue } node.Propose(proposal, !isSealer) if json { - voted[proposal] = !isSealer + voted[proposal.String()] = !isSealer } else { fmt.Printf("Voto por %v: %v\n", proposal, !isSealer) } @@ -390,10 +392,11 @@ func propose() { votes := node.Votes(latest) util.Ensure(flags.NArg() > 0, "No se especificaron candidatos por los cuales votar\n") for i := 0; i < flags.NArg(); i++ { - address := flags.Arg(i) - util.Ensure(util.IsAddress(address), "'%v' no es una dirección válida", address) + addr := flags.Arg(i) + util.Ensure(util.IsAddress(addr), "'%v' no es una dirección válida", addr) + address := bfa.Address{common.HexToAddress(addr)} if _, ok := votes.Tally[address]; !ok { - isSealer := util.Contains(votes.Signers, address) + isSealer := bfa.ContainsAddress(votes.Signers, address) switch { // address is not in a proposal, we only allow removing signers or adding non signers case isSealer && authorize: util.Error("'%v' ya es un sellador\n", address) @@ -403,7 +406,7 @@ func propose() { } node.Propose(address, authorize) if json { - voted[address] = authorize + voted[address.String()] = authorize } else { fmt.Printf("Voto por %v: %v\n", address, authorize) } diff --git a/bfa_client/src/util/util.go b/bfa_client/src/util/util.go index a8e367038daeb50c832d5c9c072d1c9e88bbf3c8..fb139eca7c2c9972f89310fe411c374bd29c2cd2 100644 --- a/bfa_client/src/util/util.go +++ b/bfa_client/src/util/util.go @@ -20,23 +20,6 @@ func Contains(slice []string, s string) bool { return false } -func ContainsAddress(slice []common.Address, address common.Address) bool { - for _, x := range slice { - if x == address { - return true - } - } - return false -} - -func LessThanAddress(a common.Address, b common.Address) bool { - for i, x := range a { - if x < b[i] { - return true - } - } - return false -} func Error(format string, args ...interface{}) { _, _ = fmt.Fprintf(os.Stderr, format, args...)