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

Optimizaciones de bfa_client

parent cf8b1abc
No related branches found
No related tags found
No related merge requests found
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
"log" "log"
"os" "os"
"path" "path"
"runtime"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
...@@ -63,15 +64,13 @@ func getSigner(header *types.Header) (signer string, err error) { ...@@ -63,15 +64,13 @@ func getSigner(header *types.Header) (signer string, err error) {
signature := header.Extra[len(header.Extra)-65:] signature := header.Extra[len(header.Extra)-65:]
hash := sigHash(header).Bytes() hash := sigHash(header).Bytes()
pubkey, err := crypto.Ecrecover(hash, signature) pubkey, err := crypto.Ecrecover(hash, signature)
address := make([]byte,20) address := make([]byte, 20)
copy(address, crypto.Keccak256(pubkey[1:])[12:]) copy(address, crypto.Keccak256(pubkey[1:])[12:])
signer = toHex(address) signer = toHex(address)
return return
} }
func (node *Node) getBlockSigner(blockNumber int64) (signer string) { 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) header := node.getBlockByNumber(blockNumber)
signer, err := getSigner(&header) signer, err := getSigner(&header)
check(err) check(err)
...@@ -119,7 +118,7 @@ func (node *Node) getSnapshotAtBlock(blockNumber int64) Snapshot { ...@@ -119,7 +118,7 @@ func (node *Node) getSnapshotAtBlock(blockNumber int64) Snapshot {
func (node *Node) getSigners() (signers []string) { func (node *Node) getSigners() (signers []string) {
var s []common.Address var s []common.Address
node.Call(&s, "clique_getSigners", nil) node.Call(&s, "clique_getSigners", nil)
for _, signer := range s{ for _, signer := range s {
signers = append(signers, toHex(signer.Bytes())) signers = append(signers, toHex(signer.Bytes()))
} }
return return
...@@ -128,7 +127,7 @@ func (node *Node) getSigners() (signers []string) { ...@@ -128,7 +127,7 @@ func (node *Node) getSigners() (signers []string) {
func (node *Node) getSignersAtHash(hash common.Hash) (signers []string) { func (node *Node) getSignersAtHash(hash common.Hash) (signers []string) {
var s []common.Address var s []common.Address
node.Call(&signers, "clique_getSignersAtHash", hash) node.Call(&signers, "clique_getSignersAtHash", hash)
for _, signer := range s{ for _, signer := range s {
signers = append(signers, toHex(signer.Bytes())) signers = append(signers, toHex(signer.Bytes()))
} }
return return
...@@ -203,19 +202,22 @@ func (node *Node) sealersStatus() map[string]int64 { ...@@ -203,19 +202,22 @@ func (node *Node) sealersStatus() map[string]int64 {
return status 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) { func (node *Node) getSealerInception(address string) (since int64) {
fmt.Println("in getSealerInception") if signers := node.getSigners(); !contains(signers, address) {
defer fmt.Println("out getSealerInception")
if signers := node.getSigners(); !contains(signers, address){
return -1 return -1
} }
lo := int64(0) lo := int64(0)
hi := node.blockNumber() hi := node.blockNumber()
for lo < hi { for lo < hi {
mid := lo + (hi - lo) / 2 mid := lo + (hi-lo)/2
signers := node.getSignersAtBlock(mid) signers := node.getSignersAtBlock(mid)
if contains(signers, address){ if contains(signers, address) {
hi = mid hi = mid
} else { } else {
lo = mid + 1 lo = mid + 1
...@@ -224,28 +226,208 @@ func (node *Node) getSealerInception(address string) (since int64) { ...@@ -224,28 +226,208 @@ func (node *Node) getSealerInception(address string) (since int64) {
return hi return hi
} }
func (node *Node) getSignerFirstBlock(signer string, since int64, until int64) (blockNumber int64){ func min(a, b int64) int64 {
fmt.Println("in getSignerFirstBlock") if a < b {
defer fmt.Println("out getSignerFirstBlock") return a
if since < 0{ }
return b
}
func (node *Node) getSignerFirstBlock(signer string, since int64, until int64) (blockNumber int64) {
if since < 0 {
return -1 return -1
} }
for i := since; i <= until; i++ { //snapshot := node.getSnapshotAtBlock(since)
if signer == node.getBlockSigner(i){ var count int64 = 20
return i // 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 return -1
} }
func (node *Node) getSignerLastBlock(signer string, since int64, until int64) (blockNumber int64){ func (node *Node) getSignerLastBlock_(signer string, since int64, until int64) (blockNumber int64) {
fmt.Println("in getSignerLastBlock")
defer fmt.Println("out getSignerLastBlock")
if since < 0 { if since < 0 {
return -1 return -1
} }
for i := until; i >= since; i-- { for i := until; i >= since; i-- {
if signer == node.getBlockSigner(i){ if signer == node.getBlockSigner(i) {
return i return i
} }
} }
...@@ -253,25 +435,22 @@ func (node *Node) getSignerLastBlock(signer string, since int64, until int64) (b ...@@ -253,25 +435,22 @@ func (node *Node) getSignerLastBlock(signer string, since int64, until int64) (b
} }
type SealerInfo struct { type SealerInfo struct {
Address string Address string
CurrentBlock int64 CurrentBlock int64
Since int64 Since int64
FirstBlock int64 FirstBlock int64
LastBlock int64 LastBlock int64
} }
func (node *Node) sealerInfo(sealer string) (info SealerInfo, err error) { func (node *Node) sealerInfo(sealer string) (info SealerInfo, err error) {
fmt.Println("in sealerInfo")
defer fmt.Println("out sealerInfo")
info.Address = sealer info.Address = sealer
info.CurrentBlock = node.blockNumber() info.CurrentBlock = node.blockNumber()
info.Since = node.getSealerInception(sealer) info.Since = node.getSealerInception(sealer)
if info.Since == -1 { if info.Since == -1 {
return info, fmt.Errorf("%q is not a sealer", sealer) return info, fmt.Errorf("%q is not a sealer", sealer)
} }
info.FirstBlock = node.getSignerFirstBlock(sealer, info.Since+1, info.CurrentBlock ) info.FirstBlock = node.getSignerFirstBlock(sealer, info.Since + 1, info.CurrentBlock)
info.LastBlock = node.getSignerLastBlock(sealer,info.FirstBlock, info.CurrentBlock) info.LastBlock = node.getSignerLastBlock(sealer, info.FirstBlock, info.CurrentBlock)
return return
} }
...@@ -301,9 +480,7 @@ func printVotes(node *Node, useJson bool) { ...@@ -301,9 +480,7 @@ func printVotes(node *Node, useJson bool) {
} }
} }
func printSealerInfo(node *Node, sealer string){ func printSealerInfo(node *Node, sealer string) {
fmt.Println("in printSealerInfo")
defer fmt.Println("out printSealerInfo")
info, err := node.sealerInfo(sealer) info, err := node.sealerInfo(sealer)
check(err) check(err)
v, err := json.MarshalIndent(info, "", " ") v, err := json.MarshalIndent(info, "", " ")
...@@ -382,9 +559,9 @@ func main() { ...@@ -382,9 +559,9 @@ func main() {
command = "" command = ""
commands = []string{"sealers", "proposals", "sealerInfo"} commands = []string{"sealers", "proposals", "sealerInfo"}
desc = map[string]string{ 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", "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() { defer func() {
...@@ -402,8 +579,8 @@ func main() { ...@@ -402,8 +579,8 @@ func main() {
} }
flags.BoolVar(&useJson, "json", false, "Produce salida en formato json") 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.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, "h", false, "")
flags.BoolVar(&help, "help", false, "Muestra esta ayuda") //flags.BoolVar(&help, "help", false, "Muestra esta ayuda")
flags.Parse(os.Args[2:]) flags.Parse(os.Args[2:])
if help { if help {
fmt.Fprintf(os.Stderr, "Uso: %v %v [opciones]\n%v\nOpciones: \n", path.Base(os.Args[0]), command, desc[command]) 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() { ...@@ -418,10 +595,8 @@ func main() {
case "proposals": case "proposals":
printVotes(node, useJson) printVotes(node, useJson)
case "sealerInfo": case "sealerInfo":
fmt.Println(flags.NArg(), flags.Args())
for i := 0; i < flags.NArg(); i++ { for i := 0; i < flags.NArg(); i++ {
fmt.Println(flags.Arg(i)) printSealerInfo(node, flags.Arg(i))
printSealerInfo(node,flags.Arg(i))
} }
} }
} }
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