diff --git a/bfa_client/src/client/bfa_client.go b/bfa_client/src/client/bfa_client.go
index c5208547eee474f31005ec404a486b1fa68e1024..86e5d7c15a215e885abcde2946fadd1b6c687ba0 100644
--- a/bfa_client/src/client/bfa_client.go
+++ b/bfa_client/src/client/bfa_client.go
@@ -14,6 +14,7 @@ import (
 	"log"
 	"os"
 	"path"
+	"runtime"
 	"sort"
 	"strconv"
 	"strings"
@@ -63,15 +64,13 @@ func getSigner(header *types.Header) (signer string, err error) {
 	signature := header.Extra[len(header.Extra)-65:]
 	hash := sigHash(header).Bytes()
 	pubkey, err := crypto.Ecrecover(hash, signature)
-	address := make([]byte,20)
+	address := make([]byte, 20)
 	copy(address, crypto.Keccak256(pubkey[1:])[12:])
 	signer = toHex(address)
 	return
 }
 
 func (node *Node) getBlockSigner(blockNumber int64) (signer string) {
-	fmt.Printf("in getBlockSigner(%d)\n",blockNumber)
-	defer fmt.Printf("out getBlockSigner(%d)\n",blockNumber)
 	header := node.getBlockByNumber(blockNumber)
 	signer, err := getSigner(&header)
 	check(err)
@@ -119,7 +118,7 @@ func (node *Node) getSnapshotAtBlock(blockNumber int64) Snapshot {
 func (node *Node) getSigners() (signers []string) {
 	var s []common.Address
 	node.Call(&s, "clique_getSigners", nil)
-	for _, signer := range s{
+	for _, signer := range s {
 		signers = append(signers, toHex(signer.Bytes()))
 	}
 	return
@@ -128,7 +127,7 @@ func (node *Node) getSigners() (signers []string) {
 func (node *Node) getSignersAtHash(hash common.Hash) (signers []string) {
 	var s []common.Address
 	node.Call(&signers, "clique_getSignersAtHash", hash)
-	for _, signer := range s{
+	for _, signer := range s {
 		signers = append(signers, toHex(signer.Bytes()))
 	}
 	return
@@ -203,19 +202,22 @@ func (node *Node) sealersStatus() map[string]int64 {
 	return status
 }
 
+func printDebug(msg string) {
+	ptr, _, _, _ := runtime.Caller(1)
+	fmt.Printf("%v: %v\n", msg, runtime.FuncForPC(ptr).Name())
+}
+
 func (node *Node) getSealerInception(address string) (since int64) {
-	fmt.Println("in getSealerInception")
-	defer fmt.Println("out getSealerInception")
-	if signers := node.getSigners(); !contains(signers, address){
+	if signers := node.getSigners(); !contains(signers, address) {
 		return -1
 	}
 
 	lo := int64(0)
 	hi := node.blockNumber()
 	for lo < hi {
-		mid := lo + (hi - lo) / 2
+		mid := lo + (hi-lo)/2
 		signers := node.getSignersAtBlock(mid)
-		if contains(signers, address){
+		if contains(signers, address) {
 			hi = mid
 		} else {
 			lo = mid + 1
@@ -224,28 +226,208 @@ func (node *Node) getSealerInception(address string) (since int64) {
 	return hi
 }
 
-func (node *Node) getSignerFirstBlock(signer string, since int64, until int64) (blockNumber int64){
-	fmt.Println("in getSignerFirstBlock")
-	defer fmt.Println("out getSignerFirstBlock")
-	if since < 0{
+func min(a, b int64) int64 {
+	if a < b {
+		return a
+	}
+	return b
+}
+
+func (node *Node) getSignerFirstBlock(signer string, since int64, until int64) (blockNumber int64) {
+	if since < 0 {
 		return -1
 	}
-	for i := since; i <= until; i++ {
-		if signer == node.getBlockSigner(i){
-			return i
+	//snapshot := node.getSnapshotAtBlock(since)
+	var count int64 = 20
+	// first, we look close to the inception
+	if blockNumber = node.searchSnapshotForward(since, signer, count); blockNumber > 0 {
+		return
+	}
+	since += count
+	n := min(10, (until-since)/count+1) // number of goroutines
+	ch := make(chan int64)
+	for i := int64(0); i < n; i++ {
+		go func() {
+			for blockNumber := <-ch; blockNumber > 0; blockNumber = <-ch {
+				cnt := min(count, until-blockNumber+1)
+				if found := node.searchSnapshotForward(blockNumber, signer, cnt); found > 0 {
+					ch <- found
+				}
+			}
+			ch <- (-1)
+		}()
+	}
+	for {
+		select {
+		case ch <- since:
+			switch {
+			case since < 0:
+				continue
+			case since + count < until:
+				since += count
+			default:
+				since = -1 //we have exhausted the search space
+			}
+		case found := <-ch:
+			switch {
+			case found < 0:
+				n-- // a goroutine has ended
+				if n == 0 { // all goroutines have ended
+					return
+				}
+			case blockNumber < 0:
+				blockNumber = found // first time we see this signer
+				since = -1          // Notify everyone
+			case found < blockNumber:
+				blockNumber = found // found an earlier block
+			}
+		}
+	}
+}
+
+func (node *Node) getSignerFirstBlock_(signer string, since int64, until int64) (blockNumber int64) {
+	if since < 0 {
+		return -1
+	}
+	last := since
+	for i := since; ; {
+		snapshot := node.getSnapshotAtBlock(i)
+		n := int64(len(snapshot.Recents))
+		if int64(snapshot.Number)-n > last {
+			i--
+			continue
+		}
+		for b, s := range snapshot.Recents {
+			if toHex(s[:]) == signer {
+				return int64(b)
+			}
+		}
+		if i >= until {
+			return -1
+		}
+		last = i
+		i += n
+	}
+}
+
+func (node *Node) searchSnapshot(blockNumber int64, signer string, count int64, forward bool) (found int64) {
+	found = -1
+	for count > 0 {
+		snapshot := node.getSnapshotAtBlock(blockNumber + count - 1)
+		for b, s := range snapshot.Recents {
+			if toHex(s[:]) == signer {
+				found = int64(b)
+				if !forward {
+					return
+				}
+			}
 		}
+		count -= int64(len(snapshot.Recents))
+	}
+	return
+}
+
+func (node *Node) searchSnapshotForward(blockNumber int64, signer string, count int64) (found int64) {
+	found = -1
+	for count > 0 {
+		snapshot := node.getSnapshotAtBlock(blockNumber + count - 1)
+		for b, s := range snapshot.Recents {
+			if toHex(s[:]) == signer {
+				found = int64(b)
+			}
+		}
+		count -= int64(len(snapshot.Recents))
+	}
+	return
+}
+
+func (node *Node) searchSnapshotBackward(blockNumber int64, signer string, count int64) (found int64) {
+	found = -1
+	for i := int64(0); i < count;  {
+		snapshot := node.getSnapshotAtBlock(blockNumber - i)
+		for b, s := range snapshot.Recents {
+			if toHex(s[:]) == signer {
+				return int64(b)
+			}
+		}
+		i += int64(len(snapshot.Recents))
+	}
+	return
+}
+
+func (node *Node) getSignerLastBlock(signer string, since int64, until int64) (blockNumber int64) {
+	if since < 0 {
+		return -1
+	}
+	var count int64 = 20
+	// first, we look close to the last block
+	if blockNumber = node.searchSnapshotBackward(until, signer, count); blockNumber > 0 {
+		return
+	}
+	until -= count
+	n := min(10, (until-since)/count+1) // number of goroutines
+	ch := make(chan int64)
+	for i := int64(0); i < n; i++ {
+		go func() {
+			for blockNumber := <-ch; blockNumber > 0; blockNumber = <-ch {
+				cnt := min(count, blockNumber - since + 1)
+				if found := node.searchSnapshotBackward(blockNumber, signer, cnt); found > 0 {
+					ch <- found
+				}
+			}
+			ch <- (-1)
+		}()
+	}
+	for {
+		select {
+		case ch <- since:
+			switch {
+			case until < 0:
+				continue
+			case until - count > since:
+				until -= count
+			default:
+				until = -1 //we have exhausted the search space
+			}
+		case found := <-ch:
+			switch {
+			case found < 0:
+				n-- // a goroutine has ended
+				if n == 0 { // all goroutines have ended
+					return
+				}
+			case blockNumber < 0:
+				blockNumber = found // first time we see this signer
+				until = -1          // Notify everyone
+			case found > blockNumber:
+				blockNumber = found // found a later block
+			}
+		}
+	}
+}
+
+func (node *Node) getSignerLastBlock__(signer string, since int64, until int64) (blockNumber int64) {
+	if since < 0 {
+		return -1
+	}
+	for i := until; i >= since; {
+		snapshot := node.getSnapshotAtBlock(i)
+		for b, s := range snapshot.Recents {
+			if toHex(s[:]) == signer {
+				return int64(b)
+			}
+		}
+		i -= int64(len(snapshot.Recents))
 	}
 	return -1
 }
 
-func (node *Node) getSignerLastBlock(signer string, since int64, until int64) (blockNumber int64){
-	fmt.Println("in getSignerLastBlock")
-	defer fmt.Println("out getSignerLastBlock")
+func (node *Node) getSignerLastBlock_(signer string, since int64, until int64) (blockNumber int64) {
 	if since < 0 {
 		return -1
 	}
 	for i := until; i >= since; i-- {
-		if signer == node.getBlockSigner(i){
+		if signer == node.getBlockSigner(i) {
 			return i
 		}
 	}
@@ -253,25 +435,22 @@ func (node *Node) getSignerLastBlock(signer string, since int64, until int64) (b
 }
 
 type SealerInfo struct {
-	Address string
+	Address      string
 	CurrentBlock int64
-	Since    int64
-	FirstBlock int64
-	LastBlock int64
+	Since        int64
+	FirstBlock   int64
+	LastBlock    int64
 }
 
-
 func (node *Node) sealerInfo(sealer string) (info SealerInfo, err error) {
-	fmt.Println("in sealerInfo")
-	defer fmt.Println("out sealerInfo")
 	info.Address = sealer
 	info.CurrentBlock = node.blockNumber()
 	info.Since = node.getSealerInception(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.getSignerFirstBlock(sealer, info.Since + 1, info.CurrentBlock)
+	info.LastBlock = node.getSignerLastBlock(sealer, info.FirstBlock, info.CurrentBlock)
 	return
 }
 
@@ -301,9 +480,7 @@ func printVotes(node *Node, useJson bool) {
 	}
 }
 
-func printSealerInfo(node *Node, sealer string){
-	fmt.Println("in printSealerInfo")
-	defer fmt.Println("out printSealerInfo")
+func printSealerInfo(node *Node, sealer string) {
 	info, err := node.sealerInfo(sealer)
 	check(err)
 	v, err := json.MarshalIndent(info, "", "  ")
@@ -382,9 +559,9 @@ func main() {
 		command  = ""
 		commands = []string{"sealers", "proposals", "sealerInfo"}
 		desc     = map[string]string{
-			"proposals": "Detalla el estado de una votación",
+			"proposals":  "Detalla el estado de una votación",
 			"sealerInfo": "Brinda datos sobre un sealer",
-			"sealers":   "Brinda información sobre la última actividad de los selladores",
+			"sealers":    "Brinda información sobre la última actividad de los selladores",
 		}
 	)
 	defer func() {
@@ -402,8 +579,8 @@ func main() {
 	}
 	flags.BoolVar(&useJson, "json", false, "Produce salida en formato json")
 	flags.StringVar(&url, "url", DefaultURL, "URL para conexión con geth. Ejemplo: /home/bfa/bfa/network/node/geth.ipc")
-	flags.BoolVar(&help, "h", false, "")
-	flags.BoolVar(&help, "help", false, "Muestra esta ayuda")
+	//flags.BoolVar(&help, "h", false, "")
+	//flags.BoolVar(&help, "help", false, "Muestra esta ayuda")
 	flags.Parse(os.Args[2:])
 	if help {
 		fmt.Fprintf(os.Stderr, "Uso: %v %v [opciones]\n%v\nOpciones: \n", path.Base(os.Args[0]), command, desc[command])
@@ -418,10 +595,8 @@ func main() {
 	case "proposals":
 		printVotes(node, useJson)
 	case "sealerInfo":
-		fmt.Println(flags.NArg(), flags.Args())
 		for i := 0; i < flags.NArg(); i++ {
-			fmt.Println(flags.Arg(i))
-			printSealerInfo(node,flags.Arg(i))
+			printSealerInfo(node, flags.Arg(i))
 		}
 	}
 }