Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
contrib
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
2
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
blockchain
contrib
Commits
dabd91d8
Commit
dabd91d8
authored
6 years ago
by
Miguel Montes
Browse files
Options
Downloads
Patches
Plain Diff
Commit inicial de bfa_client.go
parent
ed46b02e
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
bfa_client/bfa_client.go
+427
-0
427 additions, 0 deletions
bfa_client/bfa_client.go
with
427 additions
and
0 deletions
bfa_client/bfa_client.go
0 → 100644
+
427
−
0
View file @
dabd91d8
package
main
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"
"sort"
"strconv"
"strings"
)
const
(
DefaultURL
=
"http://localhost:8545"
)
type
Node
rpc
.
Client
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
)
{
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
)
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
(
node
*
Node
)
getSealerInception
(
address
string
)
(
since
int64
)
{
fmt
.
Println
(
"in getSealerInception"
)
defer
fmt
.
Println
(
"out getSealerInception"
)
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
){
fmt
.
Println
(
"in getSignerFirstBlock"
)
defer
fmt
.
Println
(
"out getSignerFirstBlock"
)
if
since
<
0
{
return
-
1
}
for
i
:=
since
;
i
<=
until
;
i
++
{
if
signer
==
node
.
getBlockSigner
(
i
){
return
i
}
}
return
-
1
}
func
(
node
*
Node
)
getSignerLastBlock
(
signer
string
,
since
int64
,
until
int64
)
(
blockNumber
int64
){
fmt
.
Println
(
"in getSignerLastBlock"
)
defer
fmt
.
Println
(
"out getSignerLastBlock"
)
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
)
{
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
)
return
}
func
printVotes
(
node
*
Node
,
useJson
bool
)
{
votes
:=
node
.
getVotes
(
-
1
)
if
useJson
{
v
,
err
:=
json
.
MarshalIndent
(
votes
,
""
,
" "
)
check
(
err
)
fmt
.
Println
(
string
(
v
))
return
}
fmt
.
Printf
(
"Bloque: %d
\n
Propuestas en curso: %d
\n
"
,
votes
.
BlockNumber
,
len
(
votes
.
Proposals
))
for
_
,
proposal
:=
range
votes
.
Proposals
{
fmt
.
Printf
(
"Propuesta: %v
\n
"
,
proposal
)
for
_
,
signer
:=
range
votes
.
Signers
{
b
:=
votes
.
Votes
[
proposal
][
signer
]
var
v
string
if
b
==
nil
{
v
=
""
}
else
{
v
=
strconv
.
FormatBool
(
*
b
)
}
fmt
.
Printf
(
"
\t
%v: %v
\n
"
,
signer
,
v
)
}
tally
:=
votes
.
Tally
[
proposal
]
fmt
.
Printf
(
"A favor: %v, en contra: %v, no votaron: %v
\n
"
,
tally
.
True
,
tally
.
False
,
tally
.
Null
)
}
}
func
printSealerInfo
(
node
*
Node
,
sealer
string
){
fmt
.
Println
(
"in printSealerInfo"
)
defer
fmt
.
Println
(
"out printSealerInfo"
)
info
,
err
:=
node
.
sealerInfo
(
sealer
)
check
(
err
)
v
,
err
:=
json
.
MarshalIndent
(
info
,
""
,
" "
)
check
(
err
)
fmt
.
Println
(
string
(
v
))
}
func
printSealers
(
node
*
Node
,
useJson
bool
)
{
sealers
:=
node
.
sealersStatus
()
if
useJson
{
v
,
err
:=
json
.
MarshalIndent
(
sealers
,
""
,
" "
)
check
(
err
)
fmt
.
Println
(
string
(
v
))
return
}
var
list
[]
string
for
sealer
:=
range
sealers
{
list
=
append
(
list
,
sealer
)
}
sort
.
Slice
(
list
,
func
(
i
,
j
int
)
bool
{
return
sealers
[
list
[
i
]]
>
sealers
[
list
[
j
]]
})
length
:=
len
(
strconv
.
FormatInt
(
sealers
[
list
[
0
]],
10
))
for
_
,
sealer
:=
range
list
{
fmt
.
Printf
(
"%v: %*d
\n
"
,
sealer
,
length
,
sealers
[
sealer
])
}
}
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
(
url
string
useJson
bool
help
bool
flags
flag
.
FlagSet
command
=
""
commands
=
[]
string
{
"sealers"
,
"proposals"
,
"sealerInfo"
}
desc
=
map
[
string
]
string
{
"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"
,
}
)
defer
func
()
{
if
err
:=
recover
();
err
!=
nil
{
log
.
Fatalf
(
"Error: %s"
,
err
)
}
}()
if
len
(
os
.
Args
)
>
1
{
command
=
os
.
Args
[
1
]
}
if
!
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
)
}
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
.
Parse
(
os
.
Args
[
2
:
])
if
help
{
fmt
.
Fprintf
(
os
.
Stderr
,
"Uso: %v %v [opciones]
\n
%v
\n
Opciones:
\n
"
,
path
.
Base
(
os
.
Args
[
0
]),
command
,
desc
[
command
])
flags
.
PrintDefaults
()
return
}
node
:=
Dial
(
url
)
defer
node
.
Close
()
switch
command
{
case
"sealers"
:
printSealers
(
node
,
useJson
)
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
))
}
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment