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 (
"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))
}
}
}
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