diff --git a/bfa_client/src/bfa/node.go b/bfa_client/src/bfa/node.go new file mode 100644 index 0000000000000000000000000000000000000000..73f9b867e41b15e7170e132b9f3d8db88af5bd38 --- /dev/null +++ b/bfa_client/src/bfa/node.go @@ -0,0 +1,447 @@ +package bfa + +import ( + . "../util" + "fmt" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/clique" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/sha3" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rpc" + "sort" + "strconv" +) + +type Node rpc.Client + +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 +} + +type Tally struct { + True int `json:"true"` + False int `json:"false"` + Null int `json:"null"` +} + +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 +} + +type SealerInfo struct { + Address string + CurrentBlock int64 + Since int64 + FirstBlock int64 + LastBlock int64 +} + +func sigHash(header *types.Header) (hash common.Hash) { + hasher := sha3.NewKeccak256() + + rlp.Encode(hasher, []interface{}{ + header.ParentHash, + header.UncleHash, + header.Coinbase, + header.Root, + header.TxHash, + header.ReceiptHash, + header.Bloom, + header.Difficulty, + header.Number, + header.GasLimit, + header.GasUsed, + header.Time, + header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short + header.MixDigest, + header.Nonce, + }) + hasher.Sum(hash[:0]) + return hash +} + + +func (node *Node) Call(result interface{}, method string, args ...interface{}) { + Check((*rpc.Client)(node).Call(result, method, args...)) +} + +func (node *Node) blockNumber() int64 { + var bn rpc.BlockNumber + node.Call(&bn, "eth_blockNumber") + return bn.Int64() +} + + + +func (node *Node) GetBlockByNumber(blockNumber int64) types.Header { + var ( + number string + resp types.Header + ) + if blockNumber < 0 { + number = "latest" + } else { + number = fmt.Sprintf("0x%x", blockNumber) + } + node.Call(&resp, "eth_getBlockByNumber", number, false) + return resp +} + +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) + copy(address, crypto.Keccak256(pubkey[1:])[12:]) + signer = ToHex(address) + return +} + +func (node *Node) GetBlockSigner(blockNumber int64) (signer string) { + header := node.GetBlockByNumber(blockNumber) + signer, err := getSigner(&header) + Check(err) + return +} + + + +func (node *Node) GetSnapshot() (snapshot Snapshot) { + node.Call(&snapshot, "clique_getSnapshot", nil) + return +} + +func (node *Node) GetSnapshotAtHash(hash common.Hash) (snapshot Snapshot) { + node.Call(&snapshot, "clique_getSnapshotAtHash", hash) + return +} + +func (node *Node) GetSnapshotAtBlock(blockNumber int64) (snapshot Snapshot) { + node.Call(&snapshot, "clique_getSnapshot", fmt.Sprintf("0x%x", blockNumber)) + return +} + +func (node *Node) GetSigners() (signers []string) { + var s []common.Address + node.Call(&s, "clique_getSigners", nil) + for _, signer := range s { + signers = append(signers, ToHex(signer.Bytes())) + } + return +} + +func (node *Node) GetSignersAtHash(hash common.Hash) (signers []string) { + var s []common.Address + node.Call(&signers, "clique_getSignersAtHash", hash) + for _, signer := range s { + signers = append(signers, ToHex(signer.Bytes())) + } + return +} + +func (node *Node) GetSignersAtBlock(blockNumber int64) (signers []string) { + var s []common.Address + node.Call(&s, "clique_getSigners", "0x"+strconv.FormatInt(blockNumber, 16)) + for _, signer := range s { + signers = append(signers, ToHex(signer.Bytes())) + } + return +} + +func (node *Node) GetVotes(blockNumber int64) (votes Proposals) { + var ( + snapshot Snapshot + ) + if blockNumber < 0 { + snapshot = node.GetSnapshot() + } else { + snapshot = node.GetSnapshotAtBlock(blockNumber) + } + votes.BlockNumber = int64(snapshot.Number) + for signer := range snapshot.Signers { + votes.Signers = append(votes.Signers, ToHex(signer[:])) + sort.Strings(votes.Signers) + } + for proposal := range snapshot.Tally { + votes.Proposals = append(votes.Proposals, ToHex(proposal[:])) + } + votes.Votes = make(map[string]map[string]*bool) + votes.Tally = make(map[string]*Tally) + for _, v := range snapshot.Votes { + proposal := ToHex(v.Address[:]) + signer := ToHex(v.Signer[:]) + if votes.Votes[proposal] == nil { + votes.Votes[proposal] = make(map[string]*bool) + for _, signer := range votes.Signers { + votes.Votes[proposal][signer] = nil + } + votes.Tally[proposal] = &Tally{0, 0, len(votes.Signers)} + } + votes.Votes[proposal][signer] = &v.Authorize + if v.Authorize { + votes.Tally[proposal].True += 1 + } else { + votes.Tally[proposal].False += 1 + } + votes.Tally[proposal].Null -= 1 + } + return +} + +func (node *Node) SealersStatus() map[string]int64 { + status := make(map[string]int64) + for _, address := range node.GetSigners() { + status[address] = -1 + } + notSeen := int64(len(status)) + block := node.GetBlockByNumber(-1) + blockNumber := block.Number.Int64() + until := blockNumber - 5*notSeen + for notSeen > 0 { + signer, _ := getSigner(&block) + if status[signer] == -1 { + status[signer] = block.Number.Int64() + notSeen-- + } + if blockNumber == until { + break + } + blockNumber-- + block = node.GetBlockByNumber(blockNumber) + } + return status +} + + +func (node *Node) GetSealerInception(address string) (since int64) { + if signers := node.GetSigners(); !Contains(signers, address) { + return -1 + } + + lo := int64(0) + hi := node.blockNumber() + for lo < hi { + mid := lo + (hi-lo)/2 + signers := node.GetSignersAtBlock(mid) + if Contains(signers, address) { + hi = mid + } else { + lo = mid + 1 + } + } + return hi +} + +func (node *Node) getSignerFirstBlock(signer string, since int64, until int64) (blockNumber int64) { + if since < 0 { + return -1 + } + //snapshot := node.GetSnapshotAtBlock(since) + var (count int64 = 20 + found int64 = -1 + ) + // first, we look close to the inception + if blockNumber, _ = node.searchSnapshotForward(since, signer, count); blockNumber > 0 { + return + } + // next, we do a coarse search + since += count + for i := since + 10000; i < until && found == -1; i += 10000 { + if found, _ = node.searchSnapshotBackward(i, signer, 0); found == -1 { // still not found + since = i + } + } + if found > 0 { + until = found + } + 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) getSignerLastBlock(signer string, since int64, until int64) (blockNumber int64) { + if since < 0 { + return -1 + } + var ( + count int64 = 20 + visited int64 = 0 + found int64 = -1 + ) + // first, we look close to the last block + if blockNumber, visited = node.searchSnapshotBackward(until, signer, 0); blockNumber > 0 { + return + } + // next, we do a coarse search + until -= visited + for i := until - 10000; i > since && found == -1; i -= 10000 { + if found, _ = node.searchSnapshotBackward(i, signer, 0); found == -1 { // still not found + until = i + } + } + if found > 0 { + since = found + } + 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 <- until: + 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) searchSnapshotForward(blockNumber int64, signer string, count int64) (found int64, visited int64) { + //printDebug("In",fmt.Sprintf("(%v, %v, %v)", blockNumber, signer, count)) + //defer printDebug("Out", "") + found = -1 + if blockNumber+count < 1 { + return + } + for count > 0 { + snapshot := node.GetSnapshotAtBlock(blockNumber + count - 1) + recents := int64(len(snapshot.Recents)) + visited += recents + count -= recents + for b, s := range snapshot.Recents { + if ToHex(s[:]) == signer { + found = int64(b) + } + } + } + return +} + +func (node *Node) searchSnapshotBackward(blockNumber int64, signer string, count int64) (found int64, visited int64) { + //printDebug("In",fmt.Sprintf("(%v, %v, %v)", blockNumber, signer, count)) + //defer printDebug("Out", "") + found = -1 + if blockNumber < 1 { // Genesis block has no signers + return + } + count = Min(count, blockNumber) // Never search below block 1 + for { + snapshot := node.GetSnapshotAtBlock(blockNumber - visited) + visited += int64(len(snapshot.Recents)) + if count == 0 { + count = Min(blockNumber, int64(2*len(snapshot.Signers))) + } + for b, s := range snapshot.Recents { + if ToHex(s[:]) == signer { + found = int64(b) + return + } + } + if visited >= count { + return + } + } +} + + + +func (node *Node) SealerInfo(sealer string) (info SealerInfo, err error) { + 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) + return +} + + + +func Dial(url string) *Node { + client, err := rpc.Dial(url) + Check(err) + return (*Node)(client) +} + +func (node *Node) Close() { + (*rpc.Client)(node).Close() +} + + diff --git a/bfa_client/src/client/bfa_client.go b/bfa_client/src/client/bfa_client.go index 86e5d7c15a215e885abcde2946fadd1b6c687ba0..a3ee59eafda9eea147f8e702a13d6e1ef535d62c 100644 --- a/bfa_client/src/client/bfa_client.go +++ b/bfa_client/src/client/bfa_client.go @@ -4,461 +4,27 @@ import ( "encoding/json" "flag" "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/clique" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/crypto/sha3" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" "log" "os" "path" - "runtime" "sort" "strconv" "strings" + "../util" + "../bfa" ) const ( DefaultURL = "http://localhost:8545" ) -type Node rpc.Client +type Node = bfa.Node -func toHex(b []byte) string { - return fmt.Sprintf("0x%02x", b) -} - -func (node *Node) blockNumber() int64 { - var bn rpc.BlockNumber - node.Call(&bn, "eth_blockNumber") - return bn.Int64() -} - -func check(err error) { - if err != nil { - panic(err.Error()) - } -} - -func (node *Node) Call(result interface{}, method string, args ...interface{}) { - check((*rpc.Client)(node).Call(result, method, args...)) -} - -func (node *Node) getBlockByNumber(blockNumber int64) types.Header { - var ( - number string - resp types.Header - ) - if blockNumber < 0 { - number = "latest" - } else { - number = fmt.Sprintf("0x%x", blockNumber) - } - node.Call(&resp, "eth_getBlockByNumber", number, false) - return resp -} - -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) - copy(address, crypto.Keccak256(pubkey[1:])[12:]) - signer = toHex(address) - return -} - -func (node *Node) getBlockSigner(blockNumber int64) (signer string) { - header := node.getBlockByNumber(blockNumber) - signer, err := getSigner(&header) - check(err) - return -} - -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 -} - -type Tally struct { - True int `json:"true"` - False int `json:"false"` - Null int `json:"null"` -} - -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 -} - -func (node *Node) getSnapshot() (snapshot Snapshot) { - node.Call(&snapshot, "clique_getSnapshot", nil) - return -} - -func (node *Node) getSnapshotAtHash(hash common.Hash) (snapshot Snapshot) { - node.Call(&snapshot, "clique_getSnapshotAtHash", hash) - return -} - -func (node *Node) getSnapshotAtBlock(blockNumber int64) Snapshot { - block := node.getBlockByNumber(blockNumber) - return node.getSnapshotAtHash(block.Hash()) -} - -func (node *Node) getSigners() (signers []string) { - var s []common.Address - node.Call(&s, "clique_getSigners", nil) - for _, signer := range s { - signers = append(signers, toHex(signer.Bytes())) - } - return -} - -func (node *Node) getSignersAtHash(hash common.Hash) (signers []string) { - var s []common.Address - node.Call(&signers, "clique_getSignersAtHash", hash) - for _, signer := range s { - signers = append(signers, toHex(signer.Bytes())) - } - return -} - -func (node *Node) getSignersAtBlock(blockNumber int64) []string { - block := node.getBlockByNumber(blockNumber) - return node.getSignersAtHash(block.Hash()) -} - -func (node *Node) getVotes(blockNumber int64) (votes Proposals) { - var ( - snapshot Snapshot - ) - if blockNumber < 0 { - snapshot = node.getSnapshot() - } else { - snapshot = node.getSnapshotAtBlock(blockNumber) - } - votes.BlockNumber = int64(snapshot.Number) - for signer := range snapshot.Signers { - votes.Signers = append(votes.Signers, toHex(signer[:])) - sort.Strings(votes.Signers) - } - for proposal := range snapshot.Tally { - votes.Proposals = append(votes.Proposals, toHex(proposal[:])) - } - votes.Votes = make(map[string]map[string]*bool) - votes.Tally = make(map[string]*Tally) - for _, v := range snapshot.Votes { - proposal := toHex(v.Address[:]) - signer := toHex(v.Signer[:]) - if votes.Votes[proposal] == nil { - votes.Votes[proposal] = make(map[string]*bool) - for _, signer := range votes.Signers { - votes.Votes[proposal][signer] = nil - } - votes.Tally[proposal] = &Tally{0, 0, len(votes.Signers)} - } - votes.Votes[proposal][signer] = &v.Authorize - if v.Authorize { - votes.Tally[proposal].True += 1 - } else { - votes.Tally[proposal].False += 1 - } - votes.Tally[proposal].Null -= 1 - } - return -} - -func (node *Node) sealersStatus() map[string]int64 { - status := make(map[string]int64) - for _, address := range node.getSigners() { - status[address] = -1 - } - notSeen := int64(len(status)) - block := node.getBlockByNumber(-1) - blockNumber := block.Number.Int64() - until := blockNumber - 5*notSeen - for notSeen > 0 { - signer, _ := getSigner(&block) - if status[signer] == -1 { - status[signer] = block.Number.Int64() - notSeen-- - } - if blockNumber == until { - break - } - blockNumber-- - block = node.getBlockByNumber(blockNumber) - } - 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) { - if signers := node.getSigners(); !contains(signers, address) { - return -1 - } - - lo := int64(0) - hi := node.blockNumber() - for lo < hi { - mid := lo + (hi-lo)/2 - signers := node.getSignersAtBlock(mid) - if contains(signers, address) { - hi = mid - } else { - lo = mid + 1 - } - } - return hi -} - -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 - } - //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) { - if since < 0 { - return -1 - } - for i := until; i >= since; i-- { - if signer == node.getBlockSigner(i) { - return i - } - } - return -1 -} - -type SealerInfo struct { - Address string - CurrentBlock int64 - Since int64 - FirstBlock int64 - LastBlock int64 -} - -func (node *Node) sealerInfo(sealer string) (info SealerInfo, err error) { - 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) - return -} - -func printVotes(node *Node, useJson bool) { - votes := node.getVotes(-1) +func printVotes(node *bfa.Node, useJson bool) { + votes := node.GetVotes(-1) if useJson { v, err := json.MarshalIndent(votes, "", " ") - check(err) + util.Check(err) fmt.Println(string(v)) return } @@ -481,18 +47,18 @@ func printVotes(node *Node, useJson bool) { } func printSealerInfo(node *Node, sealer string) { - info, err := node.sealerInfo(sealer) - check(err) + info, err := node.SealerInfo(sealer) + util.Check(err) v, err := json.MarshalIndent(info, "", " ") - check(err) + util.Check(err) fmt.Println(string(v)) } func printSealers(node *Node, useJson bool) { - sealers := node.sealersStatus() + sealers := node.SealersStatus() if useJson { v, err := json.MarshalIndent(sealers, "", " ") - check(err) + util.Check(err) fmt.Println(string(v)) return } @@ -507,48 +73,6 @@ func printSealers(node *Node, useJson bool) { } } -func sigHash(header *types.Header) (hash common.Hash) { - hasher := sha3.NewKeccak256() - - rlp.Encode(hasher, []interface{}{ - header.ParentHash, - header.UncleHash, - header.Coinbase, - header.Root, - header.TxHash, - header.ReceiptHash, - header.Bloom, - header.Difficulty, - header.Number, - header.GasLimit, - header.GasUsed, - header.Time, - header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short - header.MixDigest, - header.Nonce, - }) - hasher.Sum(hash[:0]) - return hash -} - -func Dial(url string) *Node { - client, err := rpc.Dial(url) - check(err) - return (*Node)(client) -} - -func (node *Node) Close() { - (*rpc.Client)(node).Close() -} - -func contains(slice []string, s string) bool { - for _, x := range slice { - if x == s { - return true - } - } - return false -} func main() { var ( @@ -572,7 +96,7 @@ func main() { if len(os.Args) > 1 { command = os.Args[1] } - if !contains(commands, command) { + if !util.Contains(commands, command) { fmt.Fprintf(os.Stderr, "Uso: %v <%v> [opciones]\n", path.Base(os.Args[0]), strings.Join(commands, "|")) fmt.Fprintf(os.Stderr, "For help: %v <command> -h\n", path.Base(os.Args[0])) os.Exit(1) @@ -587,7 +111,7 @@ func main() { flags.PrintDefaults() return } - node := Dial(url) + node := bfa.Dial(url) defer node.Close() switch command { case "sealers": diff --git a/bfa_client/src/util/util.go b/bfa_client/src/util/util.go new file mode 100644 index 0000000000000000000000000000000000000000..83c419759917af62c6850fb7930b6ef4ab1165c8 --- /dev/null +++ b/bfa_client/src/util/util.go @@ -0,0 +1,42 @@ +package util + +import ( + "fmt" + "runtime" +) + +func Contains(slice []string, s string) bool { + for _, x := range slice { + if x == s { + return true + } + } + return false +} + +func Check(err error) { + if err != nil { + panic(err.Error()) + } +} + +func ToHex(b []byte) string { + return fmt.Sprintf("0x%02x", b) +} + +func PrintDebug(prefix, suffix string) { + ptr, _, _, _ := runtime.Caller(1) + fmt.Printf("%v: %v%v\n", prefix, runtime.FuncForPC(ptr).Name(), suffix) +} + +func Min(a, b int64) int64 { + if a < b { + return a + } + return b +} + + + + +