Commit 77b9e508 authored by Hugo's avatar Hugo

fix golint problem in tendermint and #67

parent f495782e
......@@ -43,6 +43,7 @@ type envelope struct {
Data *json.RawMessage `json:"data"`
}
// EvidenceInfo struct
type EvidenceInfo struct {
Committed bool `json:"committed"`
Priority int64 `json:"priority"`
......@@ -77,8 +78,8 @@ func keyPending(evidence ttypes.Evidence) []byte {
return _key("%s/%s/%X", baseKeyPending, bE(evidence.Height()), evidence.Hash())
}
func _key(fmt_ string, o ...interface{}) []byte {
return []byte(fmt.Sprintf(fmt_, o...))
func _key(s string, o ...interface{}) []byte {
return []byte(fmt.Sprintf(s, o...))
}
// EvidenceStore is a store of all the evidence we've seen, including
......@@ -88,6 +89,7 @@ type EvidenceStore struct {
db dbm.DB
}
// NewEvidenceStore method
func NewEvidenceStore(db dbm.DB) *EvidenceStore {
if len(ttypes.EvidenceType2Type) == 0 {
ttypes.EvidenceType2Type = map[string]reflect.Type{
......@@ -160,8 +162,8 @@ func (store *EvidenceStore) GetEvidence(height int64, hash []byte) *EvidenceInfo
// It returns false if the evidence is already stored.
func (store *EvidenceStore) AddNewEvidence(evidence ttypes.Evidence, priority int64) bool {
// check if we already have seen it
ei_ := store.GetEvidence(evidence.Height(), evidence.Hash())
if ei_ != nil && len(ei_.Evidence.Kind) == 0 {
ei := store.GetEvidence(evidence.Height(), evidence.Hash())
if ei != nil && len(ei.Evidence.Kind) == 0 {
return false
}
......@@ -191,7 +193,7 @@ func (store *EvidenceStore) MarkEvidenceAsBroadcasted(evidence ttypes.Evidence)
store.db.Delete(key)
}
// MarkEvidenceAsPending removes evidence from pending and outqueue and sets the state to committed.
// MarkEvidenceAsCommitted removes evidence from pending and outqueue and sets the state to committed.
func (store *EvidenceStore) MarkEvidenceAsCommitted(evidence ttypes.Evidence) {
// if its committed, its been broadcast
store.MarkEvidenceAsBroadcasted(evidence)
......@@ -227,6 +229,7 @@ func (store *EvidenceStore) getEvidenceInfo(evidence ttypes.Evidence) EvidenceIn
return ei
}
// EvidenceToInfoBytes method
func EvidenceToInfoBytes(evidence ttypes.Evidence, priority int64) ([]byte, error) {
evi, err := json.Marshal(evidence)
if err != nil {
......@@ -250,6 +253,7 @@ func EvidenceToInfoBytes(evidence ttypes.Evidence, priority int64) ([]byte, erro
return eiBytes, nil
}
// EvidenceFromInfoBytes method
func (store *EvidenceStore) EvidenceFromInfoBytes(data []byte) (ttypes.Evidence, error) {
vote2 := EvidenceInfo{}
err := json.Unmarshal(data, &vote2)
......@@ -268,7 +272,6 @@ func (store *EvidenceStore) EvidenceFromInfoBytes(data []byte) (ttypes.Evidence,
}
//-------------------------evidence pool----------------------------
// EvidencePool maintains a pool of valid evidence
// in an EvidenceStore.
type EvidencePool struct {
......@@ -285,6 +288,7 @@ type EvidencePool struct {
evidenceChan chan ttypes.Evidence
}
// NewEvidencePool method
func NewEvidencePool(stateDB *CSStateDB, state State, evidenceStore *EvidenceStore) *EvidencePool {
evpool := &EvidencePool{
stateDB: stateDB,
......
......@@ -23,13 +23,14 @@ import (
const (
numBufferedConnections = 10
MaxNumPeers = 50
maxNumPeers = 50
tryListenSeconds = 5
HandshakeTimeout = 20 // * time.Second,
handshakeTimeout = 20 // * time.Second,
maxSendQueueSize = 1024
defaultSendTimeout = 60 * time.Second
//MaxMsgPacketPayloadSize define
MaxMsgPacketPayloadSize = 10 * 1024 * 1024
DefaultDialTimeout = 3 * time.Second
defaultDialTimeout = 3 * time.Second
dialRandomizerIntervalMilliseconds = 3000
// repeatedly try to reconnect for a few minutes
// ie. 5 * 20 = 100s
......@@ -47,6 +48,7 @@ const (
broadcastEvidenceIntervalS = 60 // broadcast uncommitted evidence this often
)
// Parallel method
func Parallel(tasks ...func()) {
var wg sync.WaitGroup
wg.Add(len(tasks))
......@@ -59,23 +61,27 @@ func Parallel(tasks ...func()) {
wg.Wait()
}
// GenAddressByPubKey method
func GenAddressByPubKey(pubkey crypto.PubKey) []byte {
//must add 3 bytes ahead to make compatibly
typeAddr := append([]byte{byte(0x01), byte(0x01), byte(0x20)}, pubkey.Bytes()...)
return crypto.Ripemd160(typeAddr)
}
// IP2IPPort struct
type IP2IPPort struct {
mutex sync.RWMutex
mapList map[string]string
}
// NewMutexMap method
func NewMutexMap() *IP2IPPort {
return &IP2IPPort{
mapList: make(map[string]string),
}
}
// Has method
func (ipp *IP2IPPort) Has(ip string) bool {
ipp.mutex.RLock()
defer ipp.mutex.RUnlock()
......@@ -83,18 +89,21 @@ func (ipp *IP2IPPort) Has(ip string) bool {
return ok
}
// Set method
func (ipp *IP2IPPort) Set(ip string, ipport string) {
ipp.mutex.Lock()
defer ipp.mutex.Unlock()
ipp.mapList[ip] = ipport
}
// Delete method
func (ipp *IP2IPPort) Delete(ip string) {
ipp.mutex.Lock()
defer ipp.mutex.Unlock()
delete(ipp.mapList, ip)
}
// NodeInfo struct
type NodeInfo struct {
ID ID `json:"id"`
Network string `json:"network"`
......@@ -102,6 +111,7 @@ type NodeInfo struct {
IP string `json:"ip,omitempty"`
}
// Node struct
type Node struct {
listener net.Listener
connections chan net.Conn
......@@ -129,6 +139,7 @@ type Node struct {
quit chan struct{}
}
// NewNode method
func NewNode(seeds []string, protocol string, lAddr string, privKey crypto.PrivKey, network string, version string, state *ConsensusState, evpool *EvidencePool) *Node {
address := GenAddressByPubKey(privKey.PubKey())
......@@ -163,6 +174,7 @@ func NewNode(seeds []string, protocol string, lAddr string, privKey crypto.PrivK
return node
}
// Start node
func (node *Node) Start() {
if atomic.CompareAndSwapUint32(&node.started, 0, 1) {
// Create listener
......@@ -211,6 +223,7 @@ func (node *Node) Start() {
}
}
// DialPeerWithAddress ...
func (node *Node) DialPeerWithAddress(addr string) error {
ip, _ := splitHostPort(addr)
node.dialing.Set(ip, addr)
......@@ -234,6 +247,7 @@ func (node *Node) addOutboundPeerWithConfig(addr string) error {
return nil
}
// Stop ...
func (node *Node) Stop() {
atomic.CompareAndSwapUint32(&node.stopped, 0, 1)
node.listener.Close()
......@@ -245,10 +259,11 @@ func (node *Node) Stop() {
peer.Stop()
node.peerSet.Remove(peer)
}
// Stop reactors
tendermintlog.Debug("Switch: Stopping reactors")
//stop consensus
node.state.Stop()
}
// IsRunning ...
func (node *Node) IsRunning() bool {
return atomic.LoadUint32(&node.started) == 1 && atomic.LoadUint32(&node.stopped) == 0
}
......@@ -277,9 +292,11 @@ func (node *Node) listenRoutine() {
}
}
// StartConsensusRoutine if peers reached the threshold start consensus routine
func (node *Node) StartConsensusRoutine() {
for {
if node.peerSet.Size() >= 0 {
//TODO:the peer count need be optimized
if node.peerSet.Size() >= 1 {
node.state.Start()
break
}
......@@ -347,6 +364,7 @@ func (node *Node) evidenceBroadcastRoutine() {
}
}
// BroadcastRoutine receive to broadcast
func (node *Node) BroadcastRoutine() {
for {
msg, ok := <-node.broadcastChannel
......@@ -359,7 +377,7 @@ func (node *Node) BroadcastRoutine() {
}
func (node *Node) connectComming(inConn net.Conn) {
maxPeers := MaxNumPeers
maxPeers := maxNumPeers
if maxPeers <= node.peerSet.Size() {
tendermintlog.Debug("Ignoring inbound connection: already have enough peers", "address", inConn.RemoteAddr().String(), "numPeers", node.peerSet.Size(), "max", maxPeers)
return
......@@ -378,6 +396,7 @@ func (node *Node) stopAndRemovePeer(peer Peer, reason interface{}) {
peer.Stop()
}
// StopPeerForError called if error occured
func (node *Node) StopPeerForError(peer Peer, reason interface{}) {
tendermintlog.Error("Stopping peer for error", "peer", peer, "err", reason)
addr, err := peer.RemoteAddr()
......@@ -422,7 +441,7 @@ func (node *Node) addPeer(pc *peerConn) error {
Version: node.Version,
}
// Exchange NodeInfo on the conn
peerNodeInfo, err := pc.HandshakeTimeout(nodeinfo, HandshakeTimeout*time.Second)
peerNodeInfo, err := pc.HandshakeTimeout(nodeinfo, handshakeTimeout*time.Second)
if err != nil {
return err
}
......@@ -489,6 +508,7 @@ func (node *Node) addPeer(pc *peerConn) error {
return nil
}
// Broadcast to peers in set
func (node *Node) Broadcast(msg MsgInfo) chan bool {
successChan := make(chan bool, len(node.peerSet.List()))
tendermintlog.Debug("Broadcast", "msgtype", msg.TypeID)
......@@ -519,13 +539,12 @@ func (node *Node) startInitPeer(peer *peerConn) error {
return nil
}
// FilterConnByAddr TODO:can make fileter by addr
func (node *Node) FilterConnByAddr(addr net.Addr) error {
//if node.filterConnByAddr != nil {
// return node.filterConnByAddr(addr)
//}
return nil
}
// CompatibleWith one node by nodeInfo
func (node *Node) CompatibleWith(other NodeInfo) error {
iMajor, iMinor, _, iErr := splitVersion(node.Version)
oMajor, oMinor, _, oErr := splitVersion(other.Version)
......@@ -679,7 +698,7 @@ func splitHostPort(addr string) (host string, port int) {
}
func dial(addr string) (net.Conn, error) {
conn, err := net.DialTimeout("tcp", addr, DefaultDialTimeout)
conn, err := net.DialTimeout("tcp", addr, defaultDialTimeout)
if err != nil {
return nil, err
}
......@@ -727,7 +746,7 @@ func newPeerConn(
conn := rawConn
// Set deadline for secret handshake
dl := time.Now().Add(HandshakeTimeout * time.Second)
dl := time.Now().Add(handshakeTimeout * time.Second)
if err := conn.SetDeadline(dl); err != nil {
return pc, fmt.Errorf("Error setting deadline while encrypting connection:%v", err)
}
......
......@@ -33,6 +33,7 @@ type msgPacket struct {
Bytes []byte
}
// MsgInfo struct
type MsgInfo struct {
TypeID byte
Msg proto.Message
......@@ -40,6 +41,7 @@ type MsgInfo struct {
PeerIP string
}
// Peer interface
type Peer interface {
ID() ID
RemoteIP() (net.IP, error) // remote IP of the connection
......@@ -57,6 +59,7 @@ type Peer interface {
//Get(string) interface{}
}
// PeerConnState struct
type PeerConnState struct {
mtx sync.Mutex
ip net.IP
......@@ -98,6 +101,7 @@ type peerConn struct {
heartbeatQueue chan proto.Message
}
// PeerSet struct
type PeerSet struct {
mtx sync.Mutex
lookup map[ID]*peerSetItem
......@@ -109,6 +113,7 @@ type peerSetItem struct {
index int
}
// NewPeerSet method
func NewPeerSet() *PeerSet {
return &PeerSet{
lookup: make(map[ID]*peerSetItem),
......@@ -164,6 +169,7 @@ func (ps *PeerSet) hasIP(peerIP net.IP) bool {
return false
}
// Size of list
func (ps *PeerSet) Size() int {
ps.mtx.Lock()
defer ps.mtx.Unlock()
......@@ -279,14 +285,11 @@ func (pc *peerConn) HandshakeTimeout(
if err1 != nil {
tendermintlog.Error("Peer handshake peerNodeInfo failed", "err", err1)
return
} else {
frame := make([]byte, 4)
binary.BigEndian.PutUint32(frame, uint32(len(info)))
_, err1 = pc.conn.Write(frame)
_, err1 = pc.conn.Write(info[:])
}
//var n int
//wire.WriteBinary(ourNodeInfo, p.conn, &n, &err1)
frame := make([]byte, 4)
binary.BigEndian.PutUint32(frame, uint32(len(info)))
_, err1 = pc.conn.Write(frame)
_, err1 = pc.conn.Write(info[:])
},
func() {
readBuffer := make([]byte, 4)
......@@ -304,9 +307,6 @@ func (pc *peerConn) HandshakeTimeout(
if err2 != nil {
return
}
//var n int
//wire.ReadBinary(peerNodeInfo, p.conn, maxNodeInfoSize, &n, &err2)
tendermintlog.Info("Peer handshake", "peerNodeInfo", peerNodeInfo)
},
)
......@@ -956,6 +956,7 @@ OUTER_LOOP:
}
}
// StackError struct
type StackError struct {
Err interface{}
Stack []byte
......@@ -969,7 +970,6 @@ func (se StackError) Error() string {
return se.String()
}
//-----------------------------------------------------------------
// GetRoundState returns an atomic snapshot of the PeerRoundState.
// There's no point in mutating it since it won't change PeerState.
func (ps *PeerConnState) GetRoundState() *ttypes.PeerRoundState {
......@@ -1034,7 +1034,7 @@ func (ps *PeerConnState) PickVoteToSend(votes ttypes.VoteSetReader) (vote *ttype
return nil, false
}
height, round, type_, size := votes.Height(), votes.Round(), votes.Type(), votes.Size()
height, round, voteType, size := votes.Height(), votes.Round(), votes.Type(), votes.Size()
// Lazily set data using 'votes'.
if votes.IsCommit() {
......@@ -1042,28 +1042,28 @@ func (ps *PeerConnState) PickVoteToSend(votes ttypes.VoteSetReader) (vote *ttype
}
ps.ensureVoteBitArrays(height, size)
psVotes := ps.getVoteBitArray(height, round, type_)
psVotes := ps.getVoteBitArray(height, round, voteType)
if psVotes == nil {
return nil, false // Not something worth sending
}
if index, ok := votes.BitArray().Sub(psVotes).PickRandom(); ok {
tendermintlog.Debug("PickVoteToSend", "height", height, "index", index, "type", type_, "selfVotes", votes.BitArray().String(),
tendermintlog.Debug("PickVoteToSend", "height", height, "index", index, "type", voteType, "selfVotes", votes.BitArray().String(),
"peerVotes", psVotes.String(), "peerip", ps.ip.String())
ps.setHasVote(height, round, type_, index)
ps.setHasVote(height, round, voteType, index)
return votes.GetByIndex(index), true
}
return nil, false
}
func (ps *PeerConnState) getVoteBitArray(height int64, round int, type_ byte) *ttypes.BitArray {
if !ttypes.IsVoteTypeValid(type_) {
func (ps *PeerConnState) getVoteBitArray(height int64, round int, voteType byte) *ttypes.BitArray {
if !ttypes.IsVoteTypeValid(voteType) {
return nil
}
if ps.Height == height {
if ps.Round == round {
switch type_ {
switch voteType {
case ttypes.VoteTypePrevote:
return ps.Prevotes
case ttypes.VoteTypePrecommit:
......@@ -1071,7 +1071,7 @@ func (ps *PeerConnState) getVoteBitArray(height int64, round int, type_ byte) *t
}
}
if ps.CatchupCommitRound == round {
switch type_ {
switch voteType {
case ttypes.VoteTypePrevote:
return nil
case ttypes.VoteTypePrecommit:
......@@ -1079,7 +1079,7 @@ func (ps *PeerConnState) getVoteBitArray(height int64, round int, type_ byte) *t
}
}
if ps.ProposalPOLRound == round {
switch type_ {
switch voteType {
case ttypes.VoteTypePrevote:
return ps.ProposalPOL
case ttypes.VoteTypePrecommit:
......@@ -1090,7 +1090,7 @@ func (ps *PeerConnState) getVoteBitArray(height int64, round int, type_ byte) *t
}
if ps.Height == height+1 {
if ps.LastCommitRound == round {
switch type_ {
switch voteType {
case ttypes.VoteTypePrevote:
return nil
case ttypes.VoteTypePrecommit:
......@@ -1127,7 +1127,7 @@ func (ps *PeerConnState) ensureCatchupCommitRound(height int64, round int, numVa
}
}
// EnsureVoteVitArrays ensures the bit-arrays have been allocated for tracking
// EnsureVoteBitArrays ensures the bit-arrays have been allocated for tracking
// what votes this peer has received.
// NOTE: It's important to make sure that numValidators actually matches
// what the node sees as the number of validators for height.
......@@ -1166,14 +1166,14 @@ func (ps *PeerConnState) SetHasVote(vote *ttypes.Vote) {
ps.setHasVote(vote.Height, int(vote.Round), byte(vote.Type), int(vote.ValidatorIndex))
}
func (ps *PeerConnState) setHasVote(height int64, round int, type_ byte, index int) {
func (ps *PeerConnState) setHasVote(height int64, round int, voteType byte, index int) {
// NOTE: some may be nil BitArrays -> no side effects.
psVotes := ps.getVoteBitArray(height, round, type_)
psVotes := ps.getVoteBitArray(height, round, voteType)
tendermintlog.Debug("setHasVote before", "height", height, "psVotes", psVotes.String(), "peerip", ps.ip.String())
if psVotes != nil {
psVotes.SetIndex(index, true)
}
tendermintlog.Debug("setHasVote after", "height", height, "index", index, "type", type_, "peerVotes", psVotes.String(), "peerip", ps.ip.String())
tendermintlog.Debug("setHasVote after", "height", height, "index", index, "type", voteType, "peerVotes", psVotes.String(), "peerip", ps.ip.String())
}
// ApplyNewRoundStepMessage updates the peer state for the new round.
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Uses nacl's secret_box to encrypt a net.Conn.
// Package tendermint Uses nacl's secret_box to encrypt a net.Conn.
// It is (meant to be) an implementation of the STS protocol.
// Note we do not (yet) assume that a remote peer's pubkey
// is known ahead of time, and thus we are technically
......@@ -36,7 +36,7 @@ const (
authSigMsgSize = (32) + (64)
) // fixed size (length prefixed) byte arrays
// Implements net.Conn
// SecretConnection Implements net.Conn
type SecretConnection struct {
conn io.ReadWriteCloser
recvBuffer []byte
......@@ -46,7 +46,7 @@ type SecretConnection struct {
shrSecret *[32]byte // shared secret
}
// Performs handshake and returns a new authenticated SecretConnection.
// MakeSecretConnection Performs handshake and returns a new authenticated SecretConnection.
// Returns nil if error in handshake.
// Caller should call conn.Close()
// See docs/sts-final.pdf for more information.
......@@ -108,7 +108,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
return sc, nil
}
// Returns authenticated remote pubkey
// RemotePubKey Returns authenticated remote pubkey
func (sc *SecretConnection) RemotePubKey() crypto.PubKey {
return sc.remPubKey
}
......@@ -140,9 +140,8 @@ func (sc *SecretConnection) Write(data []byte) (n int, err error) {
_, err := sc.conn.Write(sealedFrame)
if err != nil {
return n, err
} else {
n += len(chunk)
}
n += len(chunk)
}
return
}
......@@ -150,8 +149,8 @@ func (sc *SecretConnection) Write(data []byte) (n int, err error) {
// CONTRACT: data smaller than dataMaxSize is read atomically.
func (sc *SecretConnection) Read(data []byte) (n int, err error) {
if 0 < len(sc.recvBuffer) {
n_ := copy(data, sc.recvBuffer)
sc.recvBuffer = sc.recvBuffer[n_:]
count := copy(data, sc.recvBuffer)
sc.recvBuffer = sc.recvBuffer[count:]
return
}
......@@ -182,14 +181,24 @@ func (sc *SecretConnection) Read(data []byte) (n int, err error) {
return
}
// Implements net.Conn
// Close Implements net.Conn
func (sc *SecretConnection) Close() error { return sc.conn.Close() }
// LocalAddr ...
func (sc *SecretConnection) LocalAddr() net.Addr { return sc.conn.(net.Conn).LocalAddr() }
// RemoteAddr ...
func (sc *SecretConnection) RemoteAddr() net.Addr { return sc.conn.(net.Conn).RemoteAddr() }
// SetDeadline ...
func (sc *SecretConnection) SetDeadline(t time.Time) error { return sc.conn.(net.Conn).SetDeadline(t) }
// SetReadDeadline ...
func (sc *SecretConnection) SetReadDeadline(t time.Time) error {
return sc.conn.(net.Conn).SetReadDeadline(t)
}
// SetWriteDeadline ...
func (sc *SecretConnection) SetWriteDeadline(t time.Time) error {
return sc.conn.(net.Conn).SetWriteDeadline(t)
}
......@@ -343,7 +352,7 @@ func incr2Nonce(nonce *[24]byte) {
// increment nonce big-endian by 1 with wraparound.
func incrNonce(nonce *[24]byte) {
for i := 23; 0 <= i; i-- {
nonce[i] += 1
nonce[i] ++
if nonce[i] != 0 {
return
}
......
......@@ -204,14 +204,15 @@ func MakeGenesisState(genDoc *ttypes.GenesisDoc) (State, error) {
}, nil
}
//-------------------stateDB------------------------
// CSStateDB just for EvidencePool and BlockExecutor
type CSStateDB struct {
client *TendermintClient
client *Client
state State
mtx sync.Mutex
}
func NewStateDB(client *TendermintClient, state State) *CSStateDB {
// NewStateDB make a new one
func NewStateDB(client *Client, state State) *CSStateDB {
r = rand.New(rand.NewSource(time.Now().UnixNano()))
return &CSStateDB{
client: client,
......@@ -219,6 +220,7 @@ func NewStateDB(client *TendermintClient, state State) *CSStateDB {
}
}
// LoadState convert external state to internal state
func LoadState(state *tmtypes.State) State {
stateTmp := State{
ChainID: state.GetChainID(),
......@@ -286,18 +288,21 @@ func LoadState(state *tmtypes.State) State {
return stateTmp
}
// SaveState to state cache
func (csdb *CSStateDB) SaveState(state State) {
csdb.mtx.Lock()
defer csdb.mtx.Unlock()
csdb.state = state.Copy()
}
// LoadState from state cache
func (csdb *CSStateDB) LoadState() State {
csdb.mtx.Lock()
defer csdb.mtx.Unlock()
return csdb.state
}
// LoadValidators by height
func (csdb *CSStateDB) LoadValidators(height int64) (*ttypes.ValidatorSet, error) {
if height == 0 {
return nil, nil
......@@ -363,6 +368,7 @@ func saveProposer(dest *tmtypes.Validator, source *ttypes.Validator) {
}
}
// SaveState convert internal state to external state
func SaveState(state State) *tmtypes.State {
newState := tmtypes.State{
ChainID: state.ChainID,
......@@ -405,6 +411,7 @@ func getprivkey(key string) crypto.PrivKey {
return priv
}
// LoadValidators convert all external validators to internal validators
func LoadValidators(des []*ttypes.Validator, source []*tmtypes.Validator) {
for i, item := range source {
if item.GetAddress() == nil || len(item.GetAddress()) == 0 {
......@@ -427,6 +434,7 @@ func LoadValidators(des []*ttypes.Validator, source []*tmtypes.Validator) {
}
}
// LoadProposer convert external proposer to internal proposer
func LoadProposer(source *tmtypes.Validator) (*ttypes.Validator, error) {
if source.GetAddress() == nil || len(source.GetAddress()) == 0 {
tendermintlog.Warn("LoadProposer get address is nil or empty")
......@@ -449,6 +457,7 @@ func LoadProposer(source *tmtypes.Validator) (*ttypes.Validator, error) {
return des, nil
}
// CreateBlockInfoTx make blockInfo to the first transaction of the block and execer is valnode
func CreateBlockInfoTx(pubkey string, lastCommit *tmtypes.TendermintCommit, seenCommit *tmtypes.TendermintCommit, state *tmtypes.State, proposal *tmtypes.Proposal, block *tmtypes.TendermintBlock) *types.Transaction {
blockNoTxs := *block
blockNoTxs.Txs = make([]*types.Transaction, 0)
......
......@@ -22,7 +22,7 @@ import (
"github.com/golang/protobuf/proto"
)
const tendermint_version = "0.1.0"
const tendermintVersion = "0.1.0"
var (
tendermintlog = log15.New("module", "tendermint")
......@@ -36,9 +36,9 @@ var (
timeoutPrecommit int32 = 1000
timeoutPrecommitDelta int32 = 500
timeoutCommit int32 = 1000
skipTimeoutCommit bool = false
createEmptyBlocks bool = false
createEmptyBlocksInterval int32 = 0 // second
skipTimeoutCommit = false
createEmptyBlocks = false
createEmptyBlocksInterval int32 // second
validatorNodes = []string{"127.0.0.1:46656"}
peerGossipSleepDuration int32 = 100
peerQueryMaj23SleepDuration int32 = 2000
......@@ -47,10 +47,11 @@ var (
func init() {
drivers.Reg("tendermint", New)
drivers.QueryData.Register("tendermint", &TendermintClient{})
drivers.QueryData.Register("tendermint", &Client{})
}
type TendermintClient struct {
// Client Tendermint implementation
type Client struct {
//config
*drivers.BaseClient
genesisDoc *ttypes.GenesisDoc // initial validator set
......@@ -82,7 +83,7 @@ type subConfig struct {
ValidatorNodes []string `json:"validatorNodes"`
}
func (client *TendermintClient) applyConfig(sub []byte) {
func (client *Client) applyConfig(sub []byte) {
var subcfg subConfig
if sub != nil {
types.MustDecode(sub, &subcfg)
......@@ -133,6 +134,7 @@ func DefaultDBProvider(ID string) (dbm.DB, error) {
return dbm.NewDB(ID, "leveldb", "./datadir", 0), nil
}
// New ...
func New(cfg *types.Consensus, sub []byte) queue.Module {
tendermintlog.Info("Start to create tendermint client")
//init rand
......@@ -175,7 +177,7 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
pubkey := privValidator.GetPubKey().KeyString()
c := drivers.NewBaseClient(cfg)
client := &TendermintClient{
client := &Client{
BaseClient: c,
genesisDoc: genDoc,
privValidator: privValidator,
......@@ -194,21 +196,24 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
// PrivValidator returns the Node's PrivValidator.
// XXX: for convenience only!
func (client *TendermintClient) PrivValidator() ttypes.PrivValidator {
func (client *Client) PrivValidator() ttypes.PrivValidator {
return client.privValidator
}
// GenesisDoc returns the Node's GenesisDoc.
func (client *TendermintClient) GenesisDoc() *ttypes.GenesisDoc {
func (client *Client) GenesisDoc() *ttypes.GenesisDoc {
return client.genesisDoc
}
func (client *TendermintClient) Close() {
// Close TODO:may need optimize
func (client *Client) Close() {
client.node.Stop()
client.stopC <- struct{}{}
tendermintlog.Info("consensus tendermint closed")
}
func (client *TendermintClient) SetQueueClient(q queue.Client) {
// SetQueueClient ...
func (client *Client) SetQueueClient(q queue.Client) {
client.InitClient(q, func() {
//call init block
client.InitBlock()
......@@ -218,14 +223,16 @@ func (client *TendermintClient) SetQueueClient(q queue.Client) {
go client.StartConsensus()
}
const DEBUG_CATCHUP = false
// DebugCatchup define whether catch up now
const DebugCatchup = false
func (client *TendermintClient) StartConsensus() {
// StartConsensus a routine that make the consensus start
func (client *Client) StartConsensus() {
//进入共识前先同步到最大高度
hint := time.NewTicker(5 * time.Second)
beg := time.Now()
OuterLoop:
for !DEBUG_CATCHUP {
for !DebugCatchup {
select {
case <-hint.C:
tendermintlog.Info("Still catching up max height......", "Height", client.GetCurrentHeight(), "cost", time.Since(beg))
......@@ -320,7 +327,7 @@ OuterLoop:
// Create & add listener
protocol, listeningAddress := "tcp", "0.0.0.0:46656"
node := NewNode(validatorNodes, protocol, listeningAddress, client.privKey, state.ChainID, tendermint_version, csState, evidencePool)
node := NewNode(validatorNodes, protocol, listeningAddress, client.privKey, state.ChainID, tendermintVersion, csState, evidencePool)
client.node = node
node.Start()
......@@ -328,11 +335,13 @@ OuterLoop:
go client.CreateBlock()
}
func (client *TendermintClient) GetGenesisBlockTime() int64 {
// GetGenesisBlockTime ...
func (client *Client) GetGenesisBlockTime() int64 {
return genesisBlockTime
}
func (client *TendermintClient) CreateGenesisTx() (ret []*types.Transaction) {
// CreateGenesisTx ...
func (client *Client) CreateGenesisTx() (ret []*types.Transaction) {
var tx types.Transaction
tx.Execer = []byte("coins")
tx.To = genesis
......@@ -345,16 +354,18 @@ func (client *TendermintClient) CreateGenesisTx() (ret []*types.Transaction) {
return
}
//暂不检查任何的交易
func (client *TendermintClient) CheckBlock(parent *types.Block, current *types.BlockDetail) error {
// CheckBlock 暂不检查任何的交易
func (client *Client) CheckBlock(parent *types.Block, current *types.BlockDetail) error {
return nil
}
func (client *TendermintClient) ProcEvent(msg queue.Message) bool {
// ProcEvent ...
func (client *Client) ProcEvent(msg queue.Message) bool {
return false
}
func (client *TendermintClient) CreateBlock() {
// CreateBlock a routine monitor whether some transactions available and tell client by available channel
func (client *Client) CreateBlock() {
issleep := true
for {
......@@ -378,21 +389,25 @@ func (client *TendermintClient) CreateBlock() {
}
}
func (client *TendermintClient) TxsAvailable() <-chan int64 {
// TxsAvailable check available channel
func (client *Client) TxsAvailable() <-chan int64 {
return client.txsAvailable
}
func (client *TendermintClient) StopC() <-chan struct{} {
// StopC stop client
func (client *Client) StopC() <-chan struct{} {
return client.stopC
}
func (client *TendermintClient) CheckTxsAvailable() bool {
// CheckTxsAvailable check whether some new transactions arriving
func (client *Client) CheckTxsAvailable() bool {
txs := client.RequestTx(10, nil)
txs = client.CheckTxDup(txs, client.GetCurrentHeight())
return len(txs) != 0
}
func (client *TendermintClient) CheckTxDup(txs []*types.Transaction, height int64) (transactions []*types.Transaction) {
// CheckTxDup check transactions that duplicate
func (client *Client) CheckTxDup(txs []*types.Transaction, height int64) (transactions []*types.Transaction) {
cacheTxs := types.TxsToCache(txs)
var err error
cacheTxs, err = util.CheckTxDup(client.GetQueueClient(), cacheTxs, height)
......@@ -402,7 +417,8 @@ func (client *TendermintClient) CheckTxDup(txs []*types.Transaction, height int6
return types.CacheToTxs(cacheTxs)
}
func (client *TendermintClient) BuildBlock() *types.Block {
// BuildBlock build a new block contains some transactions
func (client *Client) BuildBlock() *types.Block {
lastHeight := client.GetCurrentHeight()
txs := client.RequestTx(int(types.GetP(lastHeight+1).MaxTxNumber)-1, nil)
newblock := &types.Block{}
......@@ -411,7 +427,8 @@ func (client *TendermintClient) BuildBlock() *types.Block {
return newblock
}
func (client *TendermintClient) CommitBlock(propBlock *types.Block) error {
// CommitBlock call WriteBlock to real commit to chain
func (client *Client) CommitBlock(propBlock *types.Block) error {
newblock := *propBlock
lastBlock, err := client.RequestBlock(newblock.Height - 1)
if err != nil {
......@@ -438,7 +455,8 @@ func (client *TendermintClient) CommitBlock(propBlock *types.Block) error {
return nil
}
func (client *TendermintClient) CheckCommit(height int64) bool {
// CheckCommit by height
func (client *Client) CheckCommit(height int64) bool {
retry := 0
newHeight := int64(1)
for {
......@@ -456,7 +474,8 @@ func (client *TendermintClient) CheckCommit(height int64) bool {
}
}
func (client *TendermintClient) QueryValidatorsByHeight(height int64) (*tmtypes.ValNodes, error) {
// QueryValidatorsByHeight ...
func (client *Client) QueryValidatorsByHeight(height int64) (*tmtypes.ValNodes, error) {
if height <= 0 {
return nil, types.ErrInvalidParam
}
......@@ -475,7 +494,8 @@ func (client *TendermintClient) QueryValidatorsByHeight(height int64) (*tmtypes.
return msg.GetData().(types.Message).(*tmtypes.ValNodes), nil
}
func (client *TendermintClient) QueryBlockInfoByHeight(height int64) (*tmtypes.TendermintBlockInfo, error) {
// QueryBlockInfoByHeight ...
func (client *Client) QueryBlockInfoByHeight(height int64) (*tmtypes.TendermintBlockInfo, error) {
if height <= 0 {
return nil, types.ErrInvalidParam
}
......@@ -494,7 +514,8 @@ func (client *TendermintClient) QueryBlockInfoByHeight(height int64) (*tmtypes.T
return msg.GetData().(types.Message).(*tmtypes.TendermintBlockInfo), nil
}
func (client *TendermintClient) LoadSeenCommit(height int64) *tmtypes.TendermintCommit {
// LoadSeenCommit by height
func (client *Client) LoadSeenCommit(height int64) *tmtypes.TendermintCommit {
blockInfo, err := client.QueryBlockInfoByHeight(height)
if err != nil {
panic(fmt.Sprintf("LoadSeenCommit GetBlockInfo failed:%v", err))
......@@ -506,7 +527,8 @@ func (client *TendermintClient) LoadSeenCommit(height int64) *tmtypes.Tendermint
return blockInfo.GetSeenCommit()
}
func (client *TendermintClient) LoadBlockCommit(height int64) *tmtypes.TendermintCommit {
// LoadBlockCommit by height
func (client *Client) LoadBlockCommit(height int64) *tmtypes.TendermintCommit {
blockInfo, err := client.QueryBlockInfoByHeight(height)
if err != nil {
panic(fmt.Sprintf("LoadBlockCommit GetBlockInfo failed:%v", err))
......@@ -518,7 +540,8 @@ func (client *TendermintClient) LoadBlockCommit(height int64) *tmtypes.Tendermin
return blockInfo.GetLastCommit()
}
func (client *TendermintClient) LoadProposalBlock(height int64) *tmtypes.TendermintBlock {
// LoadProposalBlock by height
func (client *Client) LoadProposalBlock(height int64) *tmtypes.TendermintBlock {
block, err := client.RequestBlock(height)
if err != nil {
tendermintlog.Error("LoadProposal by height failed", "curHeight", client.GetCurrentHeight(), "requestHeight", height, "error", err)
......
......@@ -36,7 +36,7 @@ import (
var (
random *rand.Rand
loopCount int = 10
loopCount = 10
conn *grpc.ClientConn
c types.Chain33Client
)
......
......@@ -29,7 +29,8 @@ const fee = 1e6
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
var r *rand.Rand
var TxHeightOffset int64 = 0
// TxHeightOffset needed
var TxHeightOffset int64
func main() {
if len(os.Args) == 1 || os.Args[1] == "-h" {
......@@ -69,6 +70,7 @@ func main() {
}
}
// LoadHelp ...
func LoadHelp() {
fmt.Println("Available Commands:")
fmt.Println("perf [ip, size, num, interval, duration] {offset} : 写数据性能测试")
......@@ -77,6 +79,7 @@ func LoadHelp() {
fmt.Println("valnode [ip, pubkey, power] : 增加/删除/修改tendermint节点")
}
// Perf ...
func Perf(ip, size, num, interval, duration string) {
var numThread int
numInt, err := strconv.Atoi(num)
......@@ -128,6 +131,7 @@ func Perf(ip, size, num, interval, duration string) {
}
}
// Put ...
func Put(ip string, size string, privkey string) {
sizeInt, err := strconv.Atoi(size)
if err != nil {
......@@ -164,6 +168,7 @@ func Put(ip string, size string, privkey string) {
fmt.Printf("returned JSON: %s\n", string(b))
}
// Get ...
func Get(ip string, hash string) {
url := "http://" + ip + ":8801"
fmt.Println("transaction hash:", hash)
......@@ -209,8 +214,9 @@ func setTxHeight(ip string) {
fmt.Println("TxHeightOffset:", TxHeightOffset)
}
// RespMsg ...
type RespMsg struct {
Id int64 `json:"id"`
ID int64 `json:"id"`
Result rpctypes.Header `json:"result"`
Err string `json:"error"`
}
......@@ -245,6 +251,7 @@ func genaddress() (string, crypto.PrivKey) {
return addrto.String(), privto
}
// RandStringBytes ...
func RandStringBytes(n int) string {
b := make([]byte, n)
rand.Seed(time.Now().UnixNano())
......@@ -254,6 +261,7 @@ func RandStringBytes(n int) string {
return string(b)
}
// ValNode ...
func ValNode(ip, pubkey, power string) {
url := "http://" + ip + ":8801"
......
......@@ -22,11 +22,11 @@ import (
var (
blocklog = log15.New("module", "tendermint-block")
// ConsensusCrypto define
ConsensusCrypto crypto.Crypto
)
//-----------------------------------------------------------------------------
//BlockID
// BlockID struct
type BlockID struct {
tmtypes.BlockID
}
......@@ -51,8 +51,7 @@ func (blockID BlockID) String() string {
return Fmt(`%v`, blockID.Hash)
}
//-----------------------------------------------------------------------------
//TendermintBlock
//TendermintBlock struct
type TendermintBlock struct {
*tmtypes.TendermintBlock
}
......@@ -186,12 +185,10 @@ func (b *TendermintBlock) StringIndented(indent string) string {
func (b *TendermintBlock) StringShort() string {
if b == nil {
return "nil-Block"
} else {
return Fmt("Block#%v", b.Hash())
}
return Fmt("Block#%v", b.Hash())
}
//-----------------------------------------------------------------------------
// Header defines the structure of a Tendermint block header
// TODO: limit header size
// NOTE: changes to the Header should be duplicated in the abci Header
......@@ -247,8 +244,7 @@ func (h *Header) StringIndented(indent string) string {
indent, h.Hash())
}
//-----------------------------------------------------------------------------
//Commit
// Commit struct
type Commit struct {
*tmtypes.TendermintCommit
......@@ -393,21 +389,21 @@ func (commit *Commit) StringIndented(indent string) string {
indent, commit.hash)
}
//-----------------------------------------------------------------------------
// SignedHeader is a header along with the commits that prove it
type SignedHeader struct {
Header *Header `json:"header"`
Commit *Commit `json:"commit"`
}
//-----------------------------------------------------------------------------
// EvidenceEnvelope ...
type EvidenceEnvelope struct {
*tmtypes.EvidenceEnvelope
}
// EvidenceData contains any evidence of malicious wrong-doing by validators
// EvidenceEnvelopeList contains any evidence of malicious wrong-doing by validators
type EvidenceEnvelopeList []EvidenceEnvelope
// Hash ...
func (env EvidenceEnvelope) Hash() []byte {
penv := env.EvidenceEnvelope
evidence := EvidenceEnvelope2Evidence(penv)
......@@ -464,6 +460,7 @@ func (evl EvidenceEnvelopeList) Has(evidence Evidence) bool {
return false
}
// EvidenceData ...
type EvidenceData struct {
*tmtypes.EvidenceData
hash []byte
......
......@@ -23,6 +23,7 @@ type ErrEvidenceInvalid struct {
ErrorValue error
}
// NewEvidenceInvalidErr ...
func NewEvidenceInvalidErr(ev Evidence, err error) *ErrEvidenceInvalid {
return &ErrEvidenceInvalid{ev, err}
}
......@@ -39,8 +40,11 @@ const (
MockBad = "MockBad"
)
var EvidenceType2Type map[string]reflect.Type
var EvidenceType2Obj map[string]Evidence
// EvidenceType map define
var (
EvidenceType2Type map[string]reflect.Type
EvidenceType2Obj map[string]Evidence
)
// Evidence represents any provable malicious activity by a validator
type Evidence interface {
......@@ -205,22 +209,27 @@ func (dve *DuplicateVoteEvidence) Equal(ev Evidence) bool {
return bytes.Equal(SimpleHashFromBinary(dve), SimpleHashFromBinary(ev.(*DuplicateVoteEvidence)))
}
// TypeName ...
func (dve *DuplicateVoteEvidence) TypeName() string {
return DuplicateVote
}
// Copy ...
func (dve *DuplicateVoteEvidence) Copy() Evidence {
return &DuplicateVoteEvidence{}
}
// SetChild ...
func (dve *DuplicateVoteEvidence) SetChild(child proto.Message) {
dve.DuplicateVoteEvidence = child.(*tmtypes.DuplicateVoteEvidence)
}
// Child ...
func (dve *DuplicateVoteEvidence) Child() proto.Message {
return dve.DuplicateVoteEvidence
}
// SimpleHashFromBinary ...
func SimpleHashFromBinary(item *DuplicateVoteEvidence) []byte {
bytes, e := json.Marshal(item)
if e != nil {
......@@ -231,6 +240,7 @@ func SimpleHashFromBinary(item *DuplicateVoteEvidence) []byte {
}
// EvidenceEnvelope2Evidence ...
func EvidenceEnvelope2Evidence(envelope *tmtypes.EvidenceEnvelope) Evidence {
if v, ok := EvidenceType2Type[envelope.TypeName]; ok {
realMsg2 := reflect.New(v).Interface()
......@@ -247,69 +257,98 @@ func EvidenceEnvelope2Evidence(envelope *tmtypes.EvidenceEnvelope) Evidence {
return nil
}
//-----------------------------------------------------------------
// UNSTABLE
// MockGoodEvidence UNSTABLE
type MockGoodEvidence struct {
Height_ int64
Address_ []byte
Index_ int
MGHeight int64
MGAddress []byte
MGIndex int
}
// UNSTABLE
// NewMockGoodEvidence UNSTABLE
func NewMockGoodEvidence(height int64, index int, address []byte) MockGoodEvidence {
return MockGoodEvidence{height, address, index}
}
func (e MockGoodEvidence) Height() int64 { return e.Height_ }
func (e MockGoodEvidence) Address() []byte { return e.Address_ }
func (e MockGoodEvidence) Index() int { return e.Index_ }
// Height ...
func (e MockGoodEvidence) Height() int64 { return e.MGHeight }
// Address ...
func (e MockGoodEvidence) Address() []byte { return e.MGAddress }
// Index ...
func (e MockGoodEvidence) Index() int { return e.MGIndex }
// Hash ...
func (e MockGoodEvidence) Hash() []byte {
return []byte(Fmt("%d-%d", e.Height_, e.Index_))
return []byte(Fmt("%d-%d", e.MGHeight, e.MGIndex))
}
// Verify ...
func (e MockGoodEvidence) Verify(chainID string) error { return nil }
// Equal ...
func (e MockGoodEvidence) Equal(ev Evidence) bool {
e2 := ev.(MockGoodEvidence)
return e.Height_ == e2.Height_ &&
bytes.Equal(e.Address_, e2.Address_) &&
e.Index_ == e2.Index_
return e.MGHeight == e2.MGHeight &&
bytes.Equal(e.MGAddress, e2.MGAddress) &&
e.MGIndex == e2.MGIndex
}
func (e MockGoodEvidence) String() string {
return Fmt("GoodEvidence: %d/%s/%d", e.Height_, e.Address_, e.Index_)
return Fmt("GoodEvidence: %d/%s/%d", e.MGHeight, e.MGAddress, e.MGIndex)
}
// TypeName ...
func (e MockGoodEvidence) TypeName() string {
return MockGood
}
// Copy ...
func (e MockGoodEvidence) Copy() Evidence {
return &MockGoodEvidence{}
}
// SetChild ...
func (e MockGoodEvidence) SetChild(proto.Message) {}
// Child ...
func (e MockGoodEvidence) Child() proto.Message {
return nil
}
// UNSTABLE
// MockBadEvidence UNSTABLE
type MockBadEvidence struct {
MockGoodEvidence
}
// Verify ...
func (e MockBadEvidence) Verify(chainID string) error { return fmt.Errorf("MockBadEvidence") }
// Equal ...
func (e MockBadEvidence) Equal(ev Evidence) bool {
e2 := ev.(MockBadEvidence)
return e.Height_ == e2.Height_ &&
bytes.Equal(e.Address_, e2.Address_) &&
e.Index_ == e2.Index_
return e.MGHeight == e2.MGHeight &&
bytes.Equal(e.MGAddress, e2.MGAddress) &&
e.MGIndex == e2.MGIndex
}
func (e MockBadEvidence) String() string {
return Fmt("BadEvidence: %d/%s/%d", e.Height_, e.Address_, e.Index_)
return Fmt("BadEvidence: %d/%s/%d", e.MGHeight, e.MGAddress, e.MGIndex)
}
// TypeName ...
func (e MockBadEvidence) TypeName() string {
return MockBad
}
// Copy ...
func (e MockBadEvidence) Copy() Evidence {
return &MockBadEvidence{}
}
// SetChild ...
func (e MockBadEvidence) SetChild(proto.Message) {}
// Child ...
func (e MockBadEvidence) Child() proto.Message {
return nil
}
......@@ -325,11 +364,16 @@ type EvidencePool interface {
Update(*TendermintBlock)
}
// MockMempool is an empty implementation of a Mempool, useful for testing.
// MockEvidencePool is an empty implementation of a Mempool, useful for testing.
// UNSTABLE
type MockEvidencePool struct {
}
// PendingEvidence ...
func (m MockEvidencePool) PendingEvidence() []Evidence { return nil }
// AddEvidence ...
func (m MockEvidencePool) AddEvidence(Evidence) error { return nil }
// Update ...
func (m MockEvidencePool) Update(*TendermintBlock) {}
......@@ -12,6 +12,7 @@ import (
tmtypes "github.com/33cn/plugin/plugin/dapp/valnode/types"
)
// RoundVoteSet ...
type RoundVoteSet struct {
Prevotes *VoteSet
Precommits *VoteSet
......@@ -31,6 +32,8 @@ peer to prevent abuse.
We let each peer provide us with up to 2 unexpected "catchup" rounds.
One for their LastCommit round, and another for the official commit round.
*/
// HeightVoteSet ...
type HeightVoteSet struct {
chainID string
height int64
......@@ -42,6 +45,7 @@ type HeightVoteSet struct {
peerCatchupRounds map[string][]int // keys: peer.Key; values: at most 2 rounds
}
// NewHeightVoteSet ...
func NewHeightVoteSet(chainID string, height int64, valSet *ValidatorSet) *HeightVoteSet {
hvs := &HeightVoteSet{
chainID: chainID,
......@@ -50,6 +54,7 @@ func NewHeightVoteSet(chainID string, height int64, valSet *ValidatorSet) *Heigh
return hvs
}
// Reset ...
func (hvs *HeightVoteSet) Reset(height int64, valSet *ValidatorSet) {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
......@@ -63,19 +68,21 @@ func (hvs *HeightVoteSet) Reset(height int64, valSet *ValidatorSet) {
hvs.round = 0
}
// Height ...
func (hvs *HeightVoteSet) Height() int64 {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
return hvs.height
}
// Round ...
func (hvs *HeightVoteSet) Round() int {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
return hvs.round
}
// Create more RoundVoteSets up to round.
// SetRound Create more RoundVoteSets up to round.
func (hvs *HeightVoteSet) SetRound(round int) {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
......@@ -104,7 +111,7 @@ func (hvs *HeightVoteSet) addRound(round int) {
}
}
// Duplicate votes return added=false, err=nil.
// AddVote Duplicate votes return added=false, err=nil.
// By convention, peerKey is "" if origin is self.
func (hvs *HeightVoteSet) AddVote(vote *Vote, peerID string) (added bool, err error) {
hvs.mtx.Lock()
......@@ -132,19 +139,21 @@ func (hvs *HeightVoteSet) AddVote(vote *Vote, peerID string) (added bool, err er
return
}
// Prevotes ...
func (hvs *HeightVoteSet) Prevotes(round int) *VoteSet {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
return hvs.getVoteSet(round, VoteTypePrevote)
}
// Precommits ...
func (hvs *HeightVoteSet) Precommits(round int) *VoteSet {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
return hvs.getVoteSet(round, VoteTypePrecommit)
}
// Last round and blockID that has +2/3 prevotes for a particular block or nil.
// POLInfo Last round and blockID that has +2/3 prevotes for a particular block or nil.
// Returns -1 if no such round exists.
func (hvs *HeightVoteSet) POLInfo() (polRound int, polBlockID BlockID) {
hvs.mtx.Lock()
......@@ -159,18 +168,18 @@ func (hvs *HeightVoteSet) POLInfo() (polRound int, polBlockID BlockID) {
return -1, BlockID{}
}
func (hvs *HeightVoteSet) getVoteSet(round int, type_ byte) *VoteSet {
func (hvs *HeightVoteSet) getVoteSet(round int, voteType byte) *VoteSet {
rvs, ok := hvs.roundVoteSets[round]
if !ok {
return nil
}
switch type_ {
switch voteType {
case VoteTypePrevote:
return rvs.Prevotes
case VoteTypePrecommit:
return rvs.Precommits
default:
panic(Fmt("Panicked on a Sanity Check: %v", Fmt("Unexpected vote type %X", type_)))
panic(Fmt("Panicked on a Sanity Check: %v", Fmt("Unexpected vote type %X", voteType)))
}
}
......@@ -178,6 +187,7 @@ func (hvs *HeightVoteSet) String() string {
return hvs.StringIndented("")
}
// StringIndented ...
func (hvs *HeightVoteSet) StringIndented(indent string) string {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
......@@ -207,17 +217,17 @@ func (hvs *HeightVoteSet) StringIndented(indent string) string {
indent)
}
// If a peer claims that it has 2/3 majority for given blockKey, call this.
// SetPeerMaj23 If a peer claims that it has 2/3 majority for given blockKey, call this.
// NOTE: if there are too many peers, or too much peer churn,
// this can cause memory issues.
// TODO: implement ability to remove peers too
func (hvs *HeightVoteSet) SetPeerMaj23(round int, type_ byte, peerID string, blockID *tmtypes.BlockID) {
func (hvs *HeightVoteSet) SetPeerMaj23(round int, voteType byte, peerID string, blockID *tmtypes.BlockID) {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
if !IsVoteTypeValid(type_) {
if !IsVoteTypeValid(voteType) {
return
}
voteSet := hvs.getVoteSet(round, type_)
voteSet := hvs.getVoteSet(round, voteType)
if voteSet == nil {
return
}
......
......@@ -82,7 +82,7 @@ func DefaultBlockGossip() BlockGossip {
}
}
// DefaultEvidence Params returns a default EvidenceParams.
// DefaultEvidenceParams returns a default EvidenceParams.
func DefaultEvidenceParams() EvidenceParams {
return EvidenceParams{
MaxAge: 100000, // 27.8 hrs at 1block/s
......
......@@ -22,6 +22,7 @@ var (
pvFile = "priv_validator_"
)
// KeyFileCmd ...
func KeyFileCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "keyfile",
......@@ -34,6 +35,7 @@ func KeyFileCmd() *cobra.Command {
return cmd
}
// CreateCmd ...
func CreateCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create",
......@@ -49,6 +51,7 @@ func addCreateCmdFlags(cmd *cobra.Command) {
cmd.MarkFlagRequired("num")
}
// RandStr ...
func RandStr(length int) string {
chars := []byte{}
MAIN_LOOP:
......
......@@ -12,16 +12,15 @@ import (
tmtypes "github.com/33cn/plugin/plugin/dapp/valnode/types"
)
//-----------------------------------------------------------------------------
// RoundStepType enum type
// RoundStepType enumerates the state of the consensus state machine
type RoundStepType uint8 // These must be numeric, ordered.
var (
// MsgMap define
MsgMap map[byte]reflect.Type
)
// step and message id define
const (
RoundStepNewHeight = RoundStepType(0x01) // Wait til CommitTime + timeoutCommit
RoundStepNewRound = RoundStepType(0x02) // Setup new round and go to RoundStepPropose
......@@ -49,6 +48,7 @@ const (
PacketTypePong = byte(0xfe)
)
// InitMessageMap ...
func InitMessageMap() {
MsgMap = map[byte]reflect.Type{
EvidenceListID: reflect.TypeOf(tmtypes.EvidenceData{}),
......@@ -114,6 +114,7 @@ type RoundState struct {
LastValidators *ValidatorSet
}
// RoundStateMessage ...
func (rs *RoundState) RoundStateMessage() *tmtypes.NewRoundStepMsg {
return &tmtypes.NewRoundStepMsg{
Height: rs.Height,
......@@ -164,7 +165,7 @@ func (rs *RoundState) StringShort() string {
rs.Height, rs.Round, rs.Step, rs.StartTime)
}
//---------------------PeerRoundState----------------------------
// PeerRoundState ...
type PeerRoundState struct {
Height int64 // Height peer is at
Round int // Round peer is at, -1 if unknown.
......@@ -211,16 +212,20 @@ func (prs PeerRoundState) StringIndented(indent string) string {
}
//---------------------Canonical json-----------------------------------
// CanonicalJSONBlockID ...
type CanonicalJSONBlockID struct {
Hash []byte `json:"hash,omitempty"`
PartsHeader CanonicalJSONPartSetHeader `json:"parts,omitempty"`
}
// CanonicalJSONPartSetHeader ...
type CanonicalJSONPartSetHeader struct {
Hash []byte `json:"hash"`
Total int `json:"total"`
}
// CanonicalJSONProposal ...
type CanonicalJSONProposal struct {
BlockBytes []byte `json:"block_parts_header"`
Height int64 `json:"height"`
......@@ -230,6 +235,7 @@ type CanonicalJSONProposal struct {
Timestamp string `json:"timestamp"`
}
// CanonicalJSONVote ...
type CanonicalJSONVote struct {
BlockID CanonicalJSONBlockID `json:"block_id"`
Height int64 `json:"height"`
......@@ -238,6 +244,7 @@ type CanonicalJSONVote struct {
Type byte `json:"type"`
}
// CanonicalJSONHeartbeat ...
type CanonicalJSONHeartbeat struct {
Height int64 `json:"height"`
Round int `json:"round"`
......@@ -246,33 +253,36 @@ type CanonicalJSONHeartbeat struct {
ValidatorIndex int `json:"validator_index"`
}
//------------------------------------
// Messages including a "chain id" can only be applied to one chain, hence "Once"
// CanonicalJSONOnceProposal ...
type CanonicalJSONOnceProposal struct {
ChainID string `json:"chain_id"`
Proposal CanonicalJSONProposal `json:"proposal"`
}
// CanonicalJSONOnceVote ...
type CanonicalJSONOnceVote struct {
ChainID string `json:"chain_id"`
Vote CanonicalJSONVote `json:"vote"`
}
// CanonicalJSONOnceHeartbeat ...
type CanonicalJSONOnceHeartbeat struct {
ChainID string `json:"chain_id"`
Heartbeat CanonicalJSONHeartbeat `json:"heartbeat"`
}
//-----------------------------------
// Canonicalize the structs
// CanonicalBlockID ...
func CanonicalBlockID(blockID BlockID) CanonicalJSONBlockID {
return CanonicalJSONBlockID{
Hash: blockID.Hash,
}
}
// CanonicalProposal ...
func CanonicalProposal(proposal *Proposal) CanonicalJSONProposal {
return CanonicalJSONProposal{
//BlockBytes: proposal.BlockBytes,
......@@ -286,6 +296,7 @@ func CanonicalProposal(proposal *Proposal) CanonicalJSONProposal {
}
}
// CanonicalVote ...
func CanonicalVote(vote *Vote) CanonicalJSONVote {
return CanonicalJSONVote{
BlockID: CanonicalJSONBlockID{Hash: vote.BlockID.Hash},
......@@ -296,6 +307,7 @@ func CanonicalVote(vote *Vote) CanonicalJSONVote {
}
}
// CanonicalHeartbeat ...
func CanonicalHeartbeat(heartbeat *Heartbeat) CanonicalJSONHeartbeat {
return CanonicalJSONHeartbeat{
heartbeat.Height,
......@@ -306,6 +318,7 @@ func CanonicalHeartbeat(heartbeat *Heartbeat) CanonicalJSONHeartbeat {
}
}
// CanonicalTime ...
func CanonicalTime(t time.Time) string {
// note that sending time over go-wire resets it to
// local time, we need to force UTC here, so the
......
......@@ -17,6 +17,7 @@ import (
tmtypes "github.com/33cn/plugin/plugin/dapp/valnode/types"
)
// error defines
var (
ErrVoteUnexpectedStep = errors.New("Unexpected step")
ErrVoteInvalidValidatorIndex = errors.New("Invalid validator index")
......@@ -44,7 +45,6 @@ func SignBytes(chainID string, o Signable) []byte {
return buf.Bytes()
}
//----------------------Proposal----------------------
// Proposal defines a block proposal for the consensus.
// It refers to the block only by its PartSetHeader.
// It must be signed by the correct proposer for the given Height/Round
......@@ -89,12 +89,12 @@ func (p *Proposal) WriteSignBytes(chainID string, w io.Writer, n *int, err *erro
*err = e
return
}
n_, err_ := w.Write(byteOnceProposal)
*n = n_
*err = err_
number, writeErr := w.Write(byteOnceProposal)
*n = number
*err = writeErr
}
//-------------------heartbeat-------------------------
// Heartbeat ...
type Heartbeat struct {
*tmtypes.Heartbeat
}
......@@ -114,12 +114,12 @@ func (heartbeat *Heartbeat) WriteSignBytes(chainID string, w io.Writer, n *int,
*err = e
return
}
n_, err_ := w.Write(byteHeartbeat)
*n = n_
*err = err_
number, writeErr := w.Write(byteHeartbeat)
*n = number
*err = writeErr
}
//----------------------vote-----------------------------
// ErrVoteConflictingVotes ...
type ErrVoteConflictingVotes struct {
*DuplicateVoteEvidence
}
......@@ -133,6 +133,7 @@ func (err *ErrVoteConflictingVotes) Error() string {
return fmt.Sprintf("Conflicting votes from validator %v", addr)
}
// NewConflictingVoteError ...
func NewConflictingVoteError(val *Validator, voteA, voteB *tmtypes.Vote) *ErrVoteConflictingVotes {
keyString := fmt.Sprintf("%X", val.PubKey)
return &ErrVoteConflictingVotes{
......@@ -153,8 +154,9 @@ const (
VoteTypePrecommit = byte(0x02)
)
func IsVoteTypeValid(type_ byte) bool {
switch type_ {
// IsVoteTypeValid ...
func IsVoteTypeValid(voteType byte) bool {
switch voteType {
case VoteTypePrevote:
return true
case VoteTypePrecommit:
......@@ -164,11 +166,12 @@ func IsVoteTypeValid(type_ byte) bool {
}
}
// Represents a prevote, precommit, or commit vote from validators for consensus.
// Vote Represents a prevote, precommit, or commit vote from validators for consensus.
type Vote struct {
*tmtypes.Vote
}
// WriteSignBytes ...
func (vote *Vote) WriteSignBytes(chainID string, w io.Writer, n *int, err *error) {
if *err != nil {
return
......@@ -183,11 +186,12 @@ func (vote *Vote) WriteSignBytes(chainID string, w io.Writer, n *int, err *error
votelog.Error("vote WriteSignBytes marshal failed", "err", e)
return
}
n_, err_ := w.Write(byteVote)
*n = n_
*err = err_
number, writeErr := w.Write(byteVote)
*n = number
*err = writeErr
}
// Copy ...
func (vote *Vote) Copy() *Vote {
voteCopy := *vote
return &voteCopy
......@@ -214,6 +218,7 @@ func (vote *Vote) String() string {
CanonicalTime(time.Unix(0, vote.Timestamp)))
}
// Verify ...
func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
addr := GenAddressByPubKey(pubKey)
if !bytes.Equal(addr, vote.ValidatorAddress) {
......@@ -232,6 +237,7 @@ func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
return nil
}
// Hash ...
func (vote *Vote) Hash() []byte {
if vote == nil {
//votelog.Error("vote hash is nil")
......
......@@ -22,6 +22,7 @@ import (
)
const (
// RFC3339Millis ...
RFC3339Millis = "2006-01-02T15:04:05.000Z" // forced microseconds
timeFormat = RFC3339Millis
)
......@@ -29,9 +30,11 @@ const (
var (
randgen *rand.Rand
randMux sync.Mutex
// Fmt ...
Fmt = fmt.Sprintf
)
// Init ...
func Init() {
if randgen == nil {
randMux.Lock()
......@@ -40,10 +43,12 @@ func Init() {
}
}
// WriteFile ...
func WriteFile(filePath string, contents []byte, mode os.FileMode) error {
return ioutil.WriteFile(filePath, contents, mode)
}
// WriteFileAtomic ...
func WriteFileAtomic(filePath string, newBytes []byte, mode os.FileMode) error {
dir := filepath.Dir(filePath)
f, err := ioutil.TempFile(dir, "")
......@@ -70,7 +75,7 @@ func WriteFileAtomic(filePath string, newBytes []byte, mode os.FileMode) error {
return err
}
//----------------------------------------------------------
// Tempfile ...
func Tempfile(prefix string) (*os.File, string) {
file, err := ioutil.TempFile("", prefix)
if err != nil {
......@@ -79,12 +84,14 @@ func Tempfile(prefix string) (*os.File, string) {
return file, file.Name()
}
// Fingerprint ...
func Fingerprint(slice []byte) []byte {
fingerprint := make([]byte, 6)
copy(fingerprint, slice)
return fingerprint
}
// Kill ...
func Kill() error {
p, err := os.FindProcess(os.Getpid())
if err != nil {
......@@ -93,12 +100,13 @@ func Kill() error {
return p.Signal(syscall.SIGTERM)
}
// Exit ...
func Exit(s string) {
fmt.Printf(s + "\n")
os.Exit(1)
}
//-----------------------------------------------------------
// Parallel ...
func Parallel(tasks ...func()) {
var wg sync.WaitGroup
wg.Add(len(tasks))
......@@ -114,6 +122,7 @@ func Parallel(tasks ...func()) {
// Percent represents a percentage in increments of 1/1000th of a percent.
type Percent uint32
// Float ...
func (p Percent) Float() float64 {
return float64(p) * 1e-3
}
......@@ -127,14 +136,14 @@ func (p Percent) String() string {
return string(append(b, '%'))
}
//-------------------------------------------------------------------
// MinInt ...
func MinInt(a, b int) int {
if a < b {
return a
}
return b
}
// MaxInt ...
func MaxInt(a, b int) int {
if a > b {
return a
......@@ -142,7 +151,7 @@ func MaxInt(a, b int) int {
return b
}
//--------------------------------------------------------------
// RandIntn ...
func RandIntn(n int) int {
if n <= 0 {
panic("invalid argument to Intn")
......@@ -159,6 +168,7 @@ func RandIntn(n int) int {
return int(i64)
}
// RandUint32 ...
func RandUint32() uint32 {
randMux.Lock()
u32 := randgen.Uint32()
......@@ -166,6 +176,7 @@ func RandUint32() uint32 {
return u32
}
// RandInt63n ...
func RandInt63n(n int64) int64 {
randMux.Lock()
i64 := randgen.Int63n(n)
......@@ -173,26 +184,28 @@ func RandInt63n(n int64) int64 {
return i64
}
//-------------------------------------------------------------
// PanicSanity ...
func PanicSanity(v interface{}) {
panic(Fmt("Panicked on a Sanity Check: %v", v))
}
// PanicCrisis ...
func PanicCrisis(v interface{}) {
panic(Fmt("Panicked on a Crisis: %v", v))
}
// PanicQ ...
func PanicQ(v interface{}) {
panic(Fmt("Panicked questionably: %v", v))
}
//--------------------BitArray------------------------
// BitArray ...
type BitArray struct {
*tmtypes.TendermintBitArray
mtx sync.Mutex
}
// There is no BitArray whose Size is 0. Use nil instead.
// NewBitArray There is no BitArray whose Size is 0. Use nil instead.
func NewBitArray(bits int) *BitArray {
if bits <= 0 {
return nil
......@@ -205,6 +218,7 @@ func NewBitArray(bits int) *BitArray {
}
}
// Size ...
func (bA *BitArray) Size() int {
if bA == nil {
return 0
......@@ -212,7 +226,7 @@ func (bA *BitArray) Size() int {
return int(bA.Bits)
}
// NOTE: behavior is undefined if i >= bA.Bits
// GetIndex NOTE: behavior is undefined if i >= bA.Bits
func (bA *BitArray) GetIndex(i int) bool {
if bA == nil {
return false
......@@ -229,7 +243,7 @@ func (bA *BitArray) getIndex(i int) bool {
return bA.Elems[i/64]&(uint64(1)<<uint(i%64)) > 0
}
// NOTE: behavior is undefined if i >= bA.Bits
// SetIndex NOTE: behavior is undefined if i >= bA.Bits
func (bA *BitArray) SetIndex(i int, v bool) bool {
if bA == nil {
return false
......@@ -251,6 +265,7 @@ func (bA *BitArray) setIndex(i int, v bool) bool {
return true
}
// Copy ...
func (bA *BitArray) Copy() *BitArray {
if bA == nil {
return nil
......@@ -280,7 +295,7 @@ func (bA *BitArray) copyBits(bits int) *BitArray {
}
}
// Returns a BitArray of larger bits size.
// Or Returns a BitArray of larger bits size.
func (bA *BitArray) Or(o *BitArray) *BitArray {
if bA == nil && o.TendermintBitArray == nil {
return nil
......@@ -300,7 +315,7 @@ func (bA *BitArray) Or(o *BitArray) *BitArray {
return c
}
// Returns a BitArray of smaller bit size.
// And Returns a BitArray of smaller bit size.
func (bA *BitArray) And(o *BitArray) *BitArray {
if bA == nil || o.TendermintBitArray == nil {
return nil
......@@ -318,6 +333,7 @@ func (bA *BitArray) and(o *BitArray) *BitArray {
return c
}
// Not ...
func (bA *BitArray) Not() *BitArray {
if bA == nil {
return nil // Degenerate
......@@ -331,6 +347,7 @@ func (bA *BitArray) Not() *BitArray {
return c
}
// Sub ...
func (bA *BitArray) Sub(o *BitArray) *BitArray {
if bA == nil || o.TendermintBitArray == nil {
return nil
......@@ -354,6 +371,7 @@ func (bA *BitArray) Sub(o *BitArray) *BitArray {
return bA.and(o.Not()) // Note degenerate case where o == nil
}
// IsEmpty ...
func (bA *BitArray) IsEmpty() bool {
if bA == nil {
return true // should this be opposite?
......@@ -368,6 +386,7 @@ func (bA *BitArray) IsEmpty() bool {
return true
}
// IsFull ...
func (bA *BitArray) IsFull() bool {
if bA == nil {
return true
......@@ -388,6 +407,7 @@ func (bA *BitArray) IsFull() bool {
return (lastElem+1)&((uint64(1)<<uint(lastElemBits))-1) == 0
}
// PickRandom ...
func (bA *BitArray) PickRandom() (int, bool) {
if bA == nil {
return 0, false
......@@ -440,6 +460,7 @@ func (bA *BitArray) String() string {
return bA.stringIndented("")
}
// StringIndented ...
func (bA *BitArray) StringIndented(indent string) string {
if bA == nil {
return "nil-BitArray"
......@@ -476,6 +497,7 @@ func (bA *BitArray) stringIndented(indent string) string {
return fmt.Sprintf("BA{%v:%v}", bA.Bits, strings.Join(lines, indent))
}
// Bytes ...
func (bA *BitArray) Bytes() []byte {
bA.mtx.Lock()
defer bA.mtx.Unlock()
......@@ -490,7 +512,7 @@ func (bA *BitArray) Bytes() []byte {
return bytes
}
// NOTE: other bitarray o is not locked when reading,
// Update NOTE: other bitarray o is not locked when reading,
// so if necessary, caller must copy or lock o prior to calling Update.
// If bA is nil, does nothing.
func (bA *BitArray) Update(o *BitArray) {
......@@ -503,12 +525,12 @@ func (bA *BitArray) Update(o *BitArray) {
}
//------------------Heap----------------------
// Comparable ...
type Comparable interface {
Less(o interface{}) bool
}
//-----------------------------------------------------------------------------
/*
Example usage:
h := NewHeap()
......@@ -522,22 +544,27 @@ Example usage:
fmt.Println(h.Pop())
*/
// Heap ...
type Heap struct {
pq priorityQueue
}
// NewHeap ...
func NewHeap() *Heap {
return &Heap{pq: make([]*pqItem, 0)}
}
// Len ...
func (h *Heap) Len() int64 {
return int64(len(h.pq))
}
// Push ...
func (h *Heap) Push(value interface{}, priority Comparable) {
heap.Push(&h.pq, &pqItem{value: value, priority: priority})
}
// Peek ...
func (h *Heap) Peek() interface{} {
if len(h.pq) == 0 {
return nil
......@@ -545,10 +572,12 @@ func (h *Heap) Peek() interface{} {
return h.pq[0].value
}
// Update ...
func (h *Heap) Update(value interface{}, priority Comparable) {
h.pq.Update(h.pq[0], value, priority)
}
// Pop ...
func (h *Heap) Pop() interface{} {
item := heap.Pop(&h.pq).(*pqItem)
return item.value
......
......@@ -19,6 +19,7 @@ import (
var validatorsetlog = log15.New("module", "tendermint-val")
// Validator ...
type Validator struct {
Address []byte `json:"address"`
PubKey []byte `json:"pub_key"`
......@@ -27,6 +28,7 @@ type Validator struct {
Accum int64 `json:"accum"`
}
// NewValidator ...
func NewValidator(pubKey crypto.PubKey, votingPower int64) *Validator {
return &Validator{
Address: GenAddressByPubKey(pubKey),
......@@ -36,14 +38,14 @@ func NewValidator(pubKey crypto.PubKey, votingPower int64) *Validator {
}
}
// Creates a new copy of the validator so we can mutate accum.
// Copy Creates a new copy of the validator so we can mutate accum.
// Panics if the validator is nil.
func (v *Validator) Copy() *Validator {
vCopy := *v
return &vCopy
}
// Returns the one with higher Accum.
// CompareAccum Returns the one with higher Accum.
func (v *Validator) CompareAccum(other *Validator) *Validator {
if v == nil {
return other
......@@ -105,6 +107,7 @@ type ValidatorSet struct {
totalVotingPower int64
}
// NewValidatorSet ...
func NewValidatorSet(vals []*Validator) *ValidatorSet {
validators := make([]*Validator, len(vals))
for i, val := range vals {
......@@ -122,7 +125,7 @@ func NewValidatorSet(vals []*Validator) *ValidatorSet {
return vs
}
// incrementAccum and update the proposer
// IncrementAccum incrementAccum and update the proposer
// TODO: mind the overflow when times and votingPower shares too large.
func (valSet *ValidatorSet) IncrementAccum(times int) {
// Add VotingPower * times to each validator and order into heap.
......@@ -143,6 +146,7 @@ func (valSet *ValidatorSet) IncrementAccum(times int) {
}
}
// Copy ...
func (valSet *ValidatorSet) Copy() *ValidatorSet {
validators := make([]*Validator, len(valSet.Validators))
for i, val := range valSet.Validators {
......@@ -156,6 +160,7 @@ func (valSet *ValidatorSet) Copy() *ValidatorSet {
}
}
// HasAddress ...
func (valSet *ValidatorSet) HasAddress(address []byte) bool {
idx := sort.Search(len(valSet.Validators), func(i int) bool {
return bytes.Compare(address, valSet.Validators[i].Address) <= 0
......@@ -163,15 +168,15 @@ func (valSet *ValidatorSet) HasAddress(address []byte) bool {
return idx != len(valSet.Validators) && bytes.Equal(valSet.Validators[idx].Address, address)
}
// GetByAddress ...
func (valSet *ValidatorSet) GetByAddress(address []byte) (index int, val *Validator) {
idx := sort.Search(len(valSet.Validators), func(i int) bool {
return bytes.Compare(address, valSet.Validators[i].Address) <= 0
})
if idx != len(valSet.Validators) && bytes.Equal(valSet.Validators[idx].Address, address) {
return idx, valSet.Validators[idx].Copy()
} else {
return -1, nil
}
return -1, nil
}
// GetByIndex returns the validator by index.
......@@ -185,10 +190,12 @@ func (valSet *ValidatorSet) GetByIndex(index int) (address []byte, val *Validato
return val.Address, val.Copy()
}
// Size ...
func (valSet *ValidatorSet) Size() int {
return len(valSet.Validators)
}
// TotalVotingPower ...
func (valSet *ValidatorSet) TotalVotingPower() int64 {
if valSet.totalVotingPower == 0 {
for _, val := range valSet.Validators {
......@@ -198,6 +205,7 @@ func (valSet *ValidatorSet) TotalVotingPower() int64 {
return valSet.totalVotingPower
}
// GetProposer ...
func (valSet *ValidatorSet) GetProposer() (proposer *Validator) {
if len(valSet.Validators) == 0 {
return nil
......@@ -218,6 +226,7 @@ func (valSet *ValidatorSet) findProposer() *Validator {
return proposer
}
// Hash ...
func (valSet *ValidatorSet) Hash() []byte {
if len(valSet.Validators) == 0 {
return nil
......@@ -229,6 +238,7 @@ func (valSet *ValidatorSet) Hash() []byte {
return merkle.GetMerkleRoot(hashables)
}
// Add ...
func (valSet *ValidatorSet) Add(val *Validator) (added bool) {
val = val.Copy()
idx := sort.Search(len(valSet.Validators), func(i int) bool {
......@@ -255,39 +265,40 @@ func (valSet *ValidatorSet) Add(val *Validator) (added bool) {
}
}
// Update ...
func (valSet *ValidatorSet) Update(val *Validator) (updated bool) {
index, sameVal := valSet.GetByAddress(val.Address)
if sameVal == nil {
return false
} else {
valSet.Validators[index] = val.Copy()
// Invalidate cache
valSet.Proposer = nil
valSet.totalVotingPower = 0
return true
}
valSet.Validators[index] = val.Copy()
// Invalidate cache
valSet.Proposer = nil
valSet.totalVotingPower = 0
return true
}
// Remove ...
func (valSet *ValidatorSet) Remove(address []byte) (val *Validator, removed bool) {
idx := sort.Search(len(valSet.Validators), func(i int) bool {
return bytes.Compare(address, valSet.Validators[i].Address) <= 0
})
if idx == len(valSet.Validators) || !bytes.Equal(valSet.Validators[idx].Address, address) {
return nil, false
} else {
removedVal := valSet.Validators[idx]
newValidators := valSet.Validators[:idx]
if idx+1 < len(valSet.Validators) {
newValidators = append(newValidators, valSet.Validators[idx+1:]...)
}
valSet.Validators = newValidators
// Invalidate cache
valSet.Proposer = nil
valSet.totalVotingPower = 0
return removedVal, true
}
removedVal := valSet.Validators[idx]
newValidators := valSet.Validators[:idx]
if idx+1 < len(valSet.Validators) {
newValidators = append(newValidators, valSet.Validators[idx+1:]...)
}
valSet.Validators = newValidators
// Invalidate cache
valSet.Proposer = nil
valSet.totalVotingPower = 0
return removedVal, true
}
// Iterate ...
func (valSet *ValidatorSet) Iterate(fn func(index int, val *Validator) bool) {
for i, val := range valSet.Validators {
stop := fn(i, val.Copy())
......@@ -297,7 +308,7 @@ func (valSet *ValidatorSet) Iterate(fn func(index int, val *Validator) bool) {
}
}
// Verify that +2/3 of the set had signed the given signBytes
// VerifyCommit Verify that +2/3 of the set had signed the given signBytes
func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height int64, commit *Commit) error {
if valSet.Size() != len(commit.Precommits) {
return fmt.Errorf("Invalid commit -- wrong set size: %v vs %v", valSet.Size(), len(commit.Precommits))
......@@ -350,10 +361,9 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height
if talliedVotingPower > valSet.TotalVotingPower()*2/3 {
return nil
} else {
return fmt.Errorf("Invalid commit -- insufficient voting power: got %v, needed %v",
talliedVotingPower, (valSet.TotalVotingPower()*2/3 + 1))
}
return fmt.Errorf("Invalid commit -- insufficient voting power: got %v, needed %v",
talliedVotingPower, (valSet.TotalVotingPower()*2/3 + 1))
}
// VerifyCommitAny will check to see if the set would
......@@ -453,6 +463,7 @@ func (valSet *ValidatorSet) String() string {
return valSet.StringIndented("")
}
// StringIndented ...
func (valSet *ValidatorSet) StringIndented(indent string) string {
if valSet == nil {
return "nil-ValidatorSet"
......@@ -474,9 +485,9 @@ func (valSet *ValidatorSet) StringIndented(indent string) string {
}
//-------------------------------------
// Implements sort for sorting validators by address.
// ValidatorsByAddress ...
type ValidatorsByAddress []*Validator
func (vs ValidatorsByAddress) Len() int {
......
......@@ -11,6 +11,9 @@ import (
func (val *ValNode) ExecDelLocal_Node(node *pty.ValNode, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
set := &types.LocalDBSet{}
if receipt.GetTy() != types.ExecOk {
return set, nil
}
key := CalcValNodeUpdateHeightIndexKey(val.GetHeight(), index)
set.KV = append(set.KV, &types.KeyValue{Key: key, Value: nil})
return set, nil
......@@ -18,6 +21,9 @@ func (val *ValNode) ExecDelLocal_Node(node *pty.ValNode, tx *types.Transaction,
func (val *ValNode) ExecDelLocal_BlockInfo(blockInfo *pty.TendermintBlockInfo, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
set := &types.LocalDBSet{}
if receipt.GetTy() != types.ExecOk {
return set, nil
}
key := CalcValNodeBlockInfoHeightKey(val.GetHeight())
set.KV = append(set.KV, &types.KeyValue{Key: key, Value: nil})
return set, nil
......
......@@ -13,6 +13,9 @@ import (
func (val *ValNode) ExecLocal_Node(node *pty.ValNode, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
set := &types.LocalDBSet{}
if receipt.GetTy() != types.ExecOk {
return set, nil
}
if len(node.GetPubKey()) == 0 {
return nil, errors.New("validator pubkey is empty")
}
......@@ -27,6 +30,9 @@ func (val *ValNode) ExecLocal_Node(node *pty.ValNode, tx *types.Transaction, rec
func (val *ValNode) ExecLocal_BlockInfo(blockInfo *pty.TendermintBlockInfo, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
set := &types.LocalDBSet{}
if receipt.GetTy() != types.ExecOk {
return set, nil
}
key := CalcValNodeBlockInfoHeightKey(val.GetHeight())
set.KV = append(set.KV, &types.KeyValue{Key: key, Value: types.Encode(blockInfo)})
return set, nil
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment