mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-24 18:21:38 +00:00
Add dump_consensus_state rpc command. Made it a little more secure
by moving the PrivValidator out of RoundState.
This commit is contained in:
@ -187,7 +187,6 @@ type RoundState struct {
|
|||||||
Precommits *VoteSet
|
Precommits *VoteSet
|
||||||
Commits *VoteSet
|
Commits *VoteSet
|
||||||
LastCommits *VoteSet
|
LastCommits *VoteSet
|
||||||
PrivValidator *sm.PrivValidator
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RoundState) String() string {
|
func (rs *RoundState) String() string {
|
||||||
@ -241,6 +240,7 @@ type ConsensusState struct {
|
|||||||
|
|
||||||
blockStore *bc.BlockStore
|
blockStore *bc.BlockStore
|
||||||
mempoolReactor *mempl.MempoolReactor
|
mempoolReactor *mempl.MempoolReactor
|
||||||
|
privValidator *sm.PrivValidator
|
||||||
runActionCh chan RoundAction
|
runActionCh chan RoundAction
|
||||||
newStepCh chan *RoundState
|
newStepCh chan *RoundState
|
||||||
|
|
||||||
@ -492,8 +492,12 @@ func (cs *ConsensusState) updateToState(state *sm.State, contiguous bool) {
|
|||||||
cs.Round = 0
|
cs.Round = 0
|
||||||
cs.Step = RoundStepNewHeight
|
cs.Step = RoundStepNewHeight
|
||||||
if cs.CommitTime.IsZero() {
|
if cs.CommitTime.IsZero() {
|
||||||
|
// "Now" makes it easier to sync up dev nodes.
|
||||||
|
// We add newHeightDelta to allow transactions
|
||||||
|
// to be gathered for the first block.
|
||||||
|
// And alternative solution that relies on clocks:
|
||||||
// cs.StartTime = state.LastBlockTime.Add(newHeightDelta)
|
// cs.StartTime = state.LastBlockTime.Add(newHeightDelta)
|
||||||
cs.StartTime = time.Now() // Makes it easier to sync up dev nodes.
|
cs.StartTime = time.Now().Add(newHeightDelta)
|
||||||
} else {
|
} else {
|
||||||
cs.StartTime = cs.CommitTime.Add(newHeightDelta)
|
cs.StartTime = cs.CommitTime.Add(newHeightDelta)
|
||||||
}
|
}
|
||||||
@ -523,12 +527,12 @@ func (cs *ConsensusState) updateToState(state *sm.State, contiguous bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we've timed out, then send rebond tx.
|
// If we've timed out, then send rebond tx.
|
||||||
if cs.PrivValidator != nil && cs.state.UnbondingValidators.HasAddress(cs.PrivValidator.Address) {
|
if cs.privValidator != nil && cs.state.UnbondingValidators.HasAddress(cs.privValidator.Address) {
|
||||||
rebondTx := &types.RebondTx{
|
rebondTx := &types.RebondTx{
|
||||||
Address: cs.PrivValidator.Address,
|
Address: cs.privValidator.Address,
|
||||||
Height: cs.Height + 1,
|
Height: cs.Height + 1,
|
||||||
}
|
}
|
||||||
err := cs.PrivValidator.SignRebondTx(rebondTx)
|
err := cs.privValidator.SignRebondTx(rebondTx)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Info("Signed and broadcast RebondTx", "height", cs.Height, "round", cs.Round, "tx", rebondTx)
|
log.Info("Signed and broadcast RebondTx", "height", cs.Height, "round", cs.Round, "tx", rebondTx)
|
||||||
cs.mempoolReactor.BroadcastTx(rebondTx)
|
cs.mempoolReactor.BroadcastTx(rebondTx)
|
||||||
@ -567,7 +571,7 @@ func (cs *ConsensusState) setupNewRound(round uint) {
|
|||||||
func (cs *ConsensusState) SetPrivValidator(priv *sm.PrivValidator) {
|
func (cs *ConsensusState) SetPrivValidator(priv *sm.PrivValidator) {
|
||||||
cs.mtx.Lock()
|
cs.mtx.Lock()
|
||||||
defer cs.mtx.Unlock()
|
defer cs.mtx.Unlock()
|
||||||
cs.PrivValidator = priv
|
cs.privValidator = priv
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -600,14 +604,14 @@ func (cs *ConsensusState) RunActionPropose(height uint, round uint) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Nothing to do if it's not our turn.
|
// Nothing to do if it's not our turn.
|
||||||
if cs.PrivValidator == nil {
|
if cs.privValidator == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !bytes.Equal(cs.Validators.Proposer().Address, cs.PrivValidator.Address) {
|
if !bytes.Equal(cs.Validators.Proposer().Address, cs.privValidator.Address) {
|
||||||
log.Debug("Not our turn to propose", "proposer", cs.Validators.Proposer().Address, "privValidator", cs.PrivValidator)
|
log.Debug("Not our turn to propose", "proposer", cs.Validators.Proposer().Address, "privValidator", cs.privValidator)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
log.Debug("Our turn to propose", "proposer", cs.Validators.Proposer().Address, "privValidator", cs.PrivValidator)
|
log.Debug("Our turn to propose", "proposer", cs.Validators.Proposer().Address, "privValidator", cs.privValidator)
|
||||||
}
|
}
|
||||||
|
|
||||||
var block *types.Block
|
var block *types.Block
|
||||||
@ -675,7 +679,7 @@ func (cs *ConsensusState) RunActionPropose(height uint, round uint) {
|
|||||||
|
|
||||||
// Make proposal
|
// Make proposal
|
||||||
proposal := NewProposal(cs.Height, cs.Round, blockParts.Header(), polParts.Header())
|
proposal := NewProposal(cs.Height, cs.Round, blockParts.Header(), polParts.Header())
|
||||||
err := cs.PrivValidator.SignProposal(proposal)
|
err := cs.privValidator.SignProposal(proposal)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Info("Signed and set proposal", "height", cs.Height, "round", cs.Round, "proposal", proposal)
|
log.Info("Signed and set proposal", "height", cs.Height, "round", cs.Round, "proposal", proposal)
|
||||||
log.Debug(Fmt("Signed and set proposal block: %v", block))
|
log.Debug(Fmt("Signed and set proposal block: %v", block))
|
||||||
@ -1061,7 +1065,7 @@ func (cs *ConsensusState) stageBlock(block *types.Block, blockParts *types.PartS
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header types.PartSetHeader) *types.Vote {
|
func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header types.PartSetHeader) *types.Vote {
|
||||||
if cs.PrivValidator == nil || !cs.Validators.HasAddress(cs.PrivValidator.Address) {
|
if cs.privValidator == nil || !cs.Validators.HasAddress(cs.privValidator.Address) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
vote := &types.Vote{
|
vote := &types.Vote{
|
||||||
@ -1071,10 +1075,10 @@ func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header types.Part
|
|||||||
BlockHash: hash,
|
BlockHash: hash,
|
||||||
BlockParts: header,
|
BlockParts: header,
|
||||||
}
|
}
|
||||||
err := cs.PrivValidator.SignVote(vote)
|
err := cs.privValidator.SignVote(vote)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Info("Signed and added vote", "height", cs.Height, "round", cs.Round, "vote", vote)
|
log.Info("Signed and added vote", "height", cs.Height, "round", cs.Round, "vote", vote)
|
||||||
cs.addVote(cs.PrivValidator.Address, vote)
|
cs.addVote(cs.privValidator.Address, vote)
|
||||||
return vote
|
return vote
|
||||||
} else {
|
} else {
|
||||||
log.Warn("Error signing vote", "height", cs.Height, "round", cs.Round, "vote", vote, "error", err)
|
log.Warn("Error signing vote", "height", cs.Height, "round", cs.Round, "vote", vote, "error", err)
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/tendermint/tendermint/binary"
|
||||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
sm "github.com/tendermint/tendermint/state"
|
sm "github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
func ListValidators() (*ctypes.ResponseListValidators, error) {
|
func ListValidators() (*ctypes.ResponseListValidators, error) {
|
||||||
var blockHeight uint
|
var blockHeight uint
|
||||||
var bondedValidators []*sm.Validator
|
var bondedValidators []*sm.Validator
|
||||||
@ -25,3 +24,8 @@ func ListValidators() (*ctypes.ResponseListValidators, error) {
|
|||||||
|
|
||||||
return &ctypes.ResponseListValidators{blockHeight, bondedValidators, unbondingValidators}, nil
|
return &ctypes.ResponseListValidators{blockHeight, bondedValidators, unbondingValidators}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DumpConsensusState() (*ctypes.ResponseDumpConsensusState, error) {
|
||||||
|
jsonBytes := binary.JSONBytes(consensusState.GetRoundState())
|
||||||
|
return &ctypes.ResponseDumpConsensusState{string(jsonBytes)}, nil
|
||||||
|
}
|
@ -2,7 +2,6 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
. "github.com/tendermint/tendermint/common"
|
|
||||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
"github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
|
@ -14,6 +14,7 @@ var Routes = map[string]*rpc.RPCFunc{
|
|||||||
"call": rpc.NewRPCFunc(Call, []string{"address", "data"}),
|
"call": rpc.NewRPCFunc(Call, []string{"address", "data"}),
|
||||||
"call_code": rpc.NewRPCFunc(CallCode, []string{"code", "data"}),
|
"call_code": rpc.NewRPCFunc(CallCode, []string{"code", "data"}),
|
||||||
"list_validators": rpc.NewRPCFunc(ListValidators, []string{}),
|
"list_validators": rpc.NewRPCFunc(ListValidators, []string{}),
|
||||||
|
"dump_consensus_state": rpc.NewRPCFunc(DumpConsensusState, []string{}),
|
||||||
"dump_storage": rpc.NewRPCFunc(DumpStorage, []string{"address"}),
|
"dump_storage": rpc.NewRPCFunc(DumpStorage, []string{"address"}),
|
||||||
"broadcast_tx": rpc.NewRPCFunc(BroadcastTx, []string{"tx"}),
|
"broadcast_tx": rpc.NewRPCFunc(BroadcastTx, []string{"tx"}),
|
||||||
"list_accounts": rpc.NewRPCFunc(ListAccounts, []string{}),
|
"list_accounts": rpc.NewRPCFunc(ListAccounts, []string{}),
|
||||||
|
@ -91,3 +91,7 @@ type ResponseListValidators struct {
|
|||||||
BondedValidators []*sm.Validator
|
BondedValidators []*sm.Validator
|
||||||
UnbondingValidators []*sm.Validator
|
UnbondingValidators []*sm.Validator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResponseDumpConsensusState struct {
|
||||||
|
ConsensusState string
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@ type Client interface {
|
|||||||
BroadcastTx(tx types.Tx) (*ctypes.ResponseBroadcastTx, error)
|
BroadcastTx(tx types.Tx) (*ctypes.ResponseBroadcastTx, error)
|
||||||
Call(address []byte, data []byte) (*ctypes.ResponseCall, error)
|
Call(address []byte, data []byte) (*ctypes.ResponseCall, error)
|
||||||
CallCode(code []byte, data []byte) (*ctypes.ResponseCall, error)
|
CallCode(code []byte, data []byte) (*ctypes.ResponseCall, error)
|
||||||
|
DumpConsensusState() (*ctypes.ResponseDumpConsensusState, error)
|
||||||
DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error)
|
DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error)
|
||||||
GenPrivAccount() (*ctypes.ResponseGenPrivAccount, error)
|
GenPrivAccount() (*ctypes.ResponseGenPrivAccount, error)
|
||||||
GetAccount(address []byte) (*ctypes.ResponseGetAccount, error)
|
GetAccount(address []byte) (*ctypes.ResponseGetAccount, error)
|
||||||
@ -150,6 +151,36 @@ func (c *ClientHTTP) CallCode(code []byte, data []byte) (*ctypes.ResponseCall, e
|
|||||||
return response.Result, nil
|
return response.Result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ClientHTTP) DumpConsensusState() (*ctypes.ResponseDumpConsensusState, error) {
|
||||||
|
values, err := argsToURLValues(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp, err := http.PostForm(c.addr+reverseFuncMap["DumpConsensusState"], values)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var response struct {
|
||||||
|
Result *ctypes.ResponseDumpConsensusState `json:"result"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
JSONRPC string `json:"jsonrpc"`
|
||||||
|
}
|
||||||
|
binary.ReadJSON(&response, body, &err)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.Error != "" {
|
||||||
|
return nil, fmt.Errorf(response.Error)
|
||||||
|
}
|
||||||
|
return response.Result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ClientHTTP) DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error) {
|
func (c *ClientHTTP) DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error) {
|
||||||
values, err := argsToURLValues([]string{"address"}, address)
|
values, err := argsToURLValues([]string{"address"}, address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -558,6 +589,33 @@ func (c *ClientJSON) CallCode(code []byte, data []byte) (*ctypes.ResponseCall, e
|
|||||||
return response.Result, nil
|
return response.Result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ClientJSON) DumpConsensusState() (*ctypes.ResponseDumpConsensusState, error) {
|
||||||
|
request := rpc.RPCRequest{
|
||||||
|
JSONRPC: "2.0",
|
||||||
|
Method: reverseFuncMap["DumpConsensusState"],
|
||||||
|
Params: []interface{}{},
|
||||||
|
Id: 0,
|
||||||
|
}
|
||||||
|
body, err := c.RequestResponse(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var response struct {
|
||||||
|
Result *ctypes.ResponseDumpConsensusState `json:"result"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
JSONRPC string `json:"jsonrpc"`
|
||||||
|
}
|
||||||
|
binary.ReadJSON(&response, body, &err)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.Error != "" {
|
||||||
|
return nil, fmt.Errorf(response.Error)
|
||||||
|
}
|
||||||
|
return response.Result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ClientJSON) DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error) {
|
func (c *ClientJSON) DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error) {
|
||||||
request := rpc.RPCRequest{
|
request := rpc.RPCRequest{
|
||||||
JSONRPC: "2.0",
|
JSONRPC: "2.0",
|
||||||
|
Reference in New Issue
Block a user