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

Cambios en el manejo del número de bloque como argumento

Cambios en la forma de encontrar el sellador de un bloque
parent 1967183f
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,8 @@ package bfa ...@@ -3,6 +3,8 @@ package bfa
import ( import (
. "../clique" . "../clique"
. "../util" . "../util"
"bytes"
"encoding/hex"
"errors" "errors"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -20,8 +22,7 @@ type Node rpc.Client ...@@ -20,8 +22,7 @@ type Node rpc.Client
type BigInt big.Int type BigInt big.Int
func (bigInt *BigInt) MarshalJSON() ([]byte, error) { func (bigInt *BigInt) MarshalJSON() ([]byte, error) {
i := (*big.Int)(bigInt) return (*big.Int)(bigInt).MarshalJSON()
return []byte(i.String()), nil
} }
func (bigInt *BigInt) UnmarshalJSON(b []byte) error { func (bigInt *BigInt) UnmarshalJSON(b []byte) error {
...@@ -39,16 +40,32 @@ func (bigInt *BigInt) String() string { ...@@ -39,16 +40,32 @@ func (bigInt *BigInt) String() string {
type Uint64 uint64 type Uint64 uint64
func (u *Uint64) MarshalJSON() ([]byte, error) {
return []byte(strconv.FormatUint(*(*uint64)(u), 10)), nil
}
func (u *Uint64) UnmarshalJSON(b []byte) (err error) { func (u *Uint64) UnmarshalJSON(b []byte) (err error) {
i, err := strconv.ParseUint(string(b[1:len(b)-1]), 0, 64) i, err := strconv.ParseUint(string(b[1:len(b)-1]), 0, 64)
*u = Uint64(i) *u = Uint64(i)
return return
} }
type Bytes []byte
func (b Bytes) MarshalJSON() ([]byte, error) {
dest := make([]byte, 2+hex.EncodedLen(len(b)))
copy(dest, []byte("\"0x"))
hex.Encode(dest[2:], b)
dest[len(dest)-1] = '"'
return dest, nil
}
func (b *Bytes) UnmarshalJSON(src []byte) (err error) {
Require(len(src) >= 4 && bytes.Equal(src[1:3], []byte("0x")), "invalid json string")
dest := make([]byte, hex.DecodedLen(len(src)-4))
_, err = hex.Decode(dest, src[3:len(src)-1])
if err == nil {
*b = dest
}
return
}
// RPCTransaction represents a transaction // RPCTransaction represents a transaction
type RPCTransaction struct { type RPCTransaction struct {
BlockHash common.Hash `json:"blockHash"` BlockHash common.Hash `json:"blockHash"`
...@@ -69,24 +86,49 @@ type RPCTransaction struct { ...@@ -69,24 +86,49 @@ type RPCTransaction struct {
type Block struct { type Block struct {
ParentHash common.Hash `json:"parentHash"` ParentHash common.Hash `json:"parentHash"`
UncleHash common.Hash `json:"sha3Uncles"`
Coinbase common.Address `json:"miner"` Coinbase common.Address `json:"miner"`
Root common.Hash `json:"stateRoot"` Root common.Hash `json:"stateRoot"`
TxHash common.Hash `json:"transactionsRoot"` TxHash common.Hash `json:"transactionsRoot"`
ReceiptHash common.Hash `json:"receiptsRoot"` ReceiptHash common.Hash `json:"receiptsRoot"`
Bloom types.Bloom `json:"logsBloom"` Bloom types.Bloom `json:"logsBloom"`
Difficulty Uint64 `json:"difficulty"` Difficulty *BigInt `json:"difficulty"`
Number Uint64 `json:"number"` Number *BigInt `json:"number"`
GasLimit Uint64 `json:"gasLimit"` GasLimit Uint64 `json:"gasLimit"`
GasUsed Uint64 `json:"gasUsed"` GasUsed Uint64 `json:"gasUsed"`
Time Uint64 `json:"timestamp"` Time *BigInt `json:"timestamp"`
Extra []byte `json:"extraData"` Extra Bytes `json:"extraData"`
MixDigest common.Hash `json:"mixHash"` MixDigest common.Hash `json:"mixHash"`
Nonce Uint64 `json:"nonce"` Nonce types.BlockNonce `json:"nonce"`
Transactions []RPCTransaction `json:"transactions"` Transactions []RPCTransaction `json:"transactions"`
TotalDifficulty Uint64 `json:"totalDifficulty"` TotalDifficulty Uint64 `json:"totalDifficulty"`
Signer common.Address `json:"signer"` Signer common.Address `json:"signer"`
} }
func (block *Block) Header() (header types.Header) {
header.ParentHash = block.ParentHash
header.UncleHash = block.UncleHash
header.Coinbase = block.Coinbase
header.Root = block.Root
header.TxHash = block.TxHash
header.ReceiptHash = block.TxHash
header.Bloom = block.Bloom
header.Difficulty = (*big.Int)(block.Difficulty)
header.Number = (*big.Int)(block.Number)
header.GasLimit = uint64(block.GasLimit)
header.GasUsed = uint64(block.GasUsed)
header.Time = (*big.Int)(block.Time)
header.Extra = block.Extra
header.MixDigest = block.MixDigest
header.Nonce = block.Nonce
return
}
func (block *Block) setSigner() {
header := block.Header()
block.Signer = GetSigner(&header)
}
type Snapshot struct { type Snapshot struct {
Number uint64 `json:"number"` // Block number where the snapshot was created Number uint64 `json:"number"` // Block number where the snapshot was created
Hash common.Hash `json:"hash"` // Block hash where the snapshot was created Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
...@@ -195,31 +237,38 @@ func (node *Node) Coinbase() (coinbase string, err error) { ...@@ -195,31 +237,38 @@ func (node *Node) Coinbase() (coinbase string, err error) {
return return
} }
func (node *Node) HeaderByNumber(blockNumber int64) types.Header { func hexBlockNumber(number int64) (blockNumber string) {
var ( if number == -1 {
number string blockNumber = Latest
resp types.Header
)
if blockNumber < 0 || blockNumber > node.BlockNumber() {
number = Latest
} else { } else {
number = fmt.Sprintf("0x%x", blockNumber) blockNumber = "0x" + strconv.FormatInt(number, 16)
} }
node.Call(&resp, "eth_getBlockByNumber", number, true) return
return resp
} }
func (node *Node) BlockByNumber(blockNumber int64) (block Block) { func (node *Node) BlockNumberInRange(number int64) (blockNumber int64) {
var ( latest := node.BlockNumber()
number string switch {
) case number == -1, number > latest:
if blockNumber < 0 || blockNumber > node.BlockNumber() { blockNumber = latest
number = Latest case number < 0:
} else { blockNumber = Max(0, latest+1+number)
number = fmt.Sprintf("0x%x", blockNumber) default:
blockNumber = number
} }
node.Call(&block, "eth_getBlockByNumber", number, true) return
block.Signer = node.BlockSigner(blockNumber) }
func (node *Node) HeaderByNumber(blockNumber int64) (header types.Header) {
Require(blockNumber == -1 || blockNumber == node.BlockNumberInRange(blockNumber), "block number out of range")
node.Call(&header, "eth_getBlockByNumber", hexBlockNumber(blockNumber), true)
return
}
func (node *Node) BlockByNumber(blockNumber int64) (block Block) {
Require(blockNumber == -1 || blockNumber == node.BlockNumberInRange(blockNumber), "block number out of range")
node.Call(&block, "eth_getBlockByNumber", hexBlockNumber(blockNumber), true)
block.setSigner()
return return
} }
...@@ -243,10 +292,8 @@ func (node *Node) SnapshotAtHash(hash common.Hash) (snapshot Snapshot) { ...@@ -243,10 +292,8 @@ func (node *Node) SnapshotAtHash(hash common.Hash) (snapshot Snapshot) {
} }
func (node *Node) SnapshotAtBlock(blockNumber int64) (snapshot Snapshot) { func (node *Node) SnapshotAtBlock(blockNumber int64) (snapshot Snapshot) {
if blockNumber < 0 || blockNumber >= node.BlockNumber() { Require(blockNumber == -1 || blockNumber == node.BlockNumberInRange(blockNumber), "block number out of range")
return node.GetSnapshot() node.Call(&snapshot, "clique_getSnapshot", hexBlockNumber(blockNumber))
}
node.Call(&snapshot, "clique_getSnapshot", Int64ToHex(blockNumber))
return return
} }
......
...@@ -88,6 +88,7 @@ func proposals() { ...@@ -88,6 +88,7 @@ func proposals() {
node, err := bfa.Dial(url) node, err := bfa.Dial(url)
util.Check(err) util.Check(err)
defer node.Close() defer node.Close()
blockNumber = node.BlockNumberInRange(blockNumber)
votes := node.Votes(blockNumber) votes := node.Votes(blockNumber)
if json { if json {
util.PrintJson(votes) util.PrintJson(votes)
...@@ -163,12 +164,13 @@ func sealers() { ...@@ -163,12 +164,13 @@ func sealers() {
flags.StringVar(&format, "format", "", "Formato del timestamp. Ignorado en formato json. Opciones: 'unix', 'rfc3339', 'long' ('YYYY-MM-DD hh:mm:ss'), 'short' ('hh:mm:ss') o un formato específico. Ejemplo 'DD/MM/YY hh.mm.ss'. También se admite el formato del paquete 'time' de go.") flags.StringVar(&format, "format", "", "Formato del timestamp. Ignorado en formato json. Opciones: 'unix', 'rfc3339', 'long' ('YYYY-MM-DD hh:mm:ss'), 'short' ('hh:mm:ss') o un formato específico. Ejemplo 'DD/MM/YY hh.mm.ss'. También se admite el formato del paquete 'time' de go.")
parseFlags(false) parseFlags(false)
if blockNumber == 0 { if blockNumber == 0 {
panic("El bloque génesis no tiene firmantes") util.Error("El bloque génesis no tiene firmantes")
} }
url = updateURL(url) url = updateURL(url)
node, err := bfa.Dial(url) node, err := bfa.Dial(url)
util.Check(err) util.Check(err)
defer node.Close() defer node.Close()
blockNumber = node.BlockNumberInRange(blockNumber)
extended := lastBlock || timestamp || difficulty || balance extended := lastBlock || timestamp || difficulty || balance
if extended { if extended {
sealers := node.SealersStatus(blockNumber) sealers := node.SealersStatus(blockNumber)
...@@ -268,12 +270,12 @@ func autovote() { ...@@ -268,12 +270,12 @@ func autovote() {
flags.IntVar(&threshold, "threshold", voteThreshold, "Cantidad mínima de votos en una propuesta para habilitar el voto automático.") flags.IntVar(&threshold, "threshold", voteThreshold, "Cantidad mínima de votos en una propuesta para habilitar el voto automático.")
setFlags() setFlags()
parseFlags(false) parseFlags(false)
util.DieIf(threshold < voteThreshold, "No se puede especificar una cantidad de votos inferior a %v.", voteThreshold) util.Ensure(threshold >= voteThreshold, "No se puede especificar una cantidad de votos inferior a %v.", voteThreshold)
url = updateURL(url) url = updateURL(url)
node, err := bfa.Dial(url) node, err := bfa.Dial(url)
util.Check(err) util.Check(err)
defer node.Close() defer node.Close()
util.DieIf(!node.IsSealer(bfa.Self), "Solo los selladores pueden votar") util.Ensure(node.IsSealer(bfa.Self), "Solo los selladores pueden votar")
votes := node.Votes(latest) votes := node.Votes(latest)
genesisSigners := node.SealersAtBlock(0) genesisSigners := node.SealersAtBlock(0)
self, err := node.Coinbase() self, err := node.Coinbase()
...@@ -283,7 +285,7 @@ func autovote() { ...@@ -283,7 +285,7 @@ func autovote() {
removedSealers += 1 removedSealers += 1
} }
} }
util.DieIf(len(votes.Signers)-removedSealers < minSigners, "No se puede emitir un voto automático que reduzca la cantidad de selladores por debajo de %v.", minSigners) util.Ensure(len(votes.Signers)-removedSealers >= minSigners, "No se puede emitir un voto automático que reduzca la cantidad de selladores por debajo de %v.", minSigners)
for _, proposal := range votes.Proposals { for _, proposal := range votes.Proposals {
isSealer := util.Contains(votes.Signers, proposal) isSealer := util.Contains(votes.Signers, proposal)
switch { switch {
...@@ -326,25 +328,21 @@ func propose() { ...@@ -326,25 +328,21 @@ func propose() {
node, err := bfa.Dial(url) node, err := bfa.Dial(url)
util.Check(err) util.Check(err)
defer node.Close() defer node.Close()
util.DieIf(!node.IsSealer(bfa.Self), "Solo los selladores pueden votar") util.Ensure(node.IsSealer(bfa.Self), "Solo los selladores pueden votar")
votes := node.Votes(latest) votes := node.Votes(latest)
if flags.NArg() == 0 { util.Ensure(flags.NArg() > 0, "No se especificaron candidatos por los cuales votar")
panic("No se especificaron candidatos por los cuales votar")
}
for i := 0; i < flags.NArg(); i++ { for i := 0; i < flags.NArg(); i++ {
address := flags.Arg(i) address := flags.Arg(i)
if !util.IsAddress(address) { util.Ensure(util.IsAddress(address), "'%v' no es una dirección válida", address)
panic(fmt.Sprintf("'%v' no es una dirección válida", address))
}
if _, ok := votes.Tally[address]; ok { if _, ok := votes.Tally[address]; ok {
continue // address is in a proposal, so we allow voting either way continue // address is in a proposal, so we allow voting either way
} }
isSealer := util.Contains(votes.Signers, address) isSealer := util.Contains(votes.Signers, address)
switch { // address is not in a proposal, we allow removing signers or adding non signers switch { // address is not in a proposal, we allow removing signers or adding non signers
case isSealer && authorize: case isSealer && authorize:
panic(fmt.Sprintf("'%v' ya es un sellador", address)) util.Error("'%v' ya es un sellador", address)
case !isSealer && !authorize: case !isSealer && !authorize:
panic(fmt.Sprintf("'%v' no es un sellador", address)) util.Error("'%v' no es un sellador", address)
} }
node.Propose(address, authorize) node.Propose(address, authorize)
if json { if json {
...@@ -411,6 +409,7 @@ func block() { ...@@ -411,6 +409,7 @@ func block() {
node, err := bfa.Dial(url) node, err := bfa.Dial(url)
util.Check(err) util.Check(err)
defer node.Close() defer node.Close()
blockNumber = node.BlockNumberInRange(blockNumber)
block := node.BlockByNumber(blockNumber) block := node.BlockByNumber(blockNumber)
util.PrintJson(block) util.PrintJson(block)
} }
...@@ -425,6 +424,7 @@ func snapshot() { ...@@ -425,6 +424,7 @@ func snapshot() {
node, err := bfa.Dial(url) node, err := bfa.Dial(url)
util.Check(err) util.Check(err)
defer node.Close() defer node.Close()
blockNumber = node.BlockNumberInRange(blockNumber)
snapshot := node.SnapshotAtBlock(blockNumber) snapshot := node.SnapshotAtBlock(blockNumber)
util.PrintJson(snapshot) util.PrintJson(snapshot)
} }
......
...@@ -10,8 +10,7 @@ import ( ...@@ -10,8 +10,7 @@ import (
func sigHash(header *types.Header) (hash common.Hash) { func sigHash(header *types.Header) (hash common.Hash) {
hasher := sha3.NewKeccak256() hasher := sha3.NewKeccak256()
_ = rlp.Encode(hasher, []interface{}{
rlp.Encode(hasher, []interface{}{
header.ParentHash, header.ParentHash,
header.UncleHash, header.UncleHash,
header.Coinbase, header.Coinbase,
......
...@@ -80,7 +80,3 @@ func IsAddress(address string) bool { ...@@ -80,7 +80,3 @@ func IsAddress(address string) bool {
bytes, err := hex.DecodeString(address[2:]) bytes, err := hex.DecodeString(address[2:])
return err == nil && len(bytes) == common.AddressLength return err == nil && len(bytes) == common.AddressLength
} }
func DieIf(cond bool, format string, args ...interface{}) {
Ensure(!cond, format, args)
}
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